/**
 * Control Class - handles all event actions, store, pause, resume, delete....
 * 
 */
var Control = new Class({
	/**
	 * @var Object
	 */
	elements : {},
	/**
	 * Constructor
	 */
	initialize : function() {
		//reset attributes
		this.elements = {};
		//init application
		this.loadElements();
	},
	/**
	 * main event handler for all events
	 *
	 * @param event eventObject element where event occours
	 * @param Hash params event parameter
	 *
	 * @return boolean breakEventChain return false for abort event flow
	 */
	eventHandler : function(eventObject, params) {
		switch (params.get('action')) {

		}
	},
	/**
	 * add key event
	 *
	 * @param Hash params event parameter
	 */
	addKeyEvent : function(params) {
		document.addEvent('keyup', this.eventHandler
				.bindWithEvent(this, params));
	},
	/**
	 * add normal event
	 *
	 * @param String eventType type of event (click, mouseover...)
	 * @param String / DOM-Element elementName element for the event
	 * @param Hash params parameter for event execution
	 */
	addEvent : function(eventType, elementName, params) {
		var eventElement = $(elementName);
		if (eventElement) {
			eventElement.addEvent(eventType, this.eventHandler.bindWithEvent(
					this, params));
		}
	},
	/**
	 * remove event from element
	 *
	 * @param String eventType
	 * @param String / DOM-Element elementName
	 */
	removeEvent : function(eventType, elementName, params) {
		var eventElement = $(elementName);
		if (eventElement) {
			eventElement.removeEvent(eventType, this.eventHandler
					.bindWithEvent(this, params));
		}
	},
	/**
	 * 
	 */
	formatNumber : function(seperator, number) {
		var numberToString = new String(number);
		var numberFormatted = '';
		counter = 0;
		for (i = numberToString.length - 1; i >= 0; i--) {
			if ((counter % 3) === 0 && counter !== 0) {
				numberFormatted = '.' + numberFormatted;
			}
			numberFormatted = numberToString.charAt(i) + numberFormatted;
			counter++;
		}
		return numberFormatted;
	}
});

/**
 * coreTimer
 * 
 * @author Paul Kreichauf
 */
var coreTimer = new Class({
	Extends : Control,
	lastStep : null,
	lastDelay : null,
	listener : [],
	initialize : function() {
		this.listener = [];
		this.step();
	},
	/**
	 * add a callback function for each step
	 *
	 * @param function callback
	 */
	addListener : function(callback) {
		if(callback) {
			this.listener.push(callback);
		}
	},
	/**
	 * do a step, fire step event, calc delay intervall
	 */
	step : function() {
		//call listener
		for(var i = 0; i < this.listener.length ; i++) {
			this.listener[i](this);
		}
		//set default delay to 1000 for first step
		var delay = 1000;
		var currentTime = new Date().getTime();
		//check if not first step
		if (this.lastStep !== null) {
			//calculate time between now and last call
			var timeDelta = currentTime - this.lastStep;
			//calculate new offset
			var offset = this.lastDelay - timeDelta;
			//set time for next call
			var delay = 1000 + offset;
		}
		//save current time and time for next call
		this.lastStep = new Date().getTime();
		this.lastDelay = delay;
		this.step.delay(this.lastDelay, this);
	}
});


var ZONE_EUROPE = 0;
var ZONE_AMERICA = 1;
var ZONE_ASIA = 2;
var ZONE_MIDDLE_EAST = 3;
var ZONE_AFRICA = 4;
var ZONE_OCEANIA = 5;


/**
 * Languagebar
 */
var LanguageBar = new Class({
	Extends : Control,
	/**
	 * value of current selected zone
	 * 
	 * @var Int
	 */
	selectedZone : null,
	/**
	 * callbacks
	 */
	onChangeZone : null,
	/**
	 * Constructor
	 */
	initialize : function() {
		//reset attributes
		this.selectedZone = 0;
		this.onChangeZone = null;
		//call parent constructor
		this.parent();
	},
	/**
     * handle all language bar events
     *
     * @param event eventObject
     * @param Hash params
     *
     * return boolean breakEventChain
     */
	eventHandler: function(eventObject, params) {
        //call parent eventHandler method
        this.parent(eventObject, params);
        //switch action
        switch (params.get('action')) {
            case 'change_zone':
            	if(this.elements.zone.select) {
	            	this.hideZoneFlags(this.selectedZone);
	            	this.setSelectedZone(this.elements.zone.select[this.elements.zone.select.selectedIndex].value);
	            	this.setSelectboxCaption(this.getSelectedZoneCaption());
	            	this.showZoneFlags(this.selectedZone);
	            	if(this.onChangeZone) {
	            		this.onChangeZone(this);
	            	}
            	}
				break;
        }
    },
    /**
     * hide the zone flags by zone id
     * 
     * @param int zoneId
     */
    hideZoneFlags : function(zoneId) {
    	if(this.elements.flags[zoneId]) {
    		this.elements.flags[zoneId].setStyle('display', 'none');
    	}
    },
    /**
     * show the zone flags by zone id
     * 
     * @param int zoneId
     */
    showZoneFlags : function(zoneId) {
    	if(this.elements.flags[zoneId]) {
    		this.elements.flags[zoneId].setStyle('display', 'block');
    	}
    },
    /**
     * show the zone select box
     */
    showZoneSelect : function() {
    	if(this.elements.zone.select) {
    		this.elements.zone.select.setStyle('display', 'block');
    	}
    },
    /**
     * hide the zone select box
     */
    hideZoneSelect : function() {
    	if(this.elements.zone.select) {
    		this.elements.zone.select.setStyle('display', 'none');
    	}
    },
    /**
     * get the caption from selected element from zone select
     * 
     * @return String zone
     */
    getSelectedZoneCaption : function() {
    	if(this.elements.zone.select && this.selectedZone !== null) {
	    	var zoneElement = this.elements.zone.select[this.elements.zone.select.selectedIndex];
	    	var zoneCaption = zoneElement.innerHTML;
	    	if(zoneCaption != '') {
	    		return zoneCaption;
	    	}
    	}
    	return 'undefined';
    },
    /**
     * set selected zone
     * 
     * @param int zoneId
     */
    setSelectedZone : function(zoneId) {
    	if(zoneId !== null) {
    		this.selectedZone = zoneId;
    	}
    },
    /**
     * update the select box caption
     * 
     * @param String caption
     */
    setSelectboxCaption : function(caption) {
    	if(this.elements.zone.caption && caption != '') {
    		this.elements.zone.caption.set('text', caption);
    	}
    },
	/**
	 * save dom elements to attribute elements
	 */
	loadElements : function() {
		//load select elements
		this.elements.zone = {
			'caption' : $('zoneCaption'),
			'select' : $('zoneSelect')
		};
		if(this.elements.zone.select && this.elements.zone.select[this.elements.zone.select.selectedIndex]) {
			this.setSelectedZone(this.elements.zone.select[this.elements.zone.select.selectedIndex].value);
			this.setSelectboxCaption(this.getSelectedZoneCaption());
			this.addEvent('change', this.elements.zone.select, $H({ action : 'change_zone' }));
			//load zones
			this.elements.flags = {};
			
			this.elements.zone.select.getElements('option').each(function(zone, key) {
				var zoneIndex = zone.get('value');
				//get flag container
				var flagContainer = $('flags_' + zoneIndex);
				//check if flag container exist
				if(flagContainer) {
					this.elements.flags[zoneIndex] = flagContainer;
				}
			}.bind(this));
		}
	}
});

/**
 * Gallery
 */
var Gallery = new Class({
	Extends : Control,
	/**
	 * array with images
	 * 
	 * @param Array
	 */
	images : [],
	/**
	 * path to images
	 * 
	 * @var String
	 */
	path : '/img/gallery/',
	/**
	 * handle attributes
	 */
	count : 0,
	current : 0,
	/**
	 * constructor
	 */
	initialize : function(images, path) {
		//call parent constructor
		this.parent();
		//set images
		this.images = images;
		this.count = this.images.length;
		this.current = 0;
		//check if path is set
		if(path !== null) {
			this.path = path;
		}
		//show first image
		this.showImage(this.current);
	},
	/**
     * handle all language bar events
     *
     * @param event eventObject
     * @param Hash params
     *
     * return boolean breakEventChain
     */
	eventHandler: function(eventObject, params) {
        //call parent eventHandler method
        this.parent(eventObject, params);
        //switch action
        switch (params.get('action')) {
            case 'move_prev':
            	if(this.current > 0) {
            		this.current--;
            		this.showImage(this.current);
            	}
            	if(this.current == 0) {
            		this.elements.navi.prev.addClass('disable');
            	}
            	else if(this.current == (this.count - 2)) {
            		this.elements.navi.next.removeClass('disable');
            	}
            	break;
            case 'move_next':
            	if(this.current < (this.count - 1)) {
            		this.current++;
            		this.showImage(this.current);
            	}
            	if(this.current == (this.count - 1)) {
            		this.elements.navi.next.addClass('disable');
            	}
            	else if(this.current == 1) {
            		this.elements.navi.prev.removeClass('disable');
            	}
            	break;
        }
        return false;
    },
    /**
     * show image by index
     * 
     * @param Int index
     */
    showImage : function(index) {
    	var image = this.images[index];
    	if(image) {
    		this.elements.image.set('src', this.path + image.name);
    		this.updatePosition(index);
    		this.updateDescription(image.desc);
    	}
    },
    /**
     * update the image description
     * 
     * @param String desc
     */
    updateDescription : function(desc) {
    	if(desc === '') {
    		desc = '&nbsp;';
    	}
    	this.elements.description.set('html', desc);
    },
    /**
     * update position area
     * 
     * @param Int index
     */
    updatePosition : function(index) {
    	this.elements.position.set('text', (index + 1) + ' / ' + this.count);
    },
	/**
	* load elements
	*/
	loadElements : function() {
		//image container
		this.elements.image = $('imageElement');
		//navigation
		this.elements.navi = {
			'prev' : $('naviPrev'),
			'next' : $('naviNext')
		};
		this.addEvent('click', this.elements.navi.prev, $H({ action : 'move_prev' }));
		this.addEvent('click', this.elements.navi.next, $H({ action : 'move_next' }));
		//position
		this.elements.position = $('imagePos');
		this.elements.description = $('imageDesc');
	}
});

/**
 * Login box
 */
var Login = new Class({
	Extends: Control,
	
	/**
	 * List of universes.
	 * 
	 * @var Array
	 */
	universes: null,
	
	/**
	 * Element id prefix.
	 * 
	 * @var String
	 */
	prefix: null,
	
	/**
	 * The app instance.
	 * 
	 * @var PortalApplication
	 */
	portal: null,
	
	/**
	 * main constructor; initializes the elements and event handlers.
	 * 
	 * @param Array universes The list of element ids.
	 * @param String prefix The id prefix.
	 * @param PortalApplication The app instance.
	 */
	initialize: function(universes, prefix, portal) {
		this.universes = universes;
		this.prefix = prefix;
		this.portal = portal;
		this.parent();
	},
	
	/**
	 * main event handler for all events
	 *
	 * @param event eventObject element where event occours
	 * @param Hash params event parameter
	 *
	 * @return boolean breakEventChain return false for abort event flow
	 */
	eventHandler : function(eventObject, params) {
		switch (params.get('action')) {
			case 'choose':
				this.portal.setSelectedUniverse(params.id, params.name, params.url);
			break;
		}
	},

	/**
	 * Initialize elements and event handlers.
	 */
	loadElements: function() {
		for(var id in this.universes) {
			var universe = this.universes[id];
			this.addEvent('click', this.prefix+id, $H({'action': 'choose', 'id': id, 'name': universe.name, 'url': universe.url}));
		}
	}
});

/**
 * Dialog Class
 */
var DialogHandler = new Class({
	Extends : Control,
	/**
	 * dialog prefix
	 * 
	 * @var String
	 */
	prefix : null,
	/**
	 * callbacks
	 */
	onCloseDialog : null,
	/**
	 * main constructor
	 * 
	 * @param String prefix Prefix of dialog container ids (content, close...)
	 */
	initialize : function(prefix) {
		if(prefix === null) {
			prefix = '';
		}
		this.prefix = prefix;
		//call parent constructor
		this.parent();
		//reset attributes
		this.onCloseDialog = null;
		this.onShowDialog = null;
	},
	/**
     * handle all language bar events
     *
     * @param event eventObject
     * @param Hash params
     *
     * return boolean breakEventChain
     */
	eventHandler: function(eventObject, params) {
        //call parent eventHandler method
        this.parent(eventObject, params);
        //switch action
        switch (params.get('action')) {
            case 'close_dialog':
            	this.hideDialog();
            	break;
            case 'eval_javascript':
            	eval(params.get('javascript'));
            	break;
        }
    },
    /**
     * set the dialog caption
     * 
     * @param String caption
     */
    setCaption : function(caption) {
    	this.elements.caption.set('text', caption);
    },
    /**
     * load content
     * 
     * @param String url
     */
    loadContent : function(url) {
    	if(url) {
    		var req = new Request.HTML({
                url: url,
    			data : {},
    			evalScripts : false,
    			evalResponse : false,
                onSuccess: function(responseTree, responseElements, responseHTML, responseJavaScript) {
    				this.elements.content.set('html', responseHTML);
    				this.addEvent('domready', this.elements.content, $H({ action : 'eval_javascript', javascript : responseJavaScript }));
                }.bind(this)
           }).send();
    	}
    },
    /**
     * set content
     * 
     * @param String content
     * @param String jsContent
     */
    setContent : function(content, jsContent) {
    	this.elements.content.set('html', content);
    	if(jsContent) {
    		this.addEvent('domready', this.elements.content, $H({ action : 'eval_javascript', javascript : jsContent }));
    	}
    },
    /**
     * show the dialog
     */
    showDialog : function() {
    	this.elements.container.setStyles({
    		'display' : 'block',
    		'top' : parseInt(document.documentElement.scrollTop + 100) + 'px'
    	});
    	if(this.onShowDialog) {
    		this.onShowDialog(this);
    	}
    },
    /**
     * hide the dialog
     */
    hideDialog : function() {
    	this.elements.content.removeEvents();
    	this.elements.content.empty();
    	this.elements.container.setStyle('display', 'none');
    	if(this.onCloseDialog) {
    		this.onCloseDialog(this);
    	}
    },
	/**
	 * load elements
	 */
	loadElements : function() {
		//load dialog container
		this.elements.container = $(this.prefix);
		//load content
		this.elements.content = $(this.prefix+'Content');
		this.elements.content.set('load');
		//load caption
		this.elements.caption = $(this.prefix+'Caption');
		//load close
		this.elements.close = $(this.prefix+'Close');
		this.addEvent('click', this.elements.close, $H({ action : 'close_dialog'}));
	}
});
/**
 * PortalApplication -
 */
var PortalApplication = new Class( {
	Extends : Control,
	/**
	 * @var LanguageBar>
	 */
	langBar : null,
	/**
	 * flag if black overlay already is shown or not
	 */
	blackOverlayVisible : null,
	/**
	 * dialogs
	 */
	dialogSmall : null,
	dialogBig : null,
	/**
	 * flags which indicates that user is at login form
	 */
	userAtLogin : false,
	submitFormCallback : null,
	/**
	 * @var Object
	 */
	urls : {},
	/**
	 * @var coreTimer
	 */
	timer : null,
	/**
	 * Constructor
	 */
	initialize : function(urls) {
		this.urls = {
			'showUniverse': '/start/showUniverse/',
			'register' : '/start/registerForm/',
			'activate' : '/start/activateForm/',
			'success' : '/start/success/',
			'screenshot' : '/start/screenshot/',
			'artwork' : '/start/artwork/',
			'imprint' : '/start/imprint/',
			'activation' : '/start/activate/',
			'transfer': '/start/transfer/'
		};
		if(urls) {
			for(var k in urls) {
				this.urls[k] = urls[k];
			}
		}
		//call parent constructor
		this.parent();
		//create lang bar
		this.langBar = new LanguageBar();
		//create core timer instance
		this.timer = new coreTimer();
		//set / reset attributes
		this.blackOverlayVisible = null;
		this.userAtLogin = false;
		this.submitFormCallback = null;
		
		this.dialogSmall = new DialogHandler('dialogSmall');
		this.dialogSmall.onShowDialog = this.showBlackOverlay.bind(this);
		this.dialogSmall.onCloseDialog = this.hideBlackOverlay.bind(this);
		this.dialogBig = new DialogHandler('dialogBig');
		this.dialogBig.onShowDialog = this.showBlackOverlay.bind(this);
		this.dialogBig.onCloseDialog = this.hideBlackOverlay.bind(this);
	},
	/**
     * handle all language bar events
     *
     * @param event eventObject
     * @param Hash params
     *
     * return boolean breakEventChain
     */
	eventHandler: function(eventObject, params) {
        //call parent eventHandler method
        this.parent(eventObject, params);
        //switch action
        switch (params.get('action')) {
            case 'show_dialog':
            	this.dialogSmall.loadContent(params.get('url'));
            	this.dialogSmall.setCaption(params.get('caption'));
            	this.dialogSmall.showDialog();
            	break;
            case 'show_big_dialog':
            	this.dialogBig.loadContent(params.get('url'));
            	this.dialogBig.setCaption(params.get('caption'));
            	this.dialogBig.showDialog();
            	break;
            case 'close_overlay':
            	this.hideBlackOverlay();
            	break;
            case 'submit_login':
            	this.elements.login.form.submit();
            	return false;
            	break;
            case 'submit_form_with_enter':
            	/*
            	if(eventObject.key == 'enter' && params.get('submitForm')) {
            		if(params.get('submitCallback')) {
            			params.get('submitCallback')();
            		}
            		else {
            			params.get('submitForm').submit();
            		}
            	}
            	new Event(eventObject).stop();
            	return false;
            	*/
            	break;
            case 'key_event':
            	if(eventObject.key == 'enter' && this.userAtLogin) {
            		this.elements.login.form.submit();
            	}
            	if(eventObject.key == 'enter' && this.submitFormCallback) {
            		this.submitFormCallback();
            	}
            	new Event(eventObject).stop();
            	return false;
            	break;
            case 'set_focus':
            	this.userAtLogin = true;
            	break;
            case 'remove_focus':
            	this.userAtLogin = false;
            	break;
        }
    },
	/**
	 * show black overlay to darker the sight
	 */
	showBlackOverlay : function() {
		this.elements.blackOverlay.setStyle('display', 'block');
		if(this.blackOverlayVisible === null) {
			this.initBlackOverlay();
		}
		this.langBar.hideZoneSelect();
		this.blackOverlayVisible = true;
	},
	/**
	 * hide black overlay to darker the sight
	 */
	hideBlackOverlay : function() {
		if(this.blackOverlayVisible === null) {
			this.initBlackOverlay();
		}
		this.elements.blackOverlay.setStyle('display', 'none');
		this.langBar.showZoneSelect();
		this.blackOverlayVisible = false;
	},
	/**
	 * for first show the overlay has to be initialized
	 */
	initBlackOverlay : function() {
		var bodySize = this.elements.body.getScrollSize();
		if(Browser.Engine.name == 'webkit') {
			var docu = document.body;
			bodySize = {
				x : docu.scrollWidth,
				y : docu.scrollHeight
			};
		}
		this.elements.blackOverlay.setStyle('width', bodySize.x);
		this.elements.blackOverlay.setStyle('height', bodySize.y);
		this.elements.blackOverlay.setStyle('opacity', 0.75);
	},
	/**
	 * Change the selected universe in the login box.
	 * 
	 * @param Integer id Universe id
	 * @param String name Display name
	 * @param String url Universe url
	 */
	setSelectedUniverse: function(id, name, url) {
		this.elements.login.form.set("action", url+"/login/login");
		this.elements.buttons.showUniverse.set("text", name);
		this.dialogSmall.hideDialog();
	},
	/**
	 * save dom elements to attribute elements
	 */
	loadElements : function() {
		//load body
		this.elements.body = $('body');
		//load black overlay
		this.elements.blackOverlay = $('blackOverlay');
		//login form
		this.elements.login = {
			'name' : $('playerName'),
			'password' : $('playerPw'),
			'submit' : $('loginSubmit'),
			'form' : $('loginForm')
		};
		this.addEvent('focus', this.elements.login.name, $H({ action : 'set_focus' }));
		this.addEvent('focus', this.elements.login.password, $H({ action : 'set_focus' }));
		this.addEvent('blur', this.elements.login.name, $H({ action : 'remove_focus' }));
		this.addEvent('blur', this.elements.login.password, $H({ action : 'remove_focus' }));
		this.addKeyEvent($H({ action : 'key_event' }), this.elements.login.form);
		this.addEvent('submit', this.elements.login.form, $H({ action : 'submit_login' }));
		this.addEvent('click', this.elements.login.submit, $H({ action : 'submit_login' }));
		//load buttons
		this.elements.buttons = {
			'showUniverse' : $('showUniverse'),
			'register1' : $('registerButton1'),
			'register2' : $('registerButton2'),
			'register3' : $('registerButton3'),
			'screenshots1' : $('showScreenshots1'),
			'artwork1' : $('showArtwork1'),
			'imprint1' : $('showImprint1'),
			'tos' : $('showTos'),
			'rules' : $('showRules')
		};
		this.addEvent('click', this.elements.buttons.showUniverse, $H({ action : 'show_dialog' , 'url' : this.urls.showUniverse, caption : this.elements.buttons.showUniverse.getProperty('rel') }));
		this.addEvent('click', this.elements.buttons.register1, $H({ action : 'show_dialog' , 'url' : this.urls.register, caption : this.elements.buttons.register1.getProperty('rel') }));
		this.addEvent('click', this.elements.buttons.register2, $H({ action : 'show_dialog' , 'url' : this.urls.register, caption : this.elements.buttons.register1.getProperty('rel') }));
		this.addEvent('click', this.elements.buttons.register3, $H({ action : 'show_dialog' , 'url' : this.urls.register, caption : this.elements.buttons.register1.getProperty('rel') }));
		this.addEvent('click', this.elements.buttons.tos, $H({ action : 'show_dialog' , 'url' : this.urls.tos, caption : this.elements.buttons.tos.getProperty('rel') }));
		this.addEvent('click', this.elements.buttons.rules, $H({ action : 'show_big_dialog' , 'url' : this.urls.rules, caption : this.elements.buttons.rules.getProperty('rel') }));
		this.addEvent('click', this.elements.buttons.screenshots1, $H({ action : 'show_big_dialog' , 'url' : this.urls.screenshot, caption : this.elements.buttons.screenshots1.getProperty('rel')}));
		this.addEvent('click', this.elements.buttons.artwork1, $H({ action : 'show_big_dialog' , 'url' : this.urls.artwork, caption : this.elements.buttons.artwork1.getProperty('rel') }));
		this.addEvent('click', this.elements.buttons.imprint1, $H({ action : 'show_big_dialog' , 'url' : this.urls.imprint, caption : this.elements.buttons.imprint1.getProperty('rel') }));
	}
});
