/************************************************
 * The first section in this file specifies the
 * set of card games that can be played given a
 * selection of categories chosen by the user.
 ************************************************/
 
var Games = new function() {

	/* construction */
	
	this.warehouse = new CardGameWarehouse();

	//////////////////////
	// Add/Edit Cards	//
    //////////////////////
	var cardset = new CardGame("Add/Edit Cards");
	cardset.setPlayCallback(function() { // Special case callback
		var category = this.getOptions()["category"].getValue();
		postEvent("EDITOR_START_CATEGORY", category);
		CurrentCard.setCategory(category);
	});
	this.warehouse.addGame(cardset);
	
	/////////////////
	// Flash-cards //
    /////////////////
	var fcgame = new CardGame("Flash-cards");
	fcgame.setPlayCallback(function(initMessage) { // Special case callback
		Player.startPlayer(fcgame.getOptions()["category"].getValue(),
						   fcgame.getOptions()["uid"].getValue());
	});
	this.warehouse.addGame(fcgame);

	///////////////////
 	// Concentration //
 	///////////////////
	var ccgame = new CardGame("Concentration", "../concentration");
	
	var ccoptionPlayers = new Options.RadioButtons("numPlayers", 1, "# Players: ");
	ccoptionPlayers.addButton("1-player", 1);
	ccoptionPlayers.addButton("Multi-player", 2);
	
	var ccoptionImage = new Options.RadioButtons("gameType", "pictures", "Game Type: ");
	ccoptionImage.addButton("Pictures", "pictures");
	ccoptionImage.addButton("Characters", "characters");

	ccgame.setOption(ccoptionPlayers);
	ccgame.setOption(ccoptionImage);
	
	var ccmanualOption = new Options.RadioButtons("manualMode", false, "Manual Mode: ");
	ccmanualOption.addButton("On", "true");
	ccmanualOption.addButton("Off", "false");
	
	ccgame.setAdvancedOption(new Options.FixedField("header", "Grammar Header Name: ", "concentration"));
	ccgame.setAdvancedOption(ccmanualOption);
	
	//this.warehouse.addGame(ccgame);

	//////////////////
 	// Envoice Tool //
 	//////////////////
	var envoicetool = new CardGame("Envoice Tool", "../envoicetool");
	envoicetool.setAdvancedOption(new Options.FixedField("header", "Grammar Header Name: ", "envoicetool"));
	//this.warehouse.addGame(envoicetool);

	
	/* public */
	this.runWordWarTutorial = function() {
		window.location.href = "/wordwar/?requireLogin=false&option[rows]=2&option[cols]=2&option[category]=tutorial&option[uid]=2&option[tutorial]=basic&option[gameMode]=speaking&gameType=[pictures]";
	}
	
	this.showGames = function(show, category, uid, allowEdit) {
		if (show) {
			View.games.display();
			var titleE = document.getElementById("MenuTitle");
			var gamesE = document.getElementById("GameSpan");
			var optionsE = document.getElementById("OptionsSpan");
			Utils.DOM.clearChildren(titleE);
			Utils.DOM.clearChildren(gamesE);
			Utils.DOM.clearChildren(optionsE);
			
			var categoryText = document.createTextNode("Menu ("+category+")");
			titleE.appendChild(categoryText);
    			
			gamesE.appendChild(this.warehouse.getDocumentElement(category, uid, allowEdit));
		}
		else {
			if (CurrentCard.getCategory()) {
				View.creator.display();
			}
			else {
				View.instructions.display();
			}
		}
	}
		
	/* private classes */
 
	/*
 	 * CardGameWarehouse constructor.  Basically just stores an array of games
 	 * and access to a method that returns an element that can be used to access
 	 * the games via the UI.
 	 */
	function CardGameWarehouse() {
		var games = new Array();
		
		this.addGame = function(game) {
			games.push(game);
		}
		
		/*
		 * Adds a card game by getting the options from a remote
		 * location.
		 */
		this.addGameRemotely = function(name, location) {
			var game = new CardGame(name, location);
			var optionsE = this.getRemoteOptions(location);
			
			var options = Options.getOptionsFromXML(optionsE);
			
			if (options == null) {
				alert("Warning: " + name + " is not set up properly for your browser.");
			}
			else {
				var advancedOptions = Options.getAdvancedOptionsFromXML(optionsE);
			
				game.addOptions(options);
				game.addAdvancedOptions(advancedOptions);
			
				this.addGame(game);
			}
		}
		
		this.getRemoteOptions = function(location) {
			var optionsRequest = Utils.AJAX.createRequest();
			var url = Utils.AJAX.makeRequestURL(location + "/ajaxcontrol", 
									'operation', 'fetch-options');
			optionsRequest.open('GET', url, false);
			optionsRequest.send(null);
			
			if (optionsRequest.readyState == 4) {
				if (optionsRequest.status == 200) {
					var xmldoc = optionsRequest.responseXML;
					return xmldoc;
				}
			}
			
			return null;
		}
		
		this.getGame = function(name) {
			for (var i = 0; i < games.length; i++) {
				if (games[i].getName() == name) {
					return games[i];
				}
			}
			
			return null;
		}
		
		this.getDocumentElement = function(category, uid, allowEdit) {
			var spanE = document.createElement('span');
			var sessionID = contextSwitchSave();
			
			var brE = document.createElement('br');
			
			var firstGame = (allowEdit ? 0 : 1);  // Disallow the Add / Edit cards if !allowEdit
			
			for (var i = firstGame; i < games.length; i++) {
				games[i].setOption(new Options.HiddenField("uid", User.getCurrentUser()), true);
				games[i].setOption(new Options.FixedField("category", "Category: ", category), true);
				games[i].setOption(new Options.HiddenField("cardCreatorSessionID", sessionID), true);
				
				var brE = document.createElement('br');				
				spanE.appendChild(brE);

				if (Options.getUseOptions()) {
					var smileyIcon = Utils.DOM.createOnClickImage('images/smiley.gif', 
																  "this.game.showOptions(true)");
					smileyIcon.game = games[i];
					spanE.appendChild(smileyIcon);
				}
		
				var linkE = Utils.DOM.createEmptyLink();
				linkE.game = games[i];
				linkE.onclick = function() {
					if (this.game.hasOptions(false)) {
						this.game.showOptions(false);
					} else {
						this.game.playGame(this.game.getOptionsDocument());
					}
					return false;
				};
				
				var textE = document.createTextNode(games[i].getName());
				linkE.appendChild(textE);
				spanE.appendChild(linkE);
			}
		
			return spanE;
		}
		
		
	}

	/*
 	 * This is a constructor for the java-script CardGame object.
 	 * Not all the parameters are necessary.
 	 *
 	 * The playCallback method gets called with the options for 
 	 * a particular game have been set and the user has pushed
 	 * "Play".
 	 */
	function CardGame(name, url, playCallback) {
		this.playGame = defaultPlayGame;
		
		var name = name;
		var url = (url) ? url : "";
		var options = new Array();
		var advancedOptions = new Array();
		var hasOptions = false;
		var hasAdvancedOptions = false;
		
		this.hasOptions = function(includingAdvanced) {
			return hasOptions || (includingAdvanced && hasAdvancedOptions);
		}
		
		this.setPlayCallback = function(playCallback) {
			this.playGame = playCallback;
		}
		
		// Option names must be unique (allows for easy updating)
		this.setOption = function(option, ignoreHas) {
			hasOptions = hasOptions || !ignoreHas;
			options[option.getName()] = option;
		}
		
		this.getName = function () { return name; }
		
		this.getOptions = function () {
			return options;
		}

		// Advanced options are only SHOWN to admins (default values still sent though)
		this.setAdvancedOption = function(option) {
			hasAdvancedOptions = true;
			advancedOptions[option.getName()] = option;
		}
		
		this.getAdvancedOptions = function () {
			return advancedOptions;
		}
		
		this.addOptions = function(opts) {
			var i;
			for (i = 0; i < opts.length; i++) {
				this.setOption(opts[i]);
			}
		}

		this.addAdvancedOptions = function(opts) {
			var i;
			for (i = 0; i < opts.length; i++) {
				this.setAdvancedOption(opts[i]);
			}
		}
		
		this.getOptionsDocument = function() {
			var xmldoc = Utils.XML.newDocument();
			var root = xmldoc.createElement("options");
			
			for (var i in advancedOptions) {
				var optionN = xmldoc.createElement("option");
				optionN.setAttribute("name", advancedOptions[i].getName());
				optionN.appendChild(xmldoc.createCDATASection(advancedOptions[i].getValue()));
				root.appendChild(optionN);
			}
			
			for (var i in options) {
				var optionN = xmldoc.createElement("option");
				optionN.setAttribute("name", options[i].getName());
				optionN.appendChild(xmldoc.createCDATASection(options[i].getValue()));
				root.appendChild(optionN);
			}
			
			xmldoc.appendChild(root);
			return xmldoc;
		}
		
		this.showOptions = function(advanced) {
			var optionsE = document.getElementById('OptionsSpan');
			Utils.DOM.clearChildren(optionsE);
			optionsE.appendChild(document.createTextNode(name + ' Options:'));
			optionsE.appendChild(document.createElement('br'));
			optionsE.appendChild(document.createElement('br'));
			
			var grammarHeaderName = null;
			var languageOption = null;
			
			if (advanced) {
				for (var i in advancedOptions) {
					var option = advancedOptions[i];
									
					if (option.getName() == "header") {
						grammarHeaderName = option.getValue();
					}
				
					if (option.getName() == "language") {
						languageOption = option;
					}
					
					if (option.getDocumentElement) {
						optionsE.appendChild(option.getDocumentElement());
						optionsE.appendChild(document.createElement('br'));
					}
				}
			}
			
			for (var i in options) {
				var option = options[i];

				if (option.getName() == "language") {
					languageOption = option;
				}
				
				if (option.getDocumentElement) {
					optionsE.appendChild(option.getDocumentElement());
					optionsE.appendChild(document.createElement('br'));
				}
			}
			
			var playButtonE = document.createElement('input');
			playButtonE.setAttribute('type', 'button');
			playButtonE.setAttribute('value', 'Play ' + name + '!');
			playButtonE.game = this;
			playButtonE.onclick = function() { this.game.playGame(this.game.getOptionsDocument()); };

			var closeButtonE = document.createElement('input');
			closeButtonE.setAttribute('type', 'button');
			closeButtonE.setAttribute('value', 'Close Options');
			closeButtonE.onclick = function() {
				var optionsE = document.getElementById('OptionsSpan');
				Utils.DOM.clearChildren(optionsE);
				return false;
			};
			
			var editHeaderButtonE = null;
			if (grammarHeaderName) {
				editHeaderButtonE = document.createElement('input');
				editHeaderButtonE.setAttribute('type', 'button');
				editHeaderButtonE.setAttribute('value', 'Edit Game Grammar Header');
				editHeaderButtonE.grammarHeaderName = grammarHeaderName;
				editHeaderButtonE.languageOption = languageOption;
				editHeaderButtonE.onclick = function() { 
					var languageSuffix = (languageOption ? "-" + languageOption.getValue() : "");
					Grammar.startGrammarHeaderTool(this.grammarHeaderName + languageSuffix); 
				};
			}
			
			optionsE.appendChild(document.createElement('br'));
			optionsE.appendChild(playButtonE);
			
			if (editHeaderButtonE) {
				optionsE.appendChild(editHeaderButtonE);
			}
			
			optionsE.appendChild(closeButtonE);
		}
		
		/* helpers */
		function defaultPlayGame(initMessage) {
			var request = Utils.AJAX.createRequest();
			var requestURL = Utils.AJAX.makeRequestURL(url + '/ajaxcontrol', 'operation', 'initialize'/*, 'contextSwitchSessionId', contextSwitchSave()*/);

			request.open('POST', requestURL, false);
			
			// Just get the options set by the user.
			postEvent('GAME_PUSH_PLAY', name);

			request.send(initMessage);

			if (request.status == 200) {
				var xmldoc = request.responseXML;
				var errorNs = xmldoc.getElementsByTagName('error');
				
				if (errorNs && errorNs.length > 0) {
					for (var i = 0; i < errorNs.length; i++) {
						alert(errorNs[i].getAttribute("message"));
					}
				}
				else {
					var gameurl = url;
					if (User.getCurrentUser() == 6 || User.getCurrentUser() == 237) {
						gameurl += '?requireLogin=false';
					}
					window.location.href = gameurl;
				}
			} else {
				alert("Something seems to be malfunctioning with the transition to the game.\nPlease inform the administrator.");
			}
		
			return false;  // In case this is attached to a button
		}
	}
}