////////////////////////////////////////
// CRYPTOGRAMS - RAZZLE
////////////////////////////////////////
var Cryptogram = function() {
	var Req, 
	    Data, 
	    currInputs, 
	    ReturnObj = {
	    	failCount : 0
	    };
	
	/////////////////////////////////////////////////////////////////////
	var init = function(event) {
		$("fl-reset").addEvent("click", function(event) {
			Cryptogram.resetBoard();
			event.stop();
			return false;
		});
		$("fl-newgame").addEvent("click", function(event) {
			Cryptogram.gutBoard();
			Cryptogram.getCryptogram();
			if (!!event) { event.stop(); }
			return false;
		});
		$("fl-print").addEvent("click", function(event) {
			Razzle.renderForPrint();
			event.stop();
			return false;
		});
		$("toggleFrequenciesLink").addEvent("click", function(event) {
			Cryptogram.toggleFrequencies();
			event.stop();
			return false;
		});
		
		if (Razzle.puzzleJSON.length > 0) {
			parse(Razzle.puzzleJSON[0], true);
		} else {
			getCryptogram();
		}
	};
	
	/////////////////////////////////////////////////////////////////////
	var getCryptogram = function() {
		Req = new Request.JSON({ url : "/getCryptogram/" + new Date().getTime(), method : "GET", secure : false });
		Req.addEvent("onComplete", function(cryptogram) {
			if (!!cryptogram && cryptogram.length > 0) {
				Cryptogram.parse(cryptogram[0], true);
			} else if (Cryptogram.failCount < 11) {
				Cryptogram.failCount++;
				Cryptogram.getCryptogram();
			}
		});
		Req.get();
	};
	
	/////////////////////////////////////////////////////////////////////
	var parse = function(Fields, fadeIn) {
		Data = Fields;
		Data.cWords = Data.cryptogram.split(" ");
		Data.qWords = Data.quote.split(" ");
		if (Data.cWords.length !== Data.qWords.length) {
			Cryptogram.failCount++;
			if (Cryptogram.failCount < 11) {
				getCryptogram();
			}
			return;
		}
		
		var board = $("puzzleBoard");
		if (fadeIn) {
			board.setStyles({ "opacity" : 0.0, "visibility" : "hidden" });
		}
		
		// Generate the frequency table:
		Data.freqList = Data.frequencies.split(",");
		var alphabet = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];
		$("puzDescExtra").set("html", "" + 
			"<TABLE id='cFrequencyTable'><TBODY><TR><TH>" + alphabet.join("</TH><TD rowSpan='2' class='cFT-Divider'></TD><TH>") + "</TH></TR>" + 
			"<TR><TD>" + Data.freqList.join("</TD><TD>") + "</TD></TR></TBODY></TABLE>");
		
		// Generate the cryptogram tables:
		var letters = [], 
		    lettersL = 0, 
		    cLetters = [], 
		    cLettersL = 0, 
		    html = ["<DIV class='cClearBar'></DIV>"], 
		    htmlL = 1, 
		    firefox2Display = (Browser.Engine.gecko18) ? "style='display:-moz-inline-box;'" : "";
		    tableHTML = "<TABLE class='crypTable'" + firefox2Display + "><TBODY><TR><TD>", 
		    inputStr = "<INPUT type='text' class='c-input' maxlength='1' onfocus='Cryptogram.highlightFields(event);' " +
					"onblur='Cryptogram.resetColors(event);' onkeyup='Cryptogram.checkField(event);' />";
		
		for (var i=0, len=Data.cWords.length; i<len; i++) {
			html[htmlL++] = tableHTML + Data.cWords[i].split("").join("</TD><TD>") + "</TD></TR>";
			html[htmlL++] = "<TR>" + Data.cWords[i].replace(/./g, "<TD>" + inputStr + "</TD>") + "</TR></TBODY></TABLE>";
			letters[lettersL++] = Data.cWords[i];
			cLetters[cLettersL++] = Data.qWords[i];
		}
		html[htmlL++] = "<SPAN id='authorTag'>" + Data.author + "</SPAN><DIV class='cClearBar'></DIV>";
		board.set("html", html.join(""));
		
		// Add input behavior:
		var inputs = board.getElementsByTagName("INPUT"); // Do not extend for performance reasons
		var extendedInputs = [];
		letters = letters.join("").split("");
		cLetters = cLetters.join("").split("");
		for (var input, i=0; input=inputs[i]; i++) {
			if (/[A-Z]/.test(letters[i])) {
				input.setAttribute("letter", letters[i]);
				input.setAttribute("mLetter", cLetters[i]);
				//input.value = cLetters[i];
				extendedInputs.push(input);
			} else {
				input.className = "c-input-readonly";
				input.value = letters[i];
				input.setAttribute("readOnly", "true");
				input.setAttribute("tabIndex", "1000");
			}
		}
		
		if (fadeIn) {
			board.fade(1.0);
		}
		Razzle.setStatTimer((new Date()).getTime());
		
		currInputs = [];
		setTimeout(function() {
			var st = new Date().getTime();
			while (extendedInputs.length > 0 && (new Date().getTime() - st) < 50) {
				currInputs.push($(extendedInputs.shift()));
			}
			if (extendedInputs.length > 0) {
				setTimeout(arguments.callee, 25);
			}
		}, 25);
	};
	
	/////////////////////////////////////////////////////////////////////
	var resetBoard = function() {
		for (var i=0, input; input=currInputs[i]; i++) {
			input.set({ value : "", styles : { "background-color" : "#ffffff" } });
		}
		$("messageScreen").setStyle("display", "none");
		$("messageBox").setStyle("display", "none").set("html", "");
		Razzle.setStatTimer(-1);
	};
	
	/////////////////////////////////////////////////////////////////////
	var gutBoard = function() {
		Cryptogram.failCount = 0;
		Data = {};
		currInputs = null;
		$("toggleFrequenciesLink").set("text", "Show Frequencies");
		$("puzzleBoard").set("html", "");
		$("messageScreen").setStyle("display", "none");
		$("messageBox").setStyle("display", "none").set("html", "");
	};
	
	/////////////////////////////////////////////////////////////////////
	var highlightFields = function(event) {
		event = (!!event) ? new Event(event) : ((!!window.event) ? new Event(window.event) : {});
		
		var letter = (!!event.target) ? event.target.getAttribute("letter") : "";
		if (typeof letter !== "string" || !/[A-Z]/.test(letter)) return;
		
		for (var i=0, input; input=currInputs[i]; i++) {
			if (input.get("letter") === letter) {
				input.setStyle("background-color", "#fff3bd");
			}
		}
	};
	
	/////////////////////////////////////////////////////////////////////
	var resetColors = function(event) {
		event = (!!event) ? new Event(event) : ((!!window.event) ? new Event(window.event) : {});
		
		for (var i=0, input; input=currInputs[i]; i++) {
			input.setStyle("background-color", "#ffffff");
		}
	};
	
	/////////////////////////////////////////////////////////////////////
	var checkField = function(event) {
		event = (!!event) ? new Event(event) : ((!!window.event) ? new Event(window.event) : {});
		if (event.code === 9) return; // Tab
		
		var val = event.target.value.toUpperCase(), 
		    hasWon = true, 
		    letter = event.target.getAttribute("letter");
		
		for (var i=0, input; input=currInputs[i]; i++) {
			if (input.get("letter") === letter) {
				input.value = val;
			}
			if (input.value !== input.get("mLetter")) {
				hasWon = false;
			}
		}
		
		if (hasWon) {
			event.target.blur();
			
			for (var i=0, input; input=currInputs[i]; i++) {
				input.setStyle("background-color", "#ffffff");
			}
			
			var msg = "Congratulations, you've solved the puzzle!";
			msg += "<span id='cryptogramQuote'>\" " + Data.quote + " \"</span>";
			msg += "<span id='cryptogramAuthor'>" + Data.author + "</span>";
			
			Razzle.updateStat("cryptogram");
			Razzle.showMessage(msg, true);
		}
	};
	
	/////////////////////////////////////////////////////////////////////
	var toggleFrequencies = function() {
		var cFrequencyTable = $("cFrequencyTable");
		if (cFrequencyTable.getStyle("display") !== "block") {
			cFrequencyTable.setStyle("display", "block");
			$("toggleFrequenciesLink").set("text", "Hide Frequencies");
		} else {
			cFrequencyTable.setStyle("display", "none");
			$("toggleFrequenciesLink").set("text", "Show Frequencies");
		}
	};
	
	ReturnObj.init = init;
	ReturnObj.getCryptogram = getCryptogram;
	ReturnObj.parse = parse;
	ReturnObj.resetBoard = resetBoard;
	ReturnObj.gutBoard = gutBoard;
	ReturnObj.highlightFields = highlightFields;
	ReturnObj.resetColors = resetColors;
	ReturnObj.checkField = checkField;
	ReturnObj.toggleFrequencies = toggleFrequencies;
	
	return ReturnObj;
}();
