
var GunControl = new Class({

	Extends: WebService,
	
    initialize: function (options) {
    	this.parent(options);
    	
    	this.validateControl();
    	
        this.timer = new Timer();        
        this.onTickHandler = jQuery.proxy(this.onTick, this);
        //this.onLockTimeOverHandler = jQuery.proxy(this.onLockTimeOver, this);
        
        this.onBeforeResetHandler = jQuery.proxy(this.onBeforeReset, this);
        this.onBeforeFireHandler = jQuery.proxy(this.onBeforeFire, this);
        this.onBeforeMoveHandler = jQuery.proxy(this.onBeforeMove, this);
        this.onGunCmdSuccessHandler = jQuery.proxy(this.onGunCmdSuccess, this);
        this.onGunCmdErrorHandler = jQuery.proxy(this.onGunCmdError, this);

        this.gunModes = {locked:0, available:1, exclusive:2};
        this.requestModes = {shot:'shot', moreTime:'takeMoreTime', aiming:'aiming', owner:'owner'};
        
        this.controller = new KeyboardController('services/aim.html');
        this.controller.addEvent('beforeReset', this.onBeforeResetHandler);
        this.controller.addEvent('beforeFire', this.onBeforeFireHandler);
        this.controller.addEvent('beforeMove', this.onBeforeMoveHandler);
        this.controller.addEvent('commandSuccess', this.onGunCmdSuccessHandler);
        this.controller.addEvent('commandError', this.onGunCmdErrorHandler);
        
        this.setGunState(this.options);
    },
    
    //
    // Public Methods
    //
    
    validateControl: function() {
    	var element = $(this.options.aimTimeId)
    	if (!element || element.length == 0) {
    		throw ("Element with ID "+this.options.aimTimeId+" is not found.");
    	}
    	
    	element = $(this.options.moreTimeButtonId);
    	if (!element || element.length == 0) {
    		throw ("Element with ID "+this.options.moreTimeButtonId+" is not found.");
    	}

    	element = $(this.options.aimTimePanelId);
    	if (!element || element.length == 0) {
    		throw ("Element with ID "+this.options.aimTimePanelId+" is not found.");
    	}

    	element = $(this.options.controlledById);
    	if (!element || element.length == 0) {
    		throw ("Element with ID "+this.options.controlledById+" is not found.");
    	}
    	
    },
    
    isEnabled: function() {
        return (this.timer && this.timer.isStarted);
    },
    
    isLockedByUser: function(userId) {
        return this.currentGunMode == this.gunModes.locked && this.userId == userId;
    },
    
    lock: function(lockTimeout, owner) {
        this.visibleResetButton(false);
        this.visibleAimingTimer(false);
        this.visibleMoreTimeButton(false);
        var username = owner.fullname ? owner.fullname: owner.username;
        this.setControlledBy(username, owner.fbid);
        
        //this.controller.stop();
        this.controller.isMoveEnabled = false;
    },
    
    unlock: function() {
        this.timer.stop();
        this.visibleMoreTimeButton(false);
        
        this.setControlledBy('everyone');
        
        this.visibleAimingTimer(false);
        this.visibleResetButton(false);
        
        // by this we allow or disallow anyone control when gun is not locked
        this.controller.start();
        
        if (Application.userInfo.shots > 0) {
            Application.takeControlService.enableButton(true);
        }
    },
    
    tryStartController: function(){
    	if (this.currentGunMode == this.gunModes.exclusive) {
    		this.controller.start();
    	}
    },
    
    exclusive: function(exclusiveTimeout, owner) {
        this.visibleAimingTimer(true);
        this.setControlledBy('YOU', owner.fbid);
        this.visibleResetButton(true);
        this.visibleMoreTimeButton(false);
        Application.takeControlService.disableButton(false);
        // enable only after shot
        this.enableMoreTimeButton(true);
        this.setAimTime(exclusiveTimeout);
        this.timer.start(this.onTickHandler, 1); // each 1 second
        
        this.controller.start();
    },
    
    detectCurrentGunMode: function(options) {
        // 1 - already controlled by someone, disable control
        // 2 - controlling by current user, enabling control
        // 3 - by default available for all users except shooting and reset position
        if (options && options.id) {
            this.setOwnerId(options.id);
            
            if (options.id == Application.userInfo.userId) {
                this.currentGunMode = this.gunModes.exclusive;
            } else {
                this.currentGunMode = this.gunModes.locked;
            }
        } else {
            this.currentGunMode = this.gunModes.available;
        }
    },
    // entry point
    setGunState: function(userObj) {
        var owner = (userObj && userObj.owner) ? userObj.owner : userObj;
        this.detectCurrentGunMode(owner);
        
        switch(this.currentGunMode) {
            case this.gunModes.exclusive:
                var lockTime = this.timer.getLeftSeconds(owner.started, owner.aimTime);
                this.exclusive(lockTime, owner);
                break;
            case this.gunModes.locked:
                var lockTime = this.timer.getLeftSeconds(owner.started, owner.aimTime);
                this.lock(lockTime, owner);
                this.setOwnerId(owner.id);
                Application.takeControlService.enableButton(true);
                break;
            case this.gunModes.available:
                this.unlock();
                break;
        }
    },
    
    visibleAimingTimer: function(visible) {
        this.visibleElement(this.options.aimTimePanelId, visible);
    },
    
    visibleMoreTimeButton: function(visible) {
        this.visibleElement(this.options.moreTimeButtonId, visible);
    },
    
    setControlledBy: function(name, fbid) {
        var panel = $(this.options.controlledById);
        
        if(panel.length) {
            panel.html(name);
            var avaPanel = $(this.options.avaId);
            
            if (avaPanel.length && fbid) {
                var ava = avaPanel.children('img');
                
                if (ava.length) {
                    ava.attr('src', 'http://graph.facebook.com/' + fbid + '/picture')
                    ava.attr('alt', name);
                    avaPanel.show();
                }
            } else {
                avaPanel.hide();
            }
        } else {
        	throw ("Element with ID controlledByPanel is not found");
        }
    },
    
    visibleResetButton: function(visible) {
        this.controller.enableReset(visible);
    },
    
    enableMoreTimeButton: function(enable) {
        this.enableElement(this.options.moreTimeButtonId, enable);
    },
    
    enableShootButton: function(enable) {
        this.controller.enableFire(enable);
    },
    
    setOwnerId: function(userId) {
        this.userId = userId;
    },
    
    //
    // Send Ajax Requests
    //
    
    sendMoreTimeRquest: function() {
        try {
            if (sender.disabled != false) {
                this.mode = this.requestModes.moreTime;
                this.options.submitParams[this.options.actionName] = this.mode;
                this.enableMoreTimeButton(false);
                this.onRequest();
            }
        } catch (ex) {
            this.showAlert(ex.message);
        }
        
        return false;
    },
    
    /*
    * Get gun owner for the current moment
    */
    sendOwnerRequest: function() {
        try {
            this.mode = this.requestModes.owner;
            this.options.submitParams[this.options.actionName] = this.mode;
            this.onRequest();
        } catch (ex) {
            this.showAlert(ex.message);
        }
        
        return false;
    },
    
    getAimTime: function() {
        /*var element = $(this.options.aimTimeId);
        if (element) {
            var secondsLeft = parseInt(element.innerHTML);
        }*/
        var secondsLeft = $(this.options.aimTimeId).text();
        return parseInt(secondsLeft);
    },
    
    setAimTime: function(time) {
        /*var element = $(this.options.aimTimeId);
        if (element.length) {
            element.update(time);
        }*/
        
        $(this.options.aimTimeId).html(time);
    },
    
    //
    // Event Handlers
    //
    
	onBeforeReset: function(command) {
        if (this.currentGunMode == this.gunModes.locked) {
            this.controller.clearGunCommands();
        }
        
        this.mode = this.requestModes.aiming;
        return true;
	},
	
	onBeforeFire: function(command) {
/*
        if (this.currentGunMode == this.gunModes.locked) {
            this.controller.clearGunCommands();
        }
*/

        if (Application.userInfo.shots <= 0) {
            this.controller.clearGunCommands();
            this.onAimTimeOver();
        }
        
        this.mode = this.requestModes.aiming;
        return true;
	},
	
	onBeforeMove: function(command) {
        if (this.currentGunMode == this.gunModes.locked) {
                this.controller.clearGunCommands();
        }
        
        this.mode = this.requestModes.aiming;
        return true;
	},
	
	onGunCmdSuccess: function(data, textStatus) {
        switch(this.mode) {
            case this.requestModes.gun:
            case this.requestModes.shot:
            case this.requestModes.aiming:
                this.onSuccessShot(data);
                break;
        }
	},
	
	onGunCmdError: function(data, textStatus) {
        if (this.mode == this.requestModes.aiming || this.mode == this.requestModes.shot) {
            this.showMessage("Gun is not available now.");
            this.setMessageStyle(this.options.cssClassError);
        } else {
            this.__handleResponseMessages(data);
        }
	},
    
    onSuccess: function(responseObj) {
        // response has available shots count
        switch(this.mode) {
            case this.requestModes.moreTime:
                this.onSuccessMoreTime(responseObj);
                break;
            case this.requestModes.owner:
                this.onSuccessOwnerRquested(responseObj);
                break;
            default:
                this.showAlert('Unknown mode ' + this.mode);
        }
        
        if (!responseObj.success) {
            if (this.mode == this.requestModes.aiming || this.mode == this.requestModes.shot) {
                this.showMessage("Gun is not available now.");
                this.setMessageStyle(this.options.cssClassError);
            } else {
                this.__handleResponseMessages(responseObj);
            }
        }
    },
    
    onFailed: function(data, textStatus) { 
    	this.__handleResponseMessages(data);
    },
    
    onSuccessShot: function(responseObj) {
        if (responseObj.shots) {
            Application.userInfo.setShotsCount(responseObj.shots);
            if (Application.userInfo.shots > 0) {
                // show more time buton only once
                var moreBtn = $(this.options.moreTimeButtonId);
                //if (moreBtn.visible()) {
                if (moreBtn.length && moreBtn.is(":visible")) {
                    this.enableMoreTimeButton(true);
                }
            }
        }
        //else if (responseObj.success) {
        //    Application.userInfo.decrementShots();
        //}
    },
    
    onSuccessMoreTime: function(responseObj) {
        if(responseObj.addedSeconds) {
            // update timer
            var seconds = parseInt(responseObj.addedSeconds);
            var secondsLeft = this.getAimTime();
            secondsLeft += seconds;
            this.setAimTime(secondsLeft);
            
            // after more time got, hide the button
            this.visibleMoreTimeButton(false);
        }
    },
    
    onSuccessAiming: function(responseObj) {
        /*if (this.currentGunMode != this.gunModes.exclusive && responseObj.gunMode == this.gunModes.exclusive) {
            if ($.isArray(responseObj.users)) {
                Application.usersQueue.parseUsersData(responseObj.users);
            }
        }*/
    },
    
    onSuccessOwnerRquested: function(responseObj) {
        if (responseObj.owner == null || responseObj.owner.id == null) {
            this.unlock();
        } else {
            var lockTime = this.timer.getLeftSeconds(responseObj.owner.started, responseObj.owner.aimTime);
            this.lock(lockTime, responseObj.owner.username);
            this.setOwnerId(responseObj.owner.id);
        }
    },
    
    onTick: function() {
        this.onAimTimeTick();
    },

    onAimTimeTick: function(timer) {
    	var element = $(this.options.aimTimeId);
    	if (element.length > 0) {
	        var value = element.text();
	        if (value.length > 0) {
	            var secondsLeft = parseInt(value);
	            if (secondsLeft > 0) {
	                secondsLeft--;
	                element.html(secondsLeft);
	            } else {
	                this.onAimTimeOver();
	            }
            }
        } else {
            throw('Element with ID ' + this.options.aimTimeId + ' is not found.');
        }
    },

    /*onLockTimeOver: function() {
        this.timer.stop();
        //get state of gun from server
        // this.sendOwnerRequest();
    },*/
    
    onAimTimeOver: function() {
        this.timer.stop();
        Application.usersQueue.removeItemByUserId(this.userId);
    }
});
