"use strict";
var menu = (function($) {
	var $container = null; // Game container.
	var menus = {}; // Already created menu list.
	var stack = []; // Stack for open menus.
	var openingTime = 0; // Menu opening time.
	
	var animationOptions = {
		speed : 200,
		func : 'animate'
	};

	// Menu transition animations.
	var animations = {
		/**
		 * Run open animation between last and one before.
		 * 
		 * @param callback Callback function to execute after animation is finished.
		 */
		open : function open (callback) {
			if (stack.length == 1) { // Fade animation for first menu in stack.
				var fMenu = this;
				
				var onShowCallback = function onShowCallback () {
					var animationEndCallback = function () {
						// Run callback function and onAfterShow event.
						fMenu.callEvent('onAfterShow');
						if ($.isFunction(callback)) callback.call();
					};
					
					// Insert menu in container.
					fMenu.getElement().appendTo($container);
					// Animate menu depending on browser's function availability.
					fMenu.getElement().css({opacity : 0})[animationOptions.func]({opacity : 1}, animationOptions.speed, animationEndCallback);
				};

				var onOpenCallback = function onOpenCallback () {
					fMenu.callEvent('onShow', onShowCallback);
				};

				fMenu.callEvent('onOpen', onOpenCallback);
			} else if (stack.length > 1) { // Slide animation for more than one menu in stack.
				// Get last menu and one before.
				var lMenu = stack[stack.length - 2],
					rMenu = stack[stack.length - 1];

				var onHideCallback = function onHideCallback () {
					// Disconnect menus and detach the hidden one.
					lMenu.getElement().detach();

					// Run callback function and onAfterShow event.
					rMenu.callEvent('onAfterShow');
					if ($.isFunction(callback)) callback.call();
				};

				var onShowCallback = function onShowCallback () {
					var animationEndCallback = function () {
						// Run onHide event.
						lMenu.callEvent('onHide', onHideCallback);
					};
					
					// Put one menu in another to move theme together.
					rMenu.getElement().appendTo($container).css({left : '100%'});
					lMenu.getElement().appendTo(rMenu.getElement()).css({left : '-100%'});
					
					// Animate menu depending on browser's function availability.
					rMenu.getElement()[animationOptions.func]({left : '0%'}, animationOptions.speed, animationEndCallback);
				};

				var onOpenCallback = function onOpenCallback () {
					rMenu.callEvent('onShow', onShowCallback);
				};

				rMenu.callEvent('onOpen', onOpenCallback);
			}
		},
		/**
		 * Run close animation between last and one before.
		 * 
		 * @param callback Callback function to execute after animation is finished.
		 */
		close : function close (callback) {
			if (stack.length == 1) { // Fade animation for first menu in stack.
				var fMenu = this;
				
				var onCloseCallback = function onCloseCallback () {
					// Run callback function.
					if ($.isFunction(callback)) callback.call();
				};

				var onHideCallback = function onHideCallback () {
					// Run onClose event.
					fMenu.callEvent('onClose', onCloseCallback);
				};
				
				var animationEndCallback = function () {
					// Detach menu from container.
					fMenu.getElement().detach();
					
					// Run onHide event.
					fMenu.callEvent('onHide', onHideCallback);
				};

				// Animate menu depending on browser's function availability.
				fMenu.getElement().css({opacity : 1})[animationOptions.func]({opacity : 0}, animationOptions.speed, animationEndCallback);
			} else if (stack.length > 1) { // Slide animation for more than one menu in stack.
				// Get last menu and one before.
				var lMenu = stack[stack.length - 2],
					rMenu = stack[stack.length - 1];

				var onCloseCallback = function onCloseCallback () {
					// Run callback function and onHide and onClose events.
					if ($.isFunction(callback))	callback.call();
				};

				var onHideCallback = function onHideCallback () {
					// Run onClose event.
					rMenu.callEvent('onClose', onCloseCallback);
				};

				var onShowCallback = function onShowCallback () {
					// Disconnect menus and detach the hidden one.
					lMenu.getElement().appendTo($container);
					rMenu.getElement().detach();

					// Run onHide event.
					rMenu.callEvent('onHide', onHideCallback);
				};
				
				var animationEndCallback = function () {
					// Run onShow event on showing menu.
					lMenu.callEvent('onShow', onShowCallback);
				};
				
				// Put one menu in another to move theme together.
				lMenu.getElement().appendTo($container).css({left : '-100%'});
				rMenu.getElement().appendTo(lMenu.getElement()).css({left : '100%'});
				
				// Animate menu depending on browser's function availability.
				lMenu.getElement()[animationOptions.func]({left : '0%'}, animationOptions.speed, animationEndCallback);
			}
		}
	};
	
	var inputEnabled = false;
	
	var disableInput = function disableInput () {
		inputEnabled = false;
		game.log('input is ' + (inputEnabled ? 'enabled' : 'disabled'));
	};
	
	var enableInput = function enableInput () {
		inputEnabled = true;
		game.log('input is ' + (inputEnabled ? 'enabled' : 'disabled'));
	};

	var templates = {};
	
	// List template.
	templates.list = {
		events : {
			onCreate : function onCreate () {
				var $content = $('<div class="main-menu" />');

				$.each(this.getParams().options, function(itemName, callback) {
					var $menuItem = null;

					// Create and append new menu item.
					$menuItem = $('<a class="menu-item" />').text(itemName);
					$content.append($menuItem);
					
					/**
					 * onClickItemEvent handler for list menu options.
					 */
					var onClickItemEvent = function onClickItemEvent (event) {
						event.stopPropagation();
						
						if (inputEnabled) {
							// Move selected class to clicked menu item.
							if (!view.isItMobile()) {
								$content.find('.menu-item.selected').removeClass('selected');
								$(this).addClass('selected');
							}
	
							if ($.isFunction(callback)) callback();
						}
						
						return false;
					};

					// Lower case property name and put callback in events object.
					$menuItem.bind('click', onClickItemEvent);
				});

				// Set menu content.
				this.setContent($content);
			},
			onShow : function onShow (callback) {
				var $content = this.getContent();

				// Event that handles key up event, that allows menu navigation.
				var onKeyUpEvent = function onKeyUpEvent (event) {
					event.stopPropagation();

					var $selectedButton = null,
						$siblingButton = null;
					
					var prevOption = function prevOption ($selectedButton) {
						return $selectedButton.prev('.menu-item:visible');
					};
					
					var nextOption = function nextOption ($selectedButton) {
						return $selectedButton.next('.menu-item:visible');
					};
					
					var firstOption = function firstOption ($selectedButton) {
						return $selectedButton.prevAll('.menu-item:visible:last');
					};
					
					var lastOption = function lastOption ($selectedButton) {
						return $selectedButton.nextAll('.menu-item:visible:last')
					};

					// Get selected option.
					$selectedButton = $content.find('.menu-item.selected');
					
					switch (event.keyCode) {
					case 38 : // Up.
						$siblingButton = prevOption($selectedButton);
						if ($siblingButton.length == 0) $siblingButton = lastOption($selectedButton);
						break;
					case 40 : // Down.
						$siblingButton = nextOption($selectedButton);
						if ($siblingButton.length == 0) $siblingButton = firstOption($selectedButton);
						break;
					case 13 : // Enter.
					case 32 : // Space.
						$selectedButton.trigger('click');
						break;
					}
					// If sibling button exists move class 'selected' to this button.
					if ($siblingButton) {
						$content.find('.menu-item.selected').removeClass('selected');
						$siblingButton.addClass('selected');
					}

					return false;
				};

				if (!view.isItMobile()) {
					$(window).bind('keyup.mainmenunav', onKeyUpEvent);
				}

				callback();
				
				view.setPowerState("SCREEN_DIM");
			},
			onAfterShow : function onAfterShow () {
				var $content = this.getContent();

				// Add selected class to first button and remove it from others.\
				if (!view.isItMobile()) {
					if ($content.find('.menu-item.selected').length == 0) {
						$content.find('.menu-item:visible:first').addClass('selected');
					}
				}
			},
			onHide : function onHide (callback) {
				if (!view.isItMobile()) {
					$(window).unbind('keyup.mainmenunav');
				}

				callback();
				view.setPowerState("SCREEN_BRIGHT");
			}
		}
	};
	
	// Tabs template.
	templates.tabs = {
		events : {
			onCreate : function onCreate () {
				var $content = $('<div class="tabs-menu" />');
				
				// Create tabs holder and tabs content.
				var $tabsHolder  = $('<div class="tabs-holder" />').appendTo($content);
				var $tabsContent = $('<div class="tabs-content" />').appendTo($content);
				// Get tabs options.
				var options = this.getParams().options;
				
				$.each(options, function(undefined, tab) {
					var $tab = null;
					
					// Create tab and append it to tabs holder.
					$tab = $('<div class="tab" />').css({width: (100.0 / options.length) + '%'}).text(tab.name).appendTo($tabsHolder);
					
					/**
					 * onClickTabEvent handler for tabs menu.
					 */
					var onClickTabEvent = function onClickTabEvent (event) {
						event.stopPropagation();
						
						// Move selected class to clicked tab.
						$tabsHolder.find('.tab.selected').removeClass('selected');
						$tab.addClass('selected');
						
						// Change tab content.
						$tabsContent.html(tab.content);
						
						return false;
					};

					// Lower case property name and put callback in events object.
					$tab.bind('click', onClickTabEvent);
				});
				
				// Select first tab.
				$tabsHolder.find('.tab:first').trigger('click');

				// Set menu content.
				this.setContent($content);
			},
			onShow : function onShow (callback) {
				var $content = this.getContent();

				// Event that handles key up event, that allows menu navigation.
				var onKeyUpEvent = function onKeyUpEvent (event) {
					event.stopPropagation();

					var $selectedTab = null,
						$siblingTab = null;
					
					var prevTab = function prevTab ($selectedTab) {
						return $selectedTab.prev('.tab:visible');
					};
					
					var nextTab = function nextTab ($selectedTab) {
						return $selectedTab.next('.tab:visible');
					};
					
					var firstTab = function firstTab ($selectedTab) {
						return $selectedTab.prevAll('.tab:visible:last');
					}; 
					
					var lastTab = function lastTab ($selectedTab) {
						return $selectedTab.nextAll('.tab:visible:last');
					}; 

					// Get selected tab.
					$selectedTab = $content.find('.tab.selected');
					
					switch (event.keyCode) {
					case 37 : // Left.
						$siblingTab = prevTab($selectedTab);
						if ($siblingTab.length == 0) $siblingTab = lastTab($selectedTab);
						break;
					case 39 : // Right.
						$siblingTab = nextTab($selectedTab);
						if ($siblingTab.length == 0) $siblingTab = firstTab($selectedTab);
						break;
					}
					// If sibling tab exists move class 'selected' to this button.
					if ($siblingTab) {
						$content.find('.tab.selected').removeClass('selected');
						$siblingTab.addClass('selected').trigger('click');
					}

					return false;
				};

				if (!view.isItMobile()) {
					$(window).bind('keyup.tabsnav', onKeyUpEvent);
				}

				callback();
			},
			onHide : function onHide (callback) {
				if (!view.isItMobile()) {
					$(window).unbind('keyup.tabsnav');
				}

				callback();
			}
		}
	};
	
	// Form template.
	templates.form = {
		events : {
			onCreate : function onCreate () {
				var $content = $('<form class="form-menu" />');
				var fields = this.getParams().options;
				
				// Set menu content.
				this.setContent($content);
				
				// Fields iterator. It loops through the array and generate form field for each object.
				var fieldsIterator = function fieldsIterator (undefined, field) {
					var $row = null,
						$label = null,
						$field = null;
					
					if (!field.hasOwnProperty('type') ||
						!field.hasOwnProperty('name') ||
						!field.hasOwnProperty('label')) return true;

					// Create row and add it to the form.
					$row = $('<div class="form-row" />').appendTo($content);
					
					// Add label.
					$label = $('<label />').attr({'for' : field.name}).text(field.label +':').appendTo($row);
					
					// Add field.
					switch (field.type) {
					case 'checkbox':
						$field = $('<input type="checkbox"/>').attr({name: field.name, id: field.name}).appendTo($row);
						$field.checkbox();
						break;
					case 'buttonset':
						$field = $('<select  />').attr({name: field.name, id: field.name}).appendTo($row);
						$.each(field.buttons, function (undefined, button) {
							$('<option />').attr({value: button.value}).text(button.label).appendTo($field);
						});
						$field.buttonset();
						break
					}
					
					// Bind onChange event.
					if (field.hasOwnProperty('onChange')) {
						$field.on('change', field.onChange);
					}
				};
				
				// Loop through the array of form fields.
				$.each(fields, fieldsIterator);
			}
		}
	};

	/**
	 * Default Menu class.
	 * 
	 * @param {String} name Inner name for menu.
	 * @param {Object} params Menu params like title, template, events etc.
	 */
	var Menu = function Menu (name, params) {
		var $menu = null;
		var $menuContent = null;

		/**
		 * Return menu params.
		 */
		this.getParams = function getParams () {
			return params;
		};

		/**
		 * Execute event by given name.
		 */
		this.callEvent = function callEvent (eventName, callback) {
			if (params.hasOwnProperty('events') &&
				params.events.hasOwnProperty(eventName) &&
				$.isFunction(params.events[eventName])) {
				params.events[eventName].call(this, callback);
			} else {
				if ($.isFunction(callback)) callback();
			}
		};

		/**
		 * Get jQuery menu element.
		 * 
		 * @return {jQuery} Menu element.
		 */
		this.getElement = function getElement () {
			return $menu;
		};

		/**
		 * Inserts content into menu.
		 * 
		 * @param {jQuery} Content to insert into menu.
		 */
		this.setContent = function setContent ($content) {
			$menuContent.html($content);
		};

		/**
		 * Get content element from menu.
		 * 
		 * @return {jQuery} Menu content element.
		 */
		this.getContent = function getContent () {
			return $menuContent;
		};

		/**
		 * Check if menu is visible.
		 * 
		 * @returns {Boolean} Returns visibility state.
		 */
		this.isVisible = function isVisible () {
			// Check if menu has any parent, if id does so it's visible on the screen.
			return this.getElement().parent().length > 0;
		};

		/**
		 * Check if menu is open (is in stack).
		 */
		this.isOpen = function isOpen () {
			var stack = menu.getStack();

			for ( var i in stack) {
				if (stack[i] == this) return true;
			}
			return false;
		};

		/**
		 * Constructor.
		 */
		// Use template if provided.
		if (params.template && templates.hasOwnProperty(params.template)) {
			var template = templates[params.template];
			params = $.extend(true, template, params);
		}
		// Create menu element.
		$menu = $('<div id="menu" class="menu"><div class="menu-header"><a class="menu-back"><div class="image" /></a><h1 class="menu-title">'
				+ params.title
				+ '</h1></div><div class="menu-content"></div></div>');
		// Get menu-content element.
		$menuContent = $menu.find('.menu-content:first');
		// Call onCreate event.
		this.callEvent('onCreate');
	};

	return {
		/**
		 * Initialize menu controller.
		 */
		initialize : function initialize () {
			// Decide how menu animations should behave on different devices and rendering engines.
			animationOptions.func = 'animate';
			if (view.isItMobile()) {
				animationOptions.speed = 0;
			} else {
				animationOptions.speed = 200;
				if (Modernizr.csstransitions) animationOptions.func = 'transition';
			}
			
			// Get game container for further use.
			$container = $('#container');
			
			/**
			 * onClickCloseButtonEvent handler for clicking close button in menu header.
			 */
			var onClickCloseButtonEvent = function onClickCloseButtonEvent (event) {
				event.stopPropagation();

				if (inputEnabled) {
					// Exit app when main menu is on the screen and game is not running. Otherwise just close active menu.
					if (menu.get('earthguard').isVisible()) {
						if (game.isRunning())
							menu.close();
						else
							game.exit();
					} else {
						menu.close();
					}
				}

				return false;
			};

			// Close menu by clicking X button.
			$container.on('click.menu-back', '.menu-back', onClickCloseButtonEvent);

			// Escape key opens main menu or close active menu.
			$(window).bind('keyup.toggle-menu', function(event) {
				if (event.keyCode == 27) {
					// Open main menu if there is no menu on the screen.
					menu.toggle();
				}

				return false;
			});
		},
		/**
		 * Create menu and keep it for later use.
		 * 
		 * @param {String} name Inner name for menu.
		 * @param {Object} params Menu params like title, template, events (onCreate, onOpen, onClose).
		 * @returns {Menu} Newly created menu object.
		 */
		create : function create (name, params) {
			if (typeof name == 'undefined')
				return;
			if (menus.hasOwnProperty(name))
				return menus[name];

			menus[name] = new Menu(name, params);

			return menus[name];
		},
		/**
		 * Get menu if it exists.
		 * 
		 * @param {String} name Inner name for menu.
		 * @returns {Menu} Menu object.
		 */
		get : function get (name) {
			if (menus.hasOwnProperty(name)) {
				return menus[name];
			}
			return;
		},
		/**
		 * Open menu.
		 * 
		 * @param name Inner name for menu.
		 * @param callback Callback function to execute after menu open.
		 * @returns
		 */
		open : function open (name, callback) {
			// Get menu by inner name.
			var menu = this.get(name);

			// If menu exists open it.
			if (menu) {
				// Get menu opening time.
				if (stack.length == 0) {
					openingTime = (new Date()).getTime();
				}
				
				// Callback to call after animation finish.
				var afterAnimation = function afterAnimation () {
					// Enable keyboard events when animation is finished.
					enableInput();
					
					if ($.isFunction(callback)) callback();
				};

				if (!menu.isOpen()) {
					
					// Pause the game just before show animation start.
					game.pause();

					// Add menu to the stack.
					stack.push(menu);

					// Disable all keyboard events when animation starts.
					disableInput();
					
					// Animate menu opening.
					animations.open.call(menu, afterAnimation);
				} else {
					afterAnimation();
				}
			}
		},
		/**
		 * Close active menu.
		 * 
		 * @param callback Callback function to execute after menu close.
		 * @returns
		 */
		close : function close (callback) {
			var menu = null;
			
			// Calculate menu opening time when last menu is closed.
			if (stack.length == 1) {
				openingTime = (new Date()).getTime() - openingTime;
			}

			// Close only if there is any open menu.
			if (stack.length > 0) {
				// Get last menu in the stack, the active one.
				menu = stack[stack.length - 1];

				// Callback to call after animation finish.
				var afterAnimationCallback = function afterAnimationCallback () {
					// Remove menu from top of the stack.
					stack.pop();
					
					// Enable keyboard events when animation is finished.
					enableInput();

					if ($.isFunction(callback)) callback();
				};

				// Disable all keyboard events when animation starts.
				disableInput();
				
				// Animate menu opening.
				animations.close.call(menu, afterAnimationCallback);
			} else {
				if ($.isFunction(callback)) callback();
			}
		},
		/**
		 * Close all menus in stack.
		 * 
		 * @param callback Callback function to execute after menu close.
		 * @returns
		 */
		closeAll : function closeAll (callback) {
			// Callback to call after animation finish.
			var afterAnimationCallback = function afterAnimationCallback () {
				// Enable keyboard events when animation is finished.
				enableInput();
				
				if ($.isFunction(callback)) callback();
			}
			
			// Disable all keyboard events when animation starts.
			disableInput();
				
			if (menu.stackSize() > 0) {
				menu.close(function() {
					menu.closeAll(afterAnimationCallback);
				});
			} else if (menu.stackSize() == 0) {
				afterAnimationCallback();
			}
		},
		/**
		 * Toggle between Main Menu and game screen.
		 * 
		 * @returns
		 */
		toggle : function toggle () {
			var stackSize = menu.stackSize();

			if (stackSize == 0) {
				menu.open('earthguard');
			} else if (stackSize == 1) {
				if (game.isRunning())
					menu.close();
				else
					game.exit();
			} else if (stackSize > 1) {
				menu.close();
			}
		},
		/**
		 * Get menu opening time.
		 * 
		 * @returns {Number} Menu opening time.
		 */
		getOpeningTime : function getOpeningTime () {
			return  openingTime;
		},
		/**
		 * Get menu stack size.
		 * 
		 * @returns {Number}
		 */
		stackSize : function stackSize () {
			return stack.length;
		},
		/**
		 * Get menu stack.
		 * 
		 * @returns {Array}
		 */
		getStack : function getStack () {
			return stack;
		},
		/**
		 * Checks if any menu is opened
		 * 
		 * @returns {Boolean} true if any menu is opened
		 */
		isAnyMenuOpened : function isAnyMenuOpened () {
			return (stack.length) ? true : false;
		},
		isInputEnabled : function isInputEnabled () {
			return inputEnabled;
		}
	};
})(jQuery);

// MENU DEFINITIONS.
(function() {
	var params = {};
	params.earthGuard = {
		title : 'Earth Guard',
		template : 'list',
		options : {
			'Resume' : function() {
				menu.close();
			},
			'New game' : function() {
				if (levelManager.getAlreadyPassedLevels().length <= 1) {
					menu.close(function() {
						game.start(1);
					});
				} else {
					menu.open('chooselevel');
				}
			},
			'High scores' : function() {
				menu.open('highscores');
			},
			'How to play' : function() {
				menu.open('howtoplay');
			},
			/**
			 * TODO: Turn on for production
			 */
//			'Settings' : function() {
//				menu.open('settings');
//			},
			'About' : function() {
				menu.open('about');
			},
			'Exit' : function() {
				game.exit();
			}
		},
		events : {
			onOpen : function onOpen (callback) {
				var $content = this.getContent();
				var $resume = $content.find('.menu-item:first');

				// Show resume option only when game is running.
				game.isRunning() ? $resume.show().css('display', 'block') : $resume.hide();

				callback();
			},
			onClose : function onClose (callback) {
				game.resume(true);
				callback();
			}
		}
	};
	params.chooselevel = {
		title : 'Choose the level',
		events : {
			onCreate : function onCreate () {
			},
			onShow : function onShow (callback) {
				var levels = levelManager.getAlreadyPassedLevels();
				var $content = $('<div class="chooselevel-menu" />');

				if (levels.length) {
					// Generate each high score item.
					var generateItem = function generateItem (undefined, level) {
						/**
						 * onClickItemEvent handler for choose level boxes.
						 */
						var onClickItemEvent = function onClickItemEvent (event) {
							event.stopPropagation();
							
							if (menu.isInputEnabled()) {
								menu.closeAll(function() {
									game.start(level);
								});
							}
							
							return false;
						};
						
						// Create box for level.
						$('<a class="level" />').text(level).on('click', onClickItemEvent).appendTo($content);
					};

					$.each(levels, generateItem);
				}
				
				this.setContent($content);

				// Event that handles key up event, that allows menu navigation.
				var onKeyUpEvent = function onKeyUpEvent (event) {
					event.stopPropagation();

					var $selectedButton = null,
						$siblingButton = null;
					
					var prevOption = function prevOption ($selectedButton) {
						return $selectedButton.prev('.level:visible');
					};
					
					var upperOption = function upperOption ($selectedButton) {
						return $selectedButton.prevAll('.level:visible').eq(4);
					};
					
					var nextOption = function nextOption ($selectedButton) {
						return $selectedButton.next('.level:visible');
					};
					
					var lowerOption = function lowerOption ($selectedButton) {
						return $selectedButton.nextAll('.level:visible').eq(4);
					};
					
					// Get selected button.
					$selectedButton = $content.find('.level.selected');
					
					switch (event.keyCode) {
					case 37 : // Left.
						$siblingButton = prevOption($selectedButton);
						if ($siblingButton.length == 0) $siblingButton = $selectedButton.nextAll('.level:visible:last');
						break;
					case 38 : // Up.
						$siblingButton = upperOption($selectedButton);
						if ($siblingButton.length== 0) return false;
						break;
					case 39 : // Right.
						$siblingButton = nextOption($selectedButton);
						if ($siblingButton.length == 0) $siblingButton = $selectedButton.prevAll('.level:visible:last');
						break;
					case 40 : // Down.
						$siblingButton = lowerOption($selectedButton);
						if ($siblingButton.length== 0) return false;
						break;
					case 13 : // Enter.
					case 32 : // Space.
						$selectedButton.trigger('click');
						break;
					}
					// If sibling button exists move class 'selected' to this button.
					if ($siblingButton) {
						$content.find('.level.selected').removeClass('selected');
						$siblingButton.addClass('selected');
					}

					return false;
				};

				if (!view.isItMobile()) {
					$(window).bind('keyup.chooselevelnav', onKeyUpEvent);
				}

				callback();
			},
			onAfterShow : function onAfterShow () {
				var $content = this.getContent();
				
				// Add selected class to first button and remove it from others.
				if (!view.isItMobile()) {
					if ($content.find('.level.selected').length == 0) {
						$content.find('.level:visible:first').addClass('selected');
					}
				}
			},
			onHide : function onHide (callback) {
				if (!view.isItMobile()) {
					$(window).unbind('keyup.chooselevelnav');
				}

				callback();
			}
		}
	};
	params.highScores = {
		title : 'High scores',
		events : {
			onOpen : function onOpen (callback) {
				callback();
			},
			onShow : function onShow (callback) {
				var data = highScores.getAll();

				// Prepare content for holding high scores list.
				var $content = $('<div class="default-menu highscores-menu" />');

				// Create high scores list if there are any entries.
				var objectSize = $.map(data, function(value, key) {
					return key;
				}).length;
				if (objectSize) {
					var $ul = $('<ul />').appendTo($content);

					// Generate each high score item.
					var generateItem = function generateItem (place, info) {
						// Add each individual place as another
						// li item.
						var $li = $('<li/>');
						var $cup = $('<img class="cup" src="./images/high_score_' + place + '.png" />');
						var $nicknames = $('<div class="nicknames"></div>');
						var $score = $('<div class="score">' + info.score + '</div>');

						// Generate each player item.
						var generatePlayerItem = function generatePlayerItem (undefined, nickname) {
							$nicknames.append('<div class="nickname">'
									+ nickname + '</div>');
						};

						// Put nicknames in the same li if there are more than
						// one player on the same place.
						$.each(info.players, generatePlayerItem);

						$li.append($cup);
						$li.append($nicknames);
						$li.append($score);
						$li.appendTo($ul);
					};

					$.each(data, generateItem);
				} else {
					$content.html('<p style="text-align : center">No scores yet</p>');
				}

				// Set menu content.
				this.setContent($content);

				callback();
			}
		}
	};
	params.gameover = {
		title : 'Game over',
		events : {
			onCreate : function onCreate () {
				// Prepare content for holding nickname dialog.
				var $form = $('<form class="default-menu gameover-menu" action="#" onsubmit="return false;" />');

				// Create dialog elements.
				$('<label>Your nick</label>').appendTo($form);
				var $nick = $(
						'<input type="text" name="nick" maxlength="5" autocomplete="off" tabindex="1" />')
						.appendTo($form);
				var $cancel = $(
						'<input type="reset" value="Cancel" tabindex="2" />')
						.appendTo($form);
				var $ok = $('<input type="submit" value="OK" tabindex="3" />')
						.appendTo($form);

				$form.submit(function() {
					var nick = $nick.val();
					if (nick.length == 0) {
						alert('Write down you nick or click Cancel');
						return false;
					}

					if (nick.length > 5) {
						alert('Your nick is too long');
						return false;
					}

					highScores.insert(nick, game.points);
					menu.close();
				});

				$cancel.click(function() {
					menu.close();
					return false;
				});

				$ok.click(function() {
					$form.submit();
					return false;
				});

				// Set menu content.
				this.setContent($form);
			},
			onClose : function onClose (callback) {
				this.getContent().find('input[name="nick"]').val('');
				callback();

				menu.open('earthguard', function() {
					menu.open('highscores');
				});
			},
			onAfterShow : function onAfterShow () {
				var $content = this.getContent();

				$content.find('input:first').focus();
			}
		}
	};
	params.howToPlay = {
		title : 'How to play',
		template: 'tabs',
		options : [
			{
				name : 'Control',
				content : '<img src="./images/how_to_play_tab1.png" width="100%" />'
			}, {
				name : 'Goals',
				content : '<img src="./images/how_to_play_tab2.png" width="100%" />'
			}
		]
	};
	params.settings = {
		title : 'Settings',
		template : 'form',
		options : [
			{
				type : 'checkbox',
				name : 'sound',
				label : 'Sound',
				onChange : function onChange () {
					game.log(this.value);
					game.log('Sound is '+ ($(this).is(':checked') ? 'on' : 'off'));
				}
			},
			{
				type : 'checkbox',
				name : 'music',
				label : 'Music',
				onChange : function onChange () {
					game.log('Music is '+ ($(this).is(':checked') ? 'on' : 'off'));
				}
			},
			{
				type : 'buttonset',
				name : 'difficulty',
				label : 'Difficulty',
				buttons : [
					{label : 'Easy', value : 'easy'},
					{label : 'Medium', value : 'medium'},
					{label : 'Hard', value : 'hard'},
			    ],
				onChange : function onChange () {
					game.log('Difficulty level is '+ $(this).val());
				}
			}
        ]
	};
	params.about = {
		title : 'About',
		events : {
			onCreate : function onCreate () {
				var $content = $('<div class="default-menu about-menu" data-name="highscores-menu" />').html(
						'<h2>Earth Guard ' + config.version+'</h2>' + 
						'<p>Copyrights (C) SRPOL 2013</p>' + 
						'<p>This is a Samsung Developers sample app.</p>');
	
				// Set menu content.
				this.setContent($content);
			}
		}
	};

	menu.create('chooselevel', params.chooselevel);
	menu.create('earthguard',  params.earthGuard);
	menu.create('highscores',  params.highScores);
	menu.create('gameover',    params.gameover);
	menu.create('howtoplay',   params.howToPlay);
	menu.create('settings',    params.settings);
	menu.create('about',       params.about);
})();
