var WiiRemotes = new Array();
var PrimaryRemote = 0;
for(var i=0; i<4; i++) window.WiiRemotes[i] = new WiiRemote(i);

var Wii = 
{
    isWii: function() { return (navigator.platform == "Nintendo Wii"); },
    getRemote: function(id) { WiiRemotes[id].update(); return WiiRemotes[id]; },
    getPrimaryRemote: function() { WiiRemotes[PrimaryRemote].update(); return WiiRemotes[PrimaryRemote]; }
};

function WiiRemote(id)
{
    this.id = id;
    this.rotated = false;
    this.allowRotate = (navigator.platform == "Nintendo Wii"); //Wii.isWii();
    
    this.active = (id == 0);
    this.facing = true;
    this.x = 0;
    this.y = 0;
    this.dist = 0;
    this.twist = 0;
    
    this.listeners = new Object();
}

var proto = WiiRemote.prototype

proto.update = function()
{
    if(!window.opera || !opera.wiiremote) return;
    
    var remote = opera.wiiremote.update(this.id);
    var old;
    var mask = 1;
    var buttonCode;
    
    old = this.active;
    this.active = remote.isEnabled;
    
    if(this.active != old)
    {
        if(this.active) this.dispatchEvent({type:"connected", identity: this.id});
        else this.dispatchEvent({type:"disconnected", identity: this.id});
    }
    
    //FIX ME: Is this right?
    if(!remote.isBrowsing) 
    {
        old = this.bitmap ^ remote.hold;
        this.bitmap = remote.hold;
     
        if(old > 0)
        {
            for(var i=0; i<15; i++)
            {
                buttonCode = mask;
                
                if(this.rotated && this.allowRotate)
                {
                    if(buttonCode == WiiRemote.BUTTON_UP) buttonCode = WiiRemote.BUTTON_LEFT;
                    else if(buttonCode == WiiRemote.BUTTON_RIGHT) buttonCode = WiiRemote.BUTTON_UP;
                    else if(buttonCode == WiiRemote.BUTTON_DOWN) buttonCode = WiiRemote.BUTTON_RIGHT;
                    else if(buttonCode == WiiRemote.BUTTON_LEFT) buttonCode = WiiRemote.BUTTON_DOWN;
                }
                
                if((mask & old) > 0) 
                {
                    if((remote.hold & mask) > 0) this.dispatchEvent(({type: "buttondown", buttonCode: buttonCode, identity: this.id}));
                    else this.dispatchEvent(({type: "buttonup", buttonCode: buttonCode, identity: this.id}));
                }
                
                mask <<= 1;
            }
        }
    }
    
    if(remote.dpdScreenX) 
    {
        this.facing = true;
        this.x = remote.dpdScreenX;
        this.y = remote.dpdScreenY;
    }
    else
    {
        this.facing = false;
    }
    
    if(remote.dpdDistance) this.dist = Math.floor(remote.dpdDistance * 100);
    if(remote.dpdRollX) this.twist = Math.floor((Math.atan2(remote.dpdRollY, remote.dpdRollX) * 180 / Math.PI));
    
    if(this.twist < 0) this.twist += 360;
    if(remote.isBrowsing) PrimaryRemote = this.id;
};;

proto.isDown = function(buttonCode) 
{
    if(this.rotated && this.allowRotate)
    {
        if(buttonCode == WiiRemote.BUTTON_UP) buttonCode = WiiRemote.BUTTON_RIGHT;
        else if(buttonCode == WiiRemote.BUTTON_RIGHT) buttonCode = WiiRemote.BUTTON_DOWN;
        else if(buttonCode == WiiRemote.BUTTON_DOWN) buttonCode = WiiRemote.BUTTON_LEFT;
        else if(buttonCode == WiiRemote.BUTTON_LEFT) buttonCode = WiiRemote.BUTTON_UP;
    }
	
    return (this.bitmap & buttonCode);
};

proto.addEventListener = function(type, listener)
{
    var listeners = this.listeners[type];
    
    if(!listeners) 
    {
        listeners = new Array();
        this.listeners[type] = listeners;
    }
    
    listeners[listeners.length] = listener;
};

proto.removeEventListener = function(type, listener)
{
    var listeners = this.listeners[type];
    var oldlisteners = listeners;
    var index = -1;
    
    if(!listeners) return;
    
    for(var i=0; i<listeners.length && index < 0; i++)
    {
        if(listeners[i] == listener) index = i;
    }
    
    if(index < 0) return;
    
    listeners = new Array();
    
    for(var i=0; i<oldlisteners.length; i++)
    {
        if(i != index) listeners[listeners.length] = oldlisteners[i];
    }
    
    this.listeners[type] = listeners;
};

proto.dispatchEvent = function(event)
{
    var listeners = this.listeners[event.type];
    
    if(!listeners)
    {
        return;
    }

    for(var i=0; i<listeners.length; i++)
    {
        listeners[i](event);
    }
};

proto.getIdentity = function() { return this.id; };
proto.isPrimary = function() { return (this.id == PrimaryRemote); };
proto.isConnected = function() { return this.active; };
proto.isRotated = function() { return this.rotated; };
proto.setRotated = function(rotate) { this.rotated = rotate; };
proto.getTwistAngle = function() { return this.twist; };
proto.getDistance = function() { return this.dist; };
proto.getCursorX = function() { return this.x; };
proto.getCursorY = function() { return this.y; };
proto.isFacingScreen = function() { return this.facing; };

WiiRemote.BUTTON_UP    = 0x008;
WiiRemote.BUTTON_DOWN  = 0x004;
WiiRemote.BUTTON_RIGHT = 0x002;
WiiRemote.BUTTON_LEFT  = 0x001;
WiiRemote.BUTTON_1     = 0x200;
WiiRemote.BUTTON_2     = 0x100;
WiiRemote.BUTTON_A     = 0x800;
WiiRemote.BUTTON_B     = 0x400;
WiiRemote.BUTTON_PLUS  = 0x010;
WiiRemote.BUTTON_MINUS = 0x1000;

function Nunchuk(parent)
{
    this.parent = parent;
    this.stickx = 0;
    this.sticky = 0;
}

proto = Nunchuk.prototype;

proto.isDown = function(buttonCode) 
{
    return (this.parent.bitmap & buttonCode);
};

proto.getStickX = function() {return this.stickx;}
proto.getStickY = function() {return this.sticky;}

Nunchuk.BUTTON_C = 0x4000;
Nunchuk.BUTTON_Z = 0x2000;

if(window.proto) delete(proto);

var KeyboardController = 
{
    keyMappings: {},
    buttonMappings: {},
    wiiMappings: {},
    getButtonMappingForKey: function(keyCode) { return this.keyMappings[keyCode]; },
    getKeyMappingForButton: function(buttonCode) { return this.buttonMappings[buttonCode]; },
    setKeyMapping: function(buttonCode, keyCode) 
    {
        var origKeyCode = this.buttonMappings[buttonCode];
        var origButtonCode = this.keyMappings[keyCode];
        
        if(origKeyCode) this.keyMappings[origKeyCode] = null;
        if(origButtonCode) this.buttonMappings[origButtonCode] = null;

        this.keyMappings[keyCode] = buttonCode;
        this.buttonMappings[buttonCode] = keyCode;
    }
};

var kc = KeyboardController;
var wr = WiiRemote;

function tr(buttonCode, wiimote)
{
    if(wiimote.rotated && wiimote.allowRotate)
    {
        if(buttonCode == WiiRemote.BUTTON_UP) buttonCode = WiiRemote.BUTTON_LEFT;
        else if(buttonCode == WiiRemote.BUTTON_RIGHT) buttonCode = WiiRemote.BUTTON_UP;
        else if(buttonCode == WiiRemote.BUTTON_DOWN) buttonCode = WiiRemote.BUTTON_RIGHT;
        else if(buttonCode == WiiRemote.BUTTON_LEFT) buttonCode = WiiRemote.BUTTON_DOWN;
    }
    
    return buttonCode;
}

function kd(event)
{
    var wiimote = WiiRemotes[PrimaryRemote];
    var bit;
    
    if(Wii.isWii()) bit = KeyboardController.wiiMappings[event.keyCode];
    else bit = KeyboardController.keyMappings[event.keyCode]
    
    wiimote.bitmap |= bit;
    wiimote.dispatchEvent(({type: "buttondown", buttonCode: tr(bit, wiimote), identity: PrimaryRemote}));
}

function ku(event)
{
    var wiimote = WiiRemotes[PrimaryRemote];
    var bit;
    
    if(Wii.isWii()) bit = KeyboardController.wiiMappings[event.keyCode];
    else bit = KeyboardController.keyMappings[event.keyCode];
        
    wiimote.bitmap &= ~bit;
    wiimote.dispatchEvent(({type: "buttonup", buttonCode: tr(bit, wiimote), identity: PrimaryRemote}));
}

function kp(event)
{
    var bit;
    
    if(Wii.isWii()) bit = KeyboardController.wiiMappings[event.keyCode];
    else bit = KeyboardController.keyMappings[event.keyCode];
        
    if(Browser.enabledKeys[bit] != true)
    {
        event.preventDefault();
        event.stopPropagation();
    }
}

if(document.addEventListener)
{
    document.addEventListener("keydown", kd, false);
    document.addEventListener("keyup", ku, false);
    document.addEventListener("keypress", kp, false);
}
else
{
    document.attachEvent("onkeydown", kd);
    document.attachEvent("onkeyup", ku);
    document.attachEvent("onkeypress", kp);
}

kc.keyMappings[37]  = wr.BUTTON_LEFT;
kc.keyMappings[38]  = wr.BUTTON_UP;
kc.keyMappings[39]  = wr.BUTTON_RIGHT;
kc.keyMappings[40]  = wr.BUTTON_DOWN;
kc.keyMappings[65]  = wr.BUTTON_1;
kc.keyMappings[83]  = wr.BUTTON_2;
kc.keyMappings[68]  = wr.BUTTON_A;
kc.keyMappings[32]  = wr.BUTTON_B;
kc.keyMappings[187] = wr.BUTTON_PLUS;
kc.keyMappings[189] = wr.BUTTON_MINUS;

kc.buttonMappings[wr.BUTTON_LEFT]  = 37;
kc.buttonMappings[wr.BUTTON_UP]    = 38;
kc.buttonMappings[wr.BUTTON_RIGHT] = 39;
kc.buttonMappings[wr.BUTTON_DOWN]  = 40;
kc.buttonMappings[wr.BUTTON_1]     = 65;
kc.buttonMappings[wr.BUTTON_2]     = 83;
kc.buttonMappings[wr.BUTTON_A]     = 68;
kc.buttonMappings[wr.BUTTON_B]     = 32;
kc.buttonMappings[wr.BUTTON_PLUS]  = 187;
kc.buttonMappings[wr.BUTTON_MINUS] = 189;

kc.wiiMappings[178] = wr.BUTTON_LEFT;
kc.wiiMappings[177] = wr.BUTTON_RIGHT;
kc.wiiMappings[175] = wr.BUTTON_UP;
kc.wiiMappings[176] = wr.BUTTON_DOWN;
kc.wiiMappings[13]  = wr.BUTTON_A;
kc.wiiMappings[171] = wr.BUTTON_B;
kc.wiiMappings[172] = wr.BUTTON_1;
kc.wiiMappings[173] = wr.BUTTON_2;
kc.wiiMappings[174] = wr.BUTTON_PLUS;
kc.wiiMappings[170] = wr.BUTTON_MINUS;
                      
delete kc;
delete wr;
delete kd;
delete ku;
delete kp;

var Browser =
{
    HEXCODES: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'],
    enabledKeys: {},
    setBackgroundColor: function(color)
    {
        var htmlcolor = "";
        
        for(var i=0; i<6; i++)
        {
            htmlcolor = this.HEXCODES[(color & 0x0F)] + htmlcolor;
            
            color >>>= 4;
        }
        
        if(document.firstChild) document.firstChild.style.background = "#"+htmlcolor;
        if(document.body) document.body.style.background = "#"+htmlcolor;
    },
    isDefaultEnabled: function(buttonCode)
    {
        return (this.enabledKeys[buttonCode] == true);
    },
    setDefaultEnabled: function(buttonCode, enabled)
    {
        this.enabledKeys[buttonCode] = enabled;
    },
    enableZooming: function()
    {
        this.setDefaultEnabled(WiiRemote.BUTTON_PLUS, true);
        this.setDefaultEnabled(WiiRemote.BUTTON_MINUS, true);
    },
    disableZooming: function()
    {
        this.setDefaultEnabled(WiiRemote.BUTTON_PLUS, false);
        this.setDefaultEnabled(WiiRemote.BUTTON_MINUS, false);
    },
    enableScrolling: function()
    {
        this.setDefaultEnabled(WiiRemote.BUTTON_LEFT, true);
        this.setDefaultEnabled(WiiRemote.BUTTON_UP, true);
        this.setDefaultEnabled(WiiRemote.BUTTON_RIGHT, true);
        this.setDefaultEnabled(WiiRemote.BUTTON_DOWN, true);
        this.setDefaultEnabled(WiiRemote.BUTTON_B, true);
    },
    disableScrolling: function()
    {
        this.setDefaultEnabled(WiiRemote.BUTTON_LEFT, false);
        this.setDefaultEnabled(WiiRemote.BUTTON_UP, false);
        this.setDefaultEnabled(WiiRemote.BUTTON_RIGHT, false);
        this.setDefaultEnabled(WiiRemote.BUTTON_DOWN, false);
        this.setDefaultEnabled(WiiRemote.BUTTON_B, false);
    }
};
