TypingExamination.prototype = Object.create(Phaser.State.prototype);
TypingExamination.constructor = TypingExamination;

function TypingExamination() {
}

TypingExamination.prototype.preload = function() {
	game.load.image('icon_fullscreen',	'../../../resources/image/icon/fullscreen_white.png');

	Animal.loadResources();

	game.load.script('webfont', '//ajax.googleapis.com/ajax/libs/webfont/1.4.7/webfont.js');
}

TypingExamination.prototype.create = function() {
	Phaser.Device.whenReady(function () {
		game.plugins.add(PhaserInput.Plugin);
	});

	this.dbService = new DBService();
	this.dbService.setMaestroID(sessionStorageManager.getMaestroID());
	this.dbService.setPlayerID(sessionStorageManager.getPlayerID());

	sessionStorageManager.setRecord(0);

	this.initialize();
	sessionStorageManager.setIsNewAppHighestRecord(false);

	var experienceAppTimer = new ExperienceAppTimer();
	experienceAppTimer.setTimeOverListener(
		(function() { this.timeOver(); }).bind(this)
	);

	game.stage.backgroundColor = TypingExamination.COLOR_STAGE_BACKGROUND_STRING;

	// keyboard shortcut - useless. this.keyboard is chargning for ESC event
	this.keyboardShortcut = new KeyboardShortcut();
	this.keyboardShortcut.addCallback(
		Phaser.KeyCode.ESC,	// keyCode
		null,	// keyDownHandler
		(function() { this.back(); }).bind(this),	// keyUpHandler
		"typing_examination"	// callerClassName
	);

	// top ui
	var screenTopUI = new ScreenTopUI();
	screenTopUI.makeBackButton( (function() { this.back(); }).bind(this) );
	screenTopUI.makeFullScreenButton();


	this.averageTypingSpeedText = new AverageTypingSpeed();

	this.textTimer = null;
	this.realtimeStageTimer = new RealtimeStageTimer(TypingExamination.GAME_TIME_SEC);
	this.realtimeStageTimer.setTimeUpdateEvent(
		(function(timeLeftSec) {
			if(this.textTimer === null)
				return;

			var timeLeft = TimeUtil.printHHMMSSFromSec(timeLeftSec);
			if(timeLeft !== this.textTimer.text) {
				this.textTimer.text = TimeUtil.printHHMMSSFromSec(timeLeftSec);

				this.updateCorrectUnicodeLetterCount();
				this.updateTypingRecord();
			}
		}).bind(this)
	);
	this.realtimeStageTimer.setTimeOverEvent(
		(function() {
			this.isGameOver = true;

			this.textTimer.text = "타임 오버";
			console.log("Time over");

			this.updateCorrectUnicodeLetterCount();
			this.updateTypingRecord();

			this.timeOver();
		}).bind(this)
	);


	// bottom ui
	var screenBottomUI = new ScreenBottomUI();
	screenBottomUI.printLeftTextWithAppHighestRecord(sessionStorageManager.getAppHighestRecord());
	screenBottomUI.printCenterText(sessionStorageManager.getPlayingAppKoreanName());
	screenBottomUI.printRightText(sessionStorageManager.getPlayerName());

	// this.countDown();
}

TypingExamination.prototype.initialize = function() {
	this.typingIndex = 0;

	this.isGameOver = false;
	this.isTyping = false;
	this.isTypingLine = false;

	this.timeTypingStart = 0;
	this.timeTypingEnd = 0;

	this.correctLetterCountInLine = 0;
	this.correctSyllableLetterCountInAllLines = 0;

	this.typingRecordTotal = 0;
	this.animalLevelID = -1;
}


TypingExamination.prototype.fontLoaded = function() {
	this.makeAnimalRecordList();
	// this.animalRecordList.hide();
	this.animalRecordList.applyLoadedFont();

	this.makeStageTimerText();
	this.makeTextContents();
}

TypingExamination.prototype.makeDefaultText = function(x, y) {
	var defaultText = game.add.text(x, y, "");
	defaultText.anchor.set(0, 0.5);
	defaultText.font = "Nanum Gothic Coding";
	defaultText.fontSize = TypingExamination.DEFAULT_FONT_SIZE;
	defaultText.fontWeight = "normal";
	defaultText.style.fill = "white";

	return defaultText;
}

TypingExamination.prototype.makeStageTimerText = function() {
	this.textTimer = this.makeDefaultText(960, 30);
	this.textTimer.anchor.set(1, 0.5);
	this.textTimer.fontSize = 30;
	this.textTimer.text = TimeUtil.printHHMMSSFromSec(TypingExamination.GAME_TIME_SEC);
}

TypingExamination.prototype.makeUnderlineText = function(x, y) {
	var CONTENT_TEXT_WIDTH	= 800;
	var CONTENT_UNDERLINE_OFFSET_Y = 20;	// 17;

	var graphics = game.add.graphics(0, 0);
	graphics.lineStyle(1, 0x303030, 1);
	graphics.moveTo(x, y + CONTENT_UNDERLINE_OFFSET_Y);
	graphics.lineTo(x + CONTENT_TEXT_WIDTH, y + CONTENT_UNDERLINE_OFFSET_Y);

	var underlineText = this.makeDefaultText(x, y);
	underlineText.setShadow(3, 3, 'rgba(0, 0, 0, 0.5)', 2)

	return underlineText;
}

TypingExamination.prototype.makeLineText = function(x, y) {
	var lineText = this.makeDefaultText(x, y);
	lineText.anchor.set(1, 0.5);

	return lineText;
}

TypingExamination.prototype.makeInputlineText = function(x, y) {
	var CONTENT_TEXT_WIDTH	= 800;
	var CONTENT_UNDERLINE_OFFSET_Y = 17;
	var TYPING_CONTENT_UNDERLINE_OFFSET_Y = 5;

	// current text
	this.textBackTextOnly = this.makeDefaultText(x, y);
	this.textBackTextOnly.fontSize = TypingExamination.DEFAULT_FONT_SIZE;
	this.textBackTextOnly.style.fill = TypingExamination.COLOR_NOT_INPUT_STRING;
	this.textBackTextOnly.setShadow(3, 3, 'rgba(0, 0, 0, 0.5)', 2)

	this.textNextLetterIndicator = this.makeDefaultText(x, y);
	this.textNextLetterIndicator.fontSize = TypingExamination.DEFAULT_FONT_SIZE;
	this.textNextLetterIndicator.style.fill = TypingExamination.COLOR_NEXT_INPUT_STRING;
	this.textNextLetterIndicator.setShadow(3, 3, 'rgba(0, 0, 0, 0.5)', 2)
	this.textNextLetterIndicator.style.backgroundColor = TypingExamination.COLOR_NEXT_INPUT_BACKGROUND_STRING;

	this.textCorrectText = this.makeDefaultText(x, y);
	this.textCorrectText.fontSize = TypingExamination.DEFAULT_FONT_SIZE;
	this.textCorrectText.style.fill = TypingExamination.COLOR_CORRECT_INPUT_STRING;
	this.textCorrectText.setShadow(3, 3, 'rgba(0, 0, 0, 0.5)', 2)
	this.textCorrectText.style.backgroundColor = TypingExamination.COLOR_CORRECT_INPUT_BACKGROUND_STRING;

	var graphics = game.add.graphics(0, 0);
	graphics.lineStyle(1, 0x303030, 1);
	graphics.moveTo(x, y + CONTENT_UNDERLINE_OFFSET_Y + TYPING_CONTENT_UNDERLINE_OFFSET_Y);
	graphics.lineTo(x + CONTENT_TEXT_WIDTH, y + CONTENT_UNDERLINE_OFFSET_Y + TYPING_CONTENT_UNDERLINE_OFFSET_Y);

}

TypingExamination.prototype.makeTextContents = function() {
	// typing content
	var CONTENT_TEXT_WIDTH			= 800;

	var TYPING_CONTENT_X			= 150;
	var TYPING_CONTENT_Y			= 340;

	var LINE_POS_X					= 130;

	var INPUT_TEXT_OFFSET_X			= 10;
	var INPUT_TEXT_OFFSET_Y			= 60;

	var DONE_OFFSET_Y				= 0;
	var INPUT_OFFSET_Y				= 120;
	var PREVIEW_OFFSET_Y			= 170;

	var TEXT_HEIGHT					= 50;


	// input content
	this.makeInputlineText(TYPING_CONTENT_X, TYPING_CONTENT_Y + INPUT_OFFSET_Y);
	this.textTypingLine = this.makeLineText(LINE_POS_X, TYPING_CONTENT_Y + INPUT_OFFSET_Y);


	// typed done contents
	this.textTypingContentsDone = [];
	this.textTypingRecordArray = [];
	for(var i = 0; i < TypingExamination.TYPING_CONTENT_DONE_COUNT; i++) {
		this.textTypingContentsDone[i] = this.makeUnderlineText(
			TYPING_CONTENT_X,
			TYPING_CONTENT_Y - DONE_OFFSET_Y - i * TEXT_HEIGHT
		);
		this.textTypingContentsDone[i].style.fill = TypingExamination.COLOR_DONE_INPUT_STRING;
		this.textTypingContentsDone[i].style.backgroundColor = TypingExamination.COLOR_CORRECT_INPUT_BACKGROUND_STRING;

		this.textTypingRecordArray[i] = this.makeLineText(
			LINE_POS_X,
			TYPING_CONTENT_Y - DONE_OFFSET_Y - i * TEXT_HEIGHT
		);
	}

	// preview contents
	this.textTypingContentPreview = [];
	this.textPreviewLineNumber = [];
	for(var i = 0; i < TypingExamination.TYPING_CONTENT_PREVIEW_COUNT; i++) {
		this.textTypingContentPreview[i] = this.makeUnderlineText(
			TYPING_CONTENT_X,
			TYPING_CONTENT_Y + PREVIEW_OFFSET_Y + i * TEXT_HEIGHT
		);
		this.textTypingContentPreview[i].style.fill = TypingExamination.COLOR_NOT_INPUT_STRING;

		this.textPreviewLineNumber[i] = this.makeLineText(
			LINE_POS_X,
			TYPING_CONTENT_Y + PREVIEW_OFFSET_Y + i * TEXT_HEIGHT
		);
	}


	// input text
	var setting = {
		// font: "26px Arial",
		font: "26px Nanum Gothic Coding",
		// fontSize: TypingExamination.DEFAULT_FONT_SIZE,
		// fontFamily: "Nanum Gothic Coding",
		fill: "#000000",
		fillAlpha: 1,
		fontWeight: "bold",
		forceCase: "",	// PhaserInput.ForceCase.upper,
		width: 800,
		max: 100,
		padding: 8,
		borderWidth: 1,
		borderColor: "#000",	// "#aaa",
		borderRadius: 6,
		placeHolder: "",	// "입력이 없을 때 출력될 내용",
		textAlign: "left",	// "center",
		zoom: true
	};
	this.inputText = game.add.inputField(
		TYPING_CONTENT_X - INPUT_TEXT_OFFSET_X + 2,
		TYPING_CONTENT_Y + INPUT_TEXT_OFFSET_Y - 18,
		// TYPING_CONTENT_Y + INPUT_TEXT_OFFSET_Y - 100,
		setting
	);
	this.inputText.keyListener = (function(evt) {
		// onKeyDown x 2 (?)
		// onKeyUp

		this.value = this.getFormattedText(this.domElement.value);
		// console.log(this.value + "|");

		// if (evt.keyCode === 13) {
		// 	if (this.focusOutOnEnter) {
		// 		this.endFocus();
		// 	}
		// 	return;
		// }

		this.updateText();
		this.updateCursor();
		this.updateSelection();

		if(typingExamination.isGameOver)
			return;

		// console.log(evt);
		if(typeof evt.keyCode === "undefined"){
			// console.log("undefined");
			typingExamination.onKeyDown2(this.value);
		} else {
			// console.log(evt);
			typingExamination.onKeyDown(evt, this.value);
		}

		evt.preventDefault();
	});//.bind(this);
	this.inputText.setText('');
	this.inputText.blockInput = true;
	this.inputText.startFocus();


	this.loadExaminationContent();
}

/*
countDown() {
	var style = { font: "bold 200px Arial", fill: "#fff", boundsAlignH: "center", boundsAlignV: "middle" };
	this.countDownText = game.add.text(0, 0, "", style);
	this.countDownText.setTextBounds(0, 0, game.world.width, game.world.height);
	this.countDownText.stroke = "#333";
	this.countDownText.strokeThickness = 50;

	this.countDownNumber = 3;
	if(isDebugMode())
		this.countDownNumber = 1;
	this.tweenCountDown();
}

tweenCountDown() {
	if(this.countDownNumber === 0) {
		this.startGame();
		return;
	}

	this.countDownText.text = this.countDownNumber.toString();
	this.countDownText.alpha = 1;

	var countDownTween = game.add.tween(this.countDownText);
	countDownTween.to( { alpha: 0 }, GAME_SCREEN_SIZE.x, Phaser.Easing.Linear.None, true);
	countDownTween.onComplete.add(this.tweenCountDown, this);

	this.countDownNumber--;
}
*/

TypingExamination.prototype.makeAnimalRecordList = function() {
	this.animalRecordList = new AnimalRecordList(Animal.TYPE_EXAM);
	this.animalRecordList.printScore(Animal.TYPE_EXAM);
}


TypingExamination.prototype.back = function() {
	sessionStorageManager.resetPlayingAppData();
	location.href = '../../web/client/main_menu.html';
}

TypingExamination.prototype.startGame = function() {
	this.averageTypingSpeedText.print(0);

	this.showTypingExaminationContents();
	this.showPlayingWordNumber();

	// this.realtimeStageTimer.start();
}

TypingExamination.prototype.timeOver = function() {
	var timeOverText = new TimeOverText();
	sessionStorageManager.setRecord(-1 * this.typingRecordTotal);
	if(!isExperienceMaestroAccount())
		this.updateResultRecord();

	this.stopAndGoResult();
}

TypingExamination.prototype.gameOver = function() {
	this.realtimeStageTimer.pause();
	var missionClearText = new MissionClearText();

	sessionStorageManager.setRecord(this.typingRecordTotal);
	if(!isExperienceMaestroAccount())
		this.updateResultRecord();

	this.stopAndGoResult();

}

TypingExamination.prototype.stopAndGoResult = function() {
	this.animalRecordList.stopAnimation();

	game.time.events.add(Phaser.Timer.SECOND * 2, this.goResult, this);
}

TypingExamination.prototype.updateResultRecord = function() {
	if(sessionStorageManager.getMaestroAccountType() < 100) {	// experience account
		this.dbService.updateTypingExamRecord(
			sessionStorageManager.getWritingID(),
			sessionStorageManager.getRecord(),
			(function(replyJSON) {
				console.log(replyJSON);
			}).bind(this),
			(function(replyJSON) {
				console.log(replyJSON);
			}).bind(this)
		);
	}
}

TypingExamination.prototype.goResult = function() {
	location.href = '../../web/client/result.html';
}


TypingExamination.prototype.loadExaminationContent = function() {
	this.dbService.requestWritingInfo(
		sessionStorageManager.getWritingID(),
		(function(jsonData) {		// onSucceeded
			this.downloadListSucceeded(jsonData);
		}).bind(this),
		(function(jsonData) {		// onFailed
			this.downloadListFailed(jsonData);
		}).bind(this)
	);
}

TypingExamination.prototype.downloadListSucceeded = function(jsonData) {
	// console.log(jsonData);
	var writingInfo = jsonData["writingInfo"];
	// console.log(writingInfo);

	var writer = writingInfo["writer"];
	var writerID = "";
	writingInfo["writerID"] == null ? writerID = "" : writerID = writingInfo["writerID"];

	var path = "./../../../resources/file/typing_exam/";
	var directory = writer + writerID + "/";
	var filename = writingInfo["filename"];
	var url = path + directory + filename;
	// if(isDebugMode()) {
	// 	url = path + "system/sample.txt";
	// 	console.log(url);
	// }

	game.load.onLoadComplete.add(this.completeLoadingWriting, this);
	game.load.text("writing", url);
	game.load.start();
}

TypingExamination.prototype.downloadListFailed = function(jsonData) {
	console.log(jsonData);
}

TypingExamination.prototype.completeLoadingWriting = function() {
	game.load.onFileComplete.remove(this.loadExaminationContent, this);
	game.load.onLoadComplete.remove(this.completeLoadingWriting, this);

	var writing = game.cache.getText("writing");
	// console.log(writing);
	var examinationContent = writing.split("\n");

	var count = examinationContent.length;
	for(var i = 0; i < count; i++) {
		// add enter character
		// examinationContent[i] = examinationContent[i].replace(/\r/g, "");
		// console.log(examinationContent[i]);
		if(examinationContent[i] == "\r")
			examinationContent[i] = examinationContent[i].replace(/\r/g, "");
		else
			examinationContent[i] = examinationContent[i].replace(/\r/g, TypingExamination.ENTER_INDICATOR);

		// add space indicator character
		// examinationContent[i] = examinationContent[i].replace(/ /g, TypingExamination.SPACE_INDICATOR);
	}

	// console.log('playingStageData.language : ' + playingStageData.language);
	// console.log('playingStageData.level : ' + playingStageData.level);
	// console.log('examinationContent : ' + examinationContent);

	var typingTextMan = new TypingTextManager();
	typingTextMan.makeExaminationContents(examinationContent);
	this.typingExaminationContents = typingTextMan.getContents();
	// console.log(this.typingExaminationContents.length);
	// console.log(this.typingExaminationContents[this.typingExaminationContents.length - 1]);

	var lastSentence = this.typingExaminationContents[this.typingExaminationContents.length - 1];
	if(lastSentence[lastSentence.length - 1] !== TypingExamination.ENTER_INDICATOR)
		this.typingExaminationContents[this.typingExaminationContents.length - 1] += TypingExamination.ENTER_INDICATOR;
	// console.log(this.typingExaminationContents);

	this.typingRecordArray = [];
	this.typingElapsedTime = [];
	this.typingContentLength = this.typingExaminationContents.length;
	for(var i = 0; i < this.typingContentLength; i++) {
		this.typingRecordArray[i] = 0;
		this.typingElapsedTime[i] = 0;
	}

	this.startGame();
}

TypingExamination.prototype.setTypingContentText = function(text) {
	this.textBackTextOnly.text = text;
	this.textNextLetterIndicator.text = text.substring(0, 1);
}

TypingExamination.prototype.setCorrectText = function(text) {
	this.textCorrectText.text = text;
}

TypingExamination.prototype.showTypingExaminationContents = function() {
	for(var i = 0; i < TypingExamination.TYPING_CONTENT_DONE_COUNT; i++) {
		var doneIndex = this.typingIndex - i - 1;
		if(doneIndex < 0) {
			this.textTypingContentsDone[i].text = "";
			this.textTypingRecordArray[i].text = "";
		} else {
			// console.log(this.typingExaminationContents[doneIndex] + "/");
			this.textTypingContentsDone[i].text = this.typingExaminationContents[doneIndex];

			// console.log(this.typingRecordArray);
			var typingRecordIndex = this.typingIndex - 1 - i;
			// console.log(typingRecordIndex);
			var typingRecord = this.typingRecordArray[typingRecordIndex];
			this.textTypingRecordArray[i].text = NumberUtil.getRecordText(typingRecord);
		}
	}

	if(this.typingIndex == this.typingContentLength) {
		this.setTypingContentText("");
		this.setCorrectText("");
		return;
	}

	var contentText = this.typingExaminationContents[this.typingIndex];
	this.setTypingContentText(contentText);

	for(var i = 0; i < TypingExamination.TYPING_CONTENT_PREVIEW_COUNT; i++) {
		var previewIndex = this.typingIndex + i + 1;
		if(previewIndex < this.typingExaminationContents.length) {
			this.textTypingContentPreview[i].text = this.typingExaminationContents[previewIndex];

			var lineNumber = this.typingContentLength - this.typingIndex - 1 - i;
			this.textPreviewLineNumber[i].text = "#" + NumberUtil.numberWithCommas(lineNumber) + " ";
		} else {
			this.textTypingContentPreview[i].text = "";
			this.textPreviewLineNumber[i].text = "";
		}
	}
}

TypingExamination.prototype.resetTypingContent = function() {
	this.setCorrectText("");

	this.inputText.setText('');
}

TypingExamination.prototype.onKeyDown2 = function(inputTextValue) {
	// console.log(inputTextValue);
	if(this.isTyping === false) {
		// console.log("isTyping is false");
		this.startTyping();
	}

	if(this.isTypingLine === false) {
		// console.log("isTyping is isTypingLine");
		this.setTimeTypingStart();
	}

	//not trimmed contents
	var notTrimmedInputContent = inputTextValue;
	var notTrimmedTypingContent = this.typingExaminationContents[this.typingIndex];

	// trimmed contents
	// var inputContent = inputText.replace(/ /g, TypingExamination.SPACE_INDICATOR);
	var inputContent = inputTextValue;
	var trimmedInputContent = inputContent.trim();
	var trimmedTypingContent = this.typingExaminationContents[this.typingIndex].trim();
	trimmedTypingContent = trimmedTypingContent.replace(TypingExamination.ENTER_INDICATOR, "");
	// console.log(notTrimmedInputContent + "]");
	// console.log(notTrimmedTypingContent + "]");
	// console.log(trimmedInputContent + "]");
	// console.log(trimmedTypingContent + "]");

	this.highlightTypingContent(notTrimmedInputContent, notTrimmedTypingContent);

	this.updateCorrectUnicodeLetterCount();
	this.updateTypingRecord();

	var lastInputTextChar = "";
	if(inputTextValue.length > 0)
		lastInputTextChar = inputTextValue[inputTextValue.length - 1];
	// console.log("[" + lastInputTextChar + "]");
	if(trimmedInputContent === trimmedTypingContent && lastInputTextChar === " ") {
		// console.log("last space");
		this.onKeyEnter(trimmedInputContent, trimmedTypingContent, notTrimmedTypingContent);
	}
}

TypingExamination.prototype.onKeyDown = function(event, inputTextValue) {
	// console.log(event);
	// console.log(inputTextValue);
	if(this.isTyping === false) {
		// console.log("isTyping is false");
		this.startTyping();
	}

	if(this.isTypingLine === false) {
		// console.log("isTyping is isTypingLine");
		this.setTimeTypingStart();
	}

	//not trimmed contents
	var notTrimmedInputContent = inputTextValue;
	var notTrimmedTypingContent = this.typingExaminationContents[this.typingIndex];

	// trimmed contents
	// var inputContent = inputText.replace(/ /g, TypingExamination.SPACE_INDICATOR);
	var inputContent = inputTextValue;
	var trimmedInputContent = inputContent.trim();
	var trimmedTypingContent = this.typingExaminationContents[this.typingIndex].trim();
	trimmedTypingContent = trimmedTypingContent.replace(TypingExamination.ENTER_INDICATOR, "");

	this.highlightTypingContent(notTrimmedInputContent, notTrimmedTypingContent);

	this.updateCorrectUnicodeLetterCount();
	this.updateTypingRecord();

	if(event.keyCode == Phaser.Keyboard.ENTER)
		this.onKeyEnter(trimmedInputContent, trimmedTypingContent, notTrimmedTypingContent);

	if(event.keyCode == Phaser.Keyboard.SPACEBAR)
		this.onKeyEnter(trimmedInputContent, trimmedTypingContent, notTrimmedTypingContent);

	// console.log(event.keyCode);
}

TypingExamination.prototype.onKeyUp = function(event) {
	if(this.isTyping === false) {
		// console.log(event);
		this.startTyping();
	}

	if(this.isTypingLine === false) {
		// console.log(event);
		this.setTimeTypingStart();
	}

	//not trimmed contents
	var notTrimmedInputContent = this.inputText.value;
	var notTrimmedTypingContent = this.typingExaminationContents[this.typingIndex];

	// trimmed contents
	// var inputContent = inputText.replace(/ /g, TypingExamination.SPACE_INDICATOR);
	var inputContent = this.inputText.value;
	var trimmedInputContent = inputContent.trim();
	var trimmedTypingContent = this.typingExaminationContents[this.typingIndex].trim();
	trimmedTypingContent = trimmedTypingContent.replace(TypingExamination.ENTER_INDICATOR, "");

	this.highlightTypingContent(notTrimmedInputContent, notTrimmedTypingContent);

	this.updateCorrectUnicodeLetterCount();
	this.updateTypingRecord();

	if(event.keyCode == Phaser.Keyboard.ENTER)
		this.onKeyEnter(trimmedInputContent, trimmedTypingContent, notTrimmedTypingContent);

	if(event.keyCode == Phaser.Keyboard.SPACEBAR)
		this.onKeyEnter(trimmedInputContent, trimmedTypingContent, notTrimmedTypingContent);
}

TypingExamination.prototype.setTimeTypingStart = function() {
	if(this.inputText.value == "")
		return;

	this.isTypingLine = true;

	this.timeTypingStart = game.time.elapsedSince(0);
	var timeGap = this.timeTypingStart - this.timeTypingEnd;

	if(timeGap < 50) {
		console.log("enter input check error");
		return;
	}
}

TypingExamination.prototype.calculateTypingRecord = function(typingContent) {
	this.isTypingLine = false;
	this.timeTypingEnd = game.time.elapsedSince(0);
	// console.log('this.timeTypingStart : ' + this.timeTypingStart);
	// console.log('this.timeTypingEnd : ' + this.timeTypingEnd);

	var elapsedTimeMS = this.timeTypingEnd - this.timeTypingStart;
	// console.log('elapsedTimeMS : ' + elapsedTimeMS);

	var typingContentLength = StringUtil.getUnicodeAlphabetCount(typingContent);
	// console.log('typingContentLength : ' + typingContentLength);
	var typingContentPlusEnterCount = typingContentLength + TypingExamination.TYPING_COUNT_PLUS_ENTER;

	// var typingRecord = (typingContentPlusEnterCount + TypingExamination.TYPING_COUNT_PLUS_ENTER) * 60000 / elapsedTimeMS;
	var typingRecord = typingContentPlusEnterCount * TimeUtil.MINUTE_MS / elapsedTimeMS;
	// this.typingRecordTotal = this.correctSyllableLetterCountInAllLines * TimeUtil.MINUTE_SEC / this.realtimeStageTimer.getElapsedTime();

	// this.typingElapsedTime[this.typingIndex] = elapsedTimeMS;
	// this.typingLetterCountTotal += typingContentPlusEnterCount;
	this.typingRecordArray[this.typingIndex] = typingRecord;
}


TypingExamination.prototype.updateCorrectUnicodeLetterCount = function() {
	var notTrimmedInputContent = this.inputText.value;
	var notTrimmedTypingContent = this.typingExaminationContents[this.typingIndex];

	var correctLetterCount = this.getCorrectLetterCount(notTrimmedInputContent, notTrimmedTypingContent);
	if(correctLetterCount === this.correctLetterCountInLine + 1) {
		this.correctLetterCountInLine++;

		var correctLetter = notTrimmedInputContent[this.correctLetterCountInLine - 1];
		var syllableLetterCount = StringUtil.getSyllableCount(correctLetter);
		this.correctSyllableLetterCountInAllLines += syllableLetterCount;
		// console.log(this.correctSyllableLetterCountInAllLines + " : '" + correctLetter + "'");
	} else if(correctLetterCount > this.correctLetterCountInLine) {
		var count = correctLetterCount - this.correctLetterCountInLine;
		// console.log("*** missed onKeyUp event - begin : " + count);
		for(var i = 0; i < count; i++) {
			this.correctLetterCountInLine++;

			var correctLetter = notTrimmedInputContent[this.correctLetterCountInLine - 1];
			var syllableLetterCount = StringUtil.getSyllableCount(correctLetter);
			this.correctSyllableLetterCountInAllLines += syllableLetterCount;
			// console.log(this.correctSyllableLetterCountInAllLines + " : '" + correctLetter + "'");
		}
		// console.log("*** missed onKeyUp event - end");
	} else {
		// console.log("combinationing letter for " + " (" + notTrimmedInputContent[correctLetterCount] + "), correctLetterCount : " + correctLetterCount);
	}
}

TypingExamination.prototype.onKeyEnter = function(trimmedInputContent, trimmedTypingContent, notTrimmedTypingContent) {
	// console.log("### enter ###");
	// console.log("this.typingIndex : " + this.typingIndex);
	// console.log("trimmedInputContent : [" + trimmedInputContent + "], length : " + trimmedInputContent.length);
	// console.log("trimmedTypingContent : [" + trimmedTypingContent + "], length : " + trimmedTypingContent.length);

	if(trimmedInputContent === trimmedTypingContent) {
		// console.log("input completed");
		this.calculateTypingRecord(notTrimmedTypingContent);

		this.correctSyllableLetterCountInAllLines++;
		// console.log(this.correctSyllableLetterCountInAllLines + " : Enter");
		this.correctLetterCountInLine = 0;
		// update this.textTypingRecord.text with this.correctLetterCountForAllLines
		this.updateTypingRecord();

		// console.log("this.typingIndex : " + this.typingIndex);
		// console.log("this.trimmedTypingContentLength : " + this.trimmedTypingContentLength);
		if(this.typingIndex == this.typingContentLength - 1) {
			this.isGameOver = true;
			this.gameOver();
			return;
		}

		// console.log("\n");
		// console.log("\n");
		this.playNextContent();
		return;
	}
}

TypingExamination.prototype.highlightTypingContent = function(notTrimmedInputContent, notTrimmedTypingContent) {
	// console.log(notTrimmedInputContent + "=");
	// console.log(typingContent + "=");

	if(notTrimmedTypingContent == null)
		return;

	// var replaceSpaceIndicatorInputContent = notTrimmedInputContent.replace(/ /g, TypingExamination.SPACE_INDICATOR);
	var typingContentLength = notTrimmedTypingContent.length;
	for(var i = 0; i < typingContentLength; i++) {
		var typingChar = notTrimmedTypingContent.charAt(i);
		var inputChar = notTrimmedInputContent.charAt(i);
		// console.log("typingChar : " + typingChar);
		// console.log("inputChar : " + inputChar);

		// when typingChar is the last letter
		if(isNaN(inputChar)) {
			// console.log("NaN : " + i);
			this.setCorrectText(notTrimmedTypingContent.substring(0, i + 1));
		}

		if(typingChar !== inputChar) {
			// console.log("notTrimmedInputContent.charAt(" + i + ") : " + notTrimmedInputContent.charCodeAt(i).toString(16) + ", " + inputChar);
			// console.log("notTrimmedTypingContent.charAt(" + i + ") : " + notTrimmedTypingContent.charCodeAt(i).toString(16) + ", " + typingChar);

			this.textNextLetterIndicator.text = notTrimmedTypingContent.substring(0, i + 1);
			this.setCorrectText(notTrimmedTypingContent.substring(0, i));
			return;
		}
	}
}

TypingExamination.prototype.updateTypingRecord = function() {
	if(this.isGameOver)
		return;

	this.typingRecordTotal = this.correctSyllableLetterCountInAllLines * TimeUtil.MINUTE_SEC / this.realtimeStageTimer.getElapsedTime();
	// console.log("---");
	// console.log(this.correctSyllableLetterCountInAllLines);
	// console.log(this.realtimeStageTimer.getElapsedTime());
	// console.log(typingRecord);
	var typingRecordInteger = Math.floor(this.typingRecordTotal);
	this.averageTypingSpeedText.print(typingRecordInteger);

	var animalLevelID = Animal.animalLevelIDByRecord(typingRecordInteger, Animal.TYPE_EXAM);
	if(animalLevelID !== this.animalLevelID) {
		this.animalLevelID = animalLevelID;
		this.animalRecordList.activate(animalLevelID);
		this.animalRecordList.tweenAnimation(Animal.ANIMATION_TYPE_CHANGE);
	}
}

TypingExamination.prototype.getCorrectLetterCount = function(inputContent, typingContent) {
	var typingContentLength = inputContent.length;
	for(var i = 0; i < typingContentLength; i++) {
		var typingChar = inputContent.charAt(i);
		var inputChar = typingContent.charAt(i);
		// console.log("typingChar : " + typingChar);
		// console.log("inputChar : " + inputChar);

		// when typingChar is the last letter
		// if(isNaN(inputChar))
		// 	return 0;

		if(typingChar !== inputChar) {
			// console.log("typingContent.charAt(" + i + ") : " + typingContent.charCodeAt(i).toString(16) + ", " + inputChar);
			// console.log("inputContent.charAt(" + i + ") : " + inputContent.charCodeAt(i).toString(16) + ", " + typingChar);

			return i;
		}
	}

	return typingContentLength;
}


TypingExamination.prototype.playNextContent = function() {
	this.typingIndex++;
	this.showTypingExaminationContents();
	this.showPlayingWordNumber();
	this.resetTypingContent();
	this.inputText.startFocus();
}

TypingExamination.prototype.showPlayingWordNumber = function() {
	var currentLine = this.typingIndex + 1;
	this.textTypingLine.text = "#" + (this.typingContentLength - this.typingIndex) + " ";
}

TypingExamination.prototype.startTyping = function() {
	if(this.inputText.value == "")
		return;

	this.realtimeStageTimer.start();
	this.isTyping = true;
}


TypingExamination.GAME_TIME_SEC					= TimeUtil.MINUTE_SEC * 5;	// 5 minutes

TypingExamination.SPACE_INDICATOR				= "␣";	// "ˇ";	// "ᵔ";	// "ᵕ";	// "ˣ";	// "ᵛ";	// " · ";
TypingExamination.ENTER_INDICATOR				= "⏎";	// "↵";	// "↵";

TypingExamination.TYPING_CONTENT_PREVIEW_COUNT	= 4;
TypingExamination.TYPING_CONTENT_DONE_COUNT		= 4;
TypingExamination.TYPING_COUNT_PLUS_ENTER		= 1;

TypingExamination.DEFAULT_FONT_SIZE				= 26;

TypingExamination.COLOR_NOT_INPUT_STRING		= MainColor.DARK_GRAY_STRING;
TypingExamination.COLOR_NEXT_INPUT_STRING		= MainColor.GOLD_STRING;
TypingExamination.COLOR_CORRECT_INPUT_STRING	= MainColor.YELLOW_STRING;
TypingExamination.COLOR_DONE_INPUT_STRING		= MainColor.MOCCASIN_STRING;

TypingExamination.COLOR_STAGE_BACKGROUND_STRING			= "#4d4d4d";

TypingExamination.COLOR_NEXT_INPUT_BACKGROUND_STRING	= MainColor.DARKER_CHOCO_STRING;
TypingExamination.COLOR_CORRECT_INPUT_BACKGROUND_STRING	= MainColor.DARK_CHOCO_STRING;