/*
	Copyright 2008 Egmont Serieforlaget AS

	Developed by Escio AS - http://www.escio.no/
*/
function eXWord(ePuzzle, puzzleId) {
	this.ePuzzle			= ePuzzle;

	this.eXWordId			= puzzleId;
	this.baseUrl			= '';

	this.state				= 'UNINITIALIZED';
	this.stateMessage		= '';

	this.saveState			= 'SAVED';
	this.forceSave			= false;
	this.xwordStart			= 0;
	this.xwordTimer			= 0;
	this.navigationTimer	= 0;

	this.selectedCell		= undefined;
	this.selectedWord		= undefined;
	this.xWordCheckSum		= '';
	this.puzzleMode			= '';

	this.charSet			= 'ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ';

	this.initPainter = function() {
		this.painter.initXWordElement();
	}

	this.getError = function() {
		if(this.xWord.error) return this.xWord.error;

		return false;
	}

	this.buildPuzzle = function() {
		this.ePuzzle.setPuzzleType(this.xWord.type);
		this.ePuzzle.setPuzzleCodename(this.xWord.codename);
		this.ePuzzle.setPuzzleLevel(this.xWord.level);
		this.ePuzzle.setPuzzleStatus(this.xWord.status);
		this.ePuzzle.setPuzzleTitle(this.xWord.name);
		this.ePuzzle.setAuthor(this.xWord.author);
		this.ePuzzle.setDateTs(this.xWord.availableFromTs);

		this.painter.buildXWord();

		this.addButtons();
		this.setAdditionalInfo();

		if(this.xWord.startTs > 0) {
			this.ePuzzle.setStatus('Påbegynt: ' + tsToDate(this.xWord.startTs));

			if(this.xWord.storedData != undefined) this.loadStoredData(this.xWord.storedData);
		}
	}

	this.setAdditionalInfo = function() {
		var additionalInfo = '';
		if (this.xWord.userId > 0) {
			if(this.xWord.actions.buy) {
				additionalInfo = 'Denne oppgaven er en konkurranseoppgave. Ved å kjøpe denne oppgaven får du mulighet til å delta i konkurransen.';
			} else {
				if(this.ePuzzle.puzzleContext == 'puzzle') {
					additionalInfo = 'Løs oppgaven for å samle poeng og delta i konkurranser.';
				} else {
					if(this.xWord.actions.solve) {
						additionalInfo = 'Løs oppgaven for å samle poeng og delta i konkurransen.';
					} else {
						additionalInfo = 'Du må være medlem for å kunne løse denne oppgaven og delta i konkurransen.<br /><a class="register" href="/medlemskap/">Les mer om medlemskap her</a>';
					}
				}
			}
		} else {
			additionalInfo = 'Du må være registrert bruker for å kunne sende inn løsning på oppgaven.<br /><a class="register" href="/medlemskap/">Les mer om medlemskap her</a>';
		}

		if($('puzzleHelptext') && $('puzzleHelpLinktext') && $('puzzleHelptext').innerHTML != '') {
				additionalInfo += '<br /><br /><a onclick="openHelpText(); return false;">'+$('puzzleHelpLinktext').innerHTML+'</a>';
		}
		this.ePuzzle.setAdditionalInfo(additionalInfo);
	}

	this.puzzleBought = function() {
		this.ePuzzle.removeButtons();
		this.xWord.actions.buy = false;
		this.setAdditionalInfo();
		this.addButtons();
	}

	this.addButtons = function() {
		if(this.xWord.actions.buy) {
			this.ePuzzle.addButton(this.ePuzzle, 'Gå til kjøp av oppgaven', 'buyPuzzleButton', true);
		} else {
			this.ePuzzle.addButton(this, 'Send inn'		, 'submitButton'		, this.xWord.actions.submit);
			this.ePuzzle.addButton(this, 'Lagre'		, 'saveButton'			, false);
			this.ePuzzle.addButton(this, 'Tøm'			, 'resetButton'			, true);
			this.ePuzzle.addButton(this, 'Se fasit'		, 'solveButton'			, this.xWord.actions.solve);
			this.ePuzzle.addButton(this, 'Se ord'		, 'solveWordButton'		, false);
			this.ePuzzle.addButton(this, 'Se bokstav'	, 'solveLetterButton'	, false);
			this.ePuzzle.addButton(this, 'Leksikon'		, 'nklSearchButton'		, this.xWord.actions.dictionary);
		}
	}

	this.setState = function(newState) {
		// Update internal state
		this.state = newState;

		// Tell painter-object to update
		// any visual elements affected
		// by state.
		this.painter.newState();
	}

	this.setSaveState = function(state) {
		if(state == 'SAVED') {
			if(this.saveState != 'SAVED') {
				// TODO: Oppdater lagringsstatus
			}

			this.saveState = 'SAVED';
		}

		if(state == 'CHANGED') {
			this.saveState = 'CHANGED';
		}
	}

	this.selectCell = function() {
		this.painter.selectCell();
	}

	this.selectWord = function() {
		this.painter.selectWord();
	}

	this.deSelectWord = function() {
		this.painter.deSelectWord();
	}

	this.selectNextCell = function(limitToWord) {
		var baseId = this.ePuzzle.puzzleContainer;

		var xWord = this.xWord;
		var grid = xWord.grid;
		var word = this.selectedWord;

		var increment = word[0] ? grid[0] : 1;

		var currentCell		= undefined;
		var nextCell		= undefined;

		// Find current cell
		for(var i = 0; i < word[2]; i++) {
			var cellId = baseId + '_' + ((word[1]-1) + (i*increment));

			if(currentCell && !nextCell) nextCell = cellId;
			if(!currentCell && (cellId == $(this.selectedCell.id).up().id)) currentCell = cellId;
		}

		// End of word
		if(!nextCell && !limitToWord) {
			nextCell = currentCell;
			this.selectedCell = $(currentCell+'_input');
			this.deSelectWord();

			nextCell = this.jumpNext(((word[1]-1) + (i*increment)), increment, currentCell);

			this.selectedCell = $(nextCell+'_input');
			this.selectCellWord(this.selectedCell, word[0]);
		}

		if(nextCell) {
			this.selectedCell = $(nextCell+'_input');
			this.deSelectWord();
			this.selectWord();
			this.selectCell();

			$(nextCell+'_input').focus();
		}
	}

	this.selectPrevCell = function() {
		var baseId = this.ePuzzle.puzzleContainer;

		var xWord = this.xWord;
		var grid = xWord.grid;
		var word = this.selectedWord;

		var increment = word[0] ? grid[0] : 1;

		var currentCell		= undefined;
		var nextCell		= undefined;

		// Find current cell
		for(var i = word[2]-1; i >= 0; i--) {
			var cellId = baseId + '_' + ((word[1]-1) + (i*increment));

			if(currentCell && !nextCell) nextCell = cellId;
			if(!currentCell && (cellId == $(this.selectedCell.id).up().id)) currentCell = cellId;
		}

		// End of word
		if(!nextCell) {
			nextCell = currentCell;
			this.selectedCell = $(currentCell+'_input');
			this.deSelectWord();

			nextCell = this.jumpPrev((word[1]-1) + (i*increment), increment, currentCell);

			this.selectedCell = $(nextCell+'_input');
			this.selectCellWord(this.selectedCell, word[0]);
			this.selectWord();
		}

		this.selectedCell = $(nextCell+'_input');
		this.deSelectWord();
		this.selectWord();
		this.selectCell();

		$(nextCell+'_input').focus();
	}

	this.jumpNext = function(startPos, increment, fallback) {
		var baseId = this.ePuzzle.puzzleContainer;

		var xWord = this.xWord;
		var grid = xWord.grid;

		var i = 0;

		nextCell = undefined;
		while(!nextCell) {
			if((startPos + (i*increment)) > (grid[0] * grid[1])) {
				nextCell = fallback;
			} else {
				var cellId = baseId + '_' + (startPos + (i*increment));

				if($(cellId+'_input')) {
					nextCell = cellId;
				}

				i++;
			}
		}

		return nextCell;
	}

	this.jumpPrev = function(startPos, increment, fallback) {
		var baseId = this.ePuzzle.puzzleContainer;

		var xWord = this.xWord;
		var grid = xWord.grid;

		var i = 0;

		prevCell = undefined;
		while(!prevCell) {
			if((startPos + (i*increment)) < 0) {
				prevCell = fallback;
			} else {
				var cellId = baseId + '_' + (startPos + (i*increment));

				if($(cellId+'_input')) {
					prevCell = cellId;
				}

				i--;
			}
		}

		return prevCell;
	}

	this.selectCellWord = function(targetElement, clueDirection) {
		this.deSelectWord();

		this.selectedCell = targetElement;

		if(clueDirection) {
			if(this.selectedCell.words.length > 1) {
				this.selectedWord = this.selectedCell.words[clueDirection];
			} else {
				this.selectedWord = this.selectedCell.words[0];
			}
		} else {
			if(this.selectedCell.words.length > 1) {
				if(this.selectedWord == this.selectedCell.words[0]) {
					this.selectedWord = this.selectedCell.words[1];
				} else {
					this.selectedWord = this.selectedCell.words[0];
				}
			} else {
				this.selectedWord = this.selectedCell.words[0];
			}
		}

		this.selectWord();
		this.selectCell();

		if(this.selectedCell.words.length > 1) {
			return true;
		}

		return false;
	}

	this.findCheckSum = function(original) {
		this.xWordCheckSum = '';

		for(var i = 0; i < this.xWord.words.length; i++) {
			var writtenWord = this.painter.findWrittenWord(this.xWord.words[i]);
			var checkWord = writtenWord.toLowerCase();

			if(!original) {
				checkWord = strReplace(checkWord,'æ','a');
				checkWord = strReplace(checkWord,'ø','o');
				checkWord = strReplace(checkWord,'å','a');
				checkWord = strReplace(checkWord,'l','1');
				checkWord = strReplace(checkWord,'t','7');
				checkWord = strReplace(checkWord,'s','5');
				checkWord = strReplace(checkWord,'a','4');
				checkWord = strReplace(checkWord,'e','3');
			} else {
				checkWord = strReplace(checkWord,'æ','%E6');
				checkWord = strReplace(checkWord,'ø','%F8');
				checkWord = strReplace(checkWord,'å','%E5');
			}

			this.xWordCheckSum += checkWord;
		}
	}

	this.loadStoredData = function(storedData) {
		var storedDataOffset = 0;

		for(var i = 0; i < this.xWord.words.length; i++) {
			var wordDirection	= this.xWord.words[i][0];
			var startPosition	= this.xWord.words[i][1];
			var wordLength		= this.xWord.words[i][2];
			var storedWord		= stringPart(storedData,storedDataOffset,wordLength);

			for(var j = 0; j < wordLength; j++) {
				if(wordDirection == 0) {
					this.painter.setCharacter(startPosition+j,storedWord.substring(j,j+1));
				}

				if(wordDirection == 1) {
					this.painter.setCharacter(startPosition+(j*this.xWord.grid[0]),storedWord.substring(j,j+1));
				}
			}

			storedDataOffset += wordLength;
		}

		this.setSaveState('SAVED');
	}

	this.checkWord = function(word, cascade) {
		this.setSaveState('CHANGED');

		var targetCheckSum = word[4];

		var writtenWord = this.painter.findWrittenWord(word);

		var checkWord = writtenWord.toLowerCase();
		checkWord = strReplace(checkWord,'æ','ae');
		checkWord = strReplace(checkWord,'ø','oe');
		checkWord = strReplace(checkWord,'å','aa');

		if(hex_md5(checkWord) == targetCheckSum) {
			this.xWordCheckSum = targetCheckSum;
			//eXWord.stateMessage = 'Riktig: ' + writtenWord;
			//eXWord.setState('IDLE');

			var solved = true;
			if(cascade != false) {
				for(var i = 0; solved && (i < this.xWord.words.length); i++) {
					if(solved && !this.checkWord(this.xWord.words[i], false)) {
						solved = false;
					}
				}

				if(solved) {
					var myWords = '';
					this.xWordCheckSum = '';
					for(var i = 0; i < this.xWord.words.length; i++) {
						var writtenWord = this.painter.findWrittenWord(this.xWord.words[i]);
						var checkWord = writtenWord.toLowerCase();

						checkWord = strReplace(checkWord,'æ','ae');
						checkWord = strReplace(checkWord,'ø','oe');
						checkWord = strReplace(checkWord,'å','aa');
						checkWord = strReplace(checkWord,'l','1');
						checkWord = strReplace(checkWord,'t','7');
						checkWord = strReplace(checkWord,'s','5');
						checkWord = strReplace(checkWord,'a','4');
						checkWord = strReplace(checkWord,'e','3');

						this.xWordCheckSum += checkWord;
						//this.xWordCheckSum += hex_md5(checkWord);
						//this.xWordCheckSum = hex_md5(this.xWordCheckSum);
					}
				}
			}

			return solved;
		}

		return false;
	}

	this.checkStatus = function() {
		// Update XWordTimer
		if(this.xwordStart == 0) {
			if(this.xWord.startTs) {
				this.xwordStart = (this.xWord.startTs*1000);
			} else {
				this.xwordStart = new Date().getTime();
			}
		}
		this.xwordTimer = new Date().getTime() - this.xwordStart;

		var hours	= 0;
		var minutes = 0;
		var timeString = '';

		var totalTime = Math.floor(this.xwordTimer/1000);
		if(totalTime > 3600) {
			hours = Math.floor(totalTime/3600);
			totalTime = totalTime - (hours*3600);
			if(hours > 1) {
				timeString = hours + ' timer ';
			} else {
				timeString = hours + ' time ';
			}
		}

		if(totalTime > 60) {
			minutes = Math.floor(totalTime/60);
			totalTime = totalTime - (minutes*60);
			timeString += minutes + ' min ';
		}

		timeString += totalTime + ' sek';

		if(((totalTime%60) == 0) || (this.forceSave)) {
			this.forceSave = false;
			this.findCheckSum(true);

			URL = this.baseUrl+puzzleLoader.puzzleIdentifier+'&apimode=statusUpdate';
			postBody = 'sVer=3.0&xWordCheckSum=' + this.xWordCheckSum;

			if(URL != '') {
				this.setSaveState('SAVED');
				new Ajax.Request(URL, {
					method: 'POST',
					postBody: postBody,
					onSuccess: function(response) {
						try {
							result = JSON.parse(response.responseText);
						} catch(e) {
							switch(e.name) {
								case 'TypeError':
									puzzleLoader.puzzle.errorMessage = e.message;
								break;

								default:
									puzzleLoader.puzzle.errorMessage = 'Feil';
							}

							puzzleLoader.puzzle.setState('ERROR');
						}
					}
				});
			}
		}

		puzzleLoader.puzzle.stateMessage = '';
		puzzleLoader.puzzle.setState('IDLE');
	}

	this.performRequest = function(URL, postBody) {
		if(URL != '') {
			new Ajax.Request(URL, {
				method: 'POST',
				postBody: postBody,
				onSuccess: function(response) {
					try {
						result = JSON.parse(response.responseText);
						if(result.result == 'saved') {

						}

						if(result.result == 'solution') {
							puzzleLoader.puzzle.puzzleMode = 'SOLVED';
							puzzleLoader.puzzle.xWord.endTs = result.endTs;
							puzzleLoader.puzzle.xWord.score = result.newScore;

							for(index in result.solution) {
								puzzleLoader.puzzle.painter.setCharacter(index, result.solution[index]);
							}
						}

						if(result.result == 'completed') {
							puzzleLoader.puzzle.puzzleMode = 'SOLVED';
							puzzleLoader.puzzle.xWord.endTs = result.endTs;
							puzzleLoader.puzzle.xWord.score = result.newScore;
						}

						if(result.result == 'submitted') {
							puzzleLoader.puzzle.puzzleMode = 'SOLVED';
							puzzleLoader.puzzle.xWord.endTs = result.endTs;
							puzzleLoader.puzzle.xWord.score = result.score;

							openPuzzleResult(result.score);
						}

						if(result.result == 'word') {
							var increment	= parseInt(result.wDi) ? parseInt(puzzleLoader.puzzle.xWord.grid[0]) : 1;
							var position	= parseInt(result.wId);

							for(var i = 0; i < result.letters.length; i++) {
								letter = result.letters[i];
								puzzleLoader.puzzle.painter.setCharacter(position, letter[2]);
								position += parseInt(increment);
							}
						}

						if(result.result == 'letter') {
							var letter		= result.letter;
							var position	= parseInt(result.wCh) + 1;

							puzzleLoader.puzzle.painter.setCharacter(position, letter);
						}
					} catch(e) {
						switch(e.name) {
							case 'TypeError':
								puzzleLoader.puzzle.errorMessage = e.message;
							break;

							default:
								puzzleLoader.puzzle.errorMessage = 'Feil';
						}

						puzzleLoader.puzzle.setState('ERROR');
					}
				}
			});
		}
	}

	this.controlListener = function(event) {
		var targetElement = Event.element(event);

		switch(event.type) {
			case 'click':
				var URL = '';
				var postBody = '';

				if(stringPart(targetElement.id,-12) == 'submitButton') {
					this.ePuzzle.confirm("Er du sikker på at du vil sende inn din besvarelse?\n", function(confirmed) {
						if(!confirmed) return;

						puzzleLoader.puzzle.findCheckSum();
						URL = puzzleLoader.puzzle.baseUrl+puzzleLoader.puzzleIdentifier+'&apimode=submitPuzzle';
						postBody = 'sVer=3.0&xWordCheckSum=' + puzzleLoader.puzzle.xWordCheckSum;

						puzzleLoader.puzzle.performRequest(URL,postBody);
					});
				}

				if(stringPart(targetElement.id,-10) == 'saveButton') {
					this.forceSave = true;
					return;
				}

				if(stringPart(targetElement.id,-11) == 'resetButton') {
					var cells = this.xWord.grid[0]*this.xWord.grid[1];
					for(var i = 1; i <= cells; i++) {
						this.painter.setCharacter(i, ' ');
					}
					return;
				}

				if(stringPart(targetElement.id,-11) == 'solveButton') {
					this.ePuzzle.confirm("Er du sikker på at du vil se fasiten?\n\nDersom du velger å vise fasiten vil du ikke\nlenger kunne få poeng for oppgaven.", function(confirmed) {
						if(!confirmed) return;

						puzzleLoader.puzzle.findCheckSum();
						URL = puzzleLoader.puzzle.baseUrl+puzzleLoader.puzzleIdentifier+'&apimode=solvePuzzle';
						postBody = 'sVer=3.0&xWordCheckSum=' + puzzleLoader.puzzle.xWordCheckSum;

						puzzleLoader.puzzle.performRequest(URL,postBody);
					});
				}

				if(stringPart(targetElement.id,-15) == 'solveWordButton') {
					this.ePuzzle.confirm("Er du sikker på at du vil se fasit for dette ordet?\n\nDersom du velger å vise fasiten vil du miste 1 poeng pr. bokstav.", function(confirmed) {
						if(!confirmed) return;

						URL = '';
						// There is no need to poll the server if the word is correct.
						// No points will be deducted if the word is correct...
						if(!puzzleLoader.puzzle.checkWord(puzzleLoader.puzzle.selectedWord, false)) {
							URL = puzzleLoader.puzzle.baseUrl+puzzleLoader.puzzleIdentifier+'&apimode=solvePuzzle';
							postBody = 'sVer=3.0&solveMode=word&wIn=' + puzzleLoader.puzzleDisplay.findWrittenWord(puzzleLoader.puzzle.selectedWord) + '&wId=' + puzzleLoader.puzzle.selectedWord[1] + '&wDi=' + puzzleLoader.puzzle.selectedWord[0];

							puzzleLoader.puzzle.performRequest(URL,postBody);
						}
					});
				}

				if(stringPart(targetElement.id,-17) == 'solveLetterButton') {
					this.ePuzzle.confirm("Er du sikker på at du vil se fasit for denne bokstaven?\n\nDersom du velger å vise fasiten vil du miste 1 poeng.", function(confirmed) {
						if(!confirmed) return;
	
						var character = puzzleLoader.puzzle.painter.getCharacter();
						URL = puzzleLoader.puzzle.baseUrl+puzzleLoader.puzzleIdentifier+'&apimode=solvePuzzle';
						postBody = 'sVer=3.0&solveMode=letter&wLt=' + character[1] + '&wCh=' + character[0];

						puzzleLoader.puzzle.performRequest(URL,postBody);
					});
				}

				if(stringPart(targetElement.id,-15) == 'nklSearchButton') {
					var containerPosition = $(targetElement.id).positionedOffset();
					var x = containerPosition['left'];
					var y = containerPosition['top'];
					x += 150;				
					y -= 250;
					 
					if(this.selectedWord && this.selectedWord[3]) {
						var writtenWord = this.painter.findWrittenWord(this.selectedWord)
						var checkWord = writtenWord.toLowerCase();
						
						checkWord = checkWord.replace(/ /g, '?');		
						
						nklSearch2(this.selectedWord[3][2], checkWord, x, y);
					} else {
						nklSearch2('','', x, y);
					}
				}
			break;
		}
	}

	this.eventListener = function(event) {
		var targetElement = Event.element(event);
		var baseId = this.ePuzzle.puzzleContainer;

		switch(event.type) {
			case 'click':
				if(targetElement.id.substring(0,14) == baseId + '_clues') {
					var clueDirection	= targetElement.id.substring(15,16);
					
					if(stringPart(targetElement.id,-5) == 'index') {
						var clueId = stringPart(targetElement.id,17,-6)-1;
					} else if(stringPart(targetElement.id,-4) == 'text') {
						var clueId = stringPart(targetElement.id,17,-5)-1;
					} else {
						var clueId = targetElement.id.substring(17)-1;
					}
					var input			= baseId + '_' + clueId + '_input';

					this.selectCellWord($(input), clueDirection);
					$(input).focus();
				} else {
					this.selectCellWord(targetElement);
				}
			break;

			case 'keydown':
			case 'keypress':
				switch(event.keyCode) {
					case Event.KEY_RIGHT:
					case Event.KEY_LEFT:
					case Event.KEY_DOWN:
					case Event.KEY_UP:
					case Event.KEY_DELETE:
					case Event.KEY_BACKSPACE:
						Event.stop(event);
					break;

					default:
						if(targetElement.value.length > 0) {
							targetElement.value = '';
						}
						var charCode = event.charCode ? event.charCode : event.keyCode;
						var inputChar = '';

						switch(charCode) {
							case 222: inputChar = 'Æ'; break;
							case 192: inputChar = 'Ø'; break;
							case 221: inputChar = 'Å'; break;
							default: inputChar = String.fromCharCode(charCode);
						}

						// Special characters
						if(
							(inputChar != '\\') &&
							(inputChar != '*') &&
							(inputChar != "'") &&
							(inputChar != '+') &&
							(inputChar != '%') &&
							(inputChar != '&') &&
							(inputChar != '(') &&
							(inputChar != ')') &&
							(inputChar != '.') &&
							(inputChar != '?')) {
							var match = this.charSet.match(inputChar.capitalize());
						}

						if(match && (match != null)) {
							targetElement.value = this.charSet.match(inputChar.capitalize());
							this.selectNextCell(true);

							this.checkWord(this.selectedWord);
						}

						Event.stop(event);
					break;
				}
			break;

			case 'keyup':
				var xWord = this.xWord;
				var grid = xWord.grid;

				var word = this.selectedWord;
				var increment = word[0] ? grid[0] : 1;
				var currentCell = $(this.selectedCell.id).up().id;
				var cellId;

				for(var i = 0; i < word[2]; i++) {
					cellId = baseId + '_' + ((word[1]-1) + (i*increment));
					if(cellId == currentCell) var startPos = (word[1]-1) + (i*increment);
				}

				switch(event.keyCode) {
					case Event.KEY_DELETE:
						if(BrowserDetect.browser == 'Explorer') {
							if(targetElement.value == '') {
								this.selectNextCell();
							} else {
								this.selectedCell.value = '';
								this.selectNextCell();
							}
						} else {
							if(targetElement.value == '') {
								this.selectNextCell();
							}
							this.selectedCell.value = '';
						}
						this.checkWord(this.selectedWord);
						Event.stop(event);
					break;

					case Event.KEY_BACKSPACE:
						if(targetElement.value == '') {
							this.selectPrevCell();
						}
						this.selectedCell.value = '';
						this.checkWord(this.selectedWord);
						Event.stop(event);
					break;

					case Event.KEY_RIGHT:
						if(this.selectedWord[0] == 0) {
							this.selectNextCell();
						} else {
							if(this.selectCellWord(targetElement)) {
								this.selectNextCell();
							} else {
								nextCell = currentCell;
								this.selectedCell = $(currentCell+'_input');
								this.deSelectWord();

								var increment = (1-word[0]) ? grid[0] : 1;
								startPos += increment;
								var nextCell = this.jumpNext(startPos, increment, currentCell);

								this.selectedCell = $(nextCell+'_input');
								this.selectCellWord(this.selectedCell, (1-word[0]));
								this.selectCell();

								$(nextCell+'_input').focus();
							}
						}
					break;

					case Event.KEY_LEFT:
						if(this.selectedWord[0] == 0) {
							this.selectPrevCell();
						} else {
							if(this.selectCellWord(targetElement)) {
								this.selectPrevCell();
							} else {
								nextCell = currentCell;
								this.selectedCell = $(currentCell+'_input');
								this.deSelectWord();

								var increment = (1-word[0]) ? grid[0] : 1;
								startPos -= parseInt(increment);
								var nextCell = this.jumpPrev(startPos, increment, currentCell);

								this.selectedCell = $(nextCell+'_input');
								this.selectCellWord(this.selectedCell, (1-word[0]));
								this.selectCell();

								$(nextCell+'_input').focus();
							}
						}
					break;

					case Event.KEY_DOWN:
						if(this.selectedWord[0] == 1) {
							this.selectNextCell();
						} else {
							if(this.selectCellWord(targetElement)) {
								this.selectNextCell();
							} else {
								nextCell = currentCell;
								this.selectedCell = $(currentCell+'_input');
								this.deSelectWord();

								var increment = (1-word[0]) ? grid[0] : 1;
								startPos += parseInt(increment);
								var nextCell = this.jumpNext(startPos, increment, currentCell);

								this.selectedCell = $(nextCell+'_input');
								this.selectCellWord(this.selectedCell, (1-word[0]));
								this.selectCell();

								$(nextCell+'_input').focus();
							}
						}
					break;

					case Event.KEY_UP:
						if(this.selectedWord[0] == 1) {
							this.selectPrevCell();
						} else {
							if(this.selectCellWord(targetElement)) {
								this.selectPrevCell();
							} else {
								nextCell = currentCell;
								this.selectedCell = $(currentCell+'_input');
								this.deSelectWord();

								var increment = (1-word[0]) ? grid[0] : 1;
								startPos -= increment;
								var nextCell = this.jumpPrev(startPos, increment, currentCell);

								this.selectedCell = $(nextCell+'_input');
								this.selectCellWord(this.selectedCell, (1-word[0]));
								this.selectCell();

								$(nextCell+'_input').focus();
							}
						}
					break;
				}
			break;
		}
	}
}

function strReplace(string, search, replace) {
	var match = string.replace(search, replace);

	while(match != string) {
		string	= match;
		match	= string.replace(search, replace);
	}

	return string;
}