var Game = {

	create: function() {
		this.dbConnectManager = new DBConnectManager();
		sessionStorageManager.setRecord(0);

		this.game.stage.backgroundColor = "#000000";	// '#4d4d4d';

		sessionStorageManager.setIsNewAppHighestRecord(false);

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

		// keyboard shortcut
		this.keyboardShortcut = new KeyboardShortcut();
		this.keyboardShortcut.addCallback(
			Phaser.KeyCode.ESC,	// keyCode
			null,	// keyDownHandler
			(function() { this.back(); }).bind(this),	// keyUpHandler
			"card matching"	// callerClassName
		);

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

		this.scoreManager = new ScoreManager();
		this.scoreBoard = new ScoreBoard();
		this.scoreManager.addOnChangeScoreListener(
			(function(score) {
				sessionStorageManager.setRecord(score);
				this.scoreBoard.printScore(NumberUtil.numberWithCommas(score));
			}).bind(this)
		);
		this.scoreManager.addOnChangeHighScoreListener(
			(function(highScore) {
				// console.log(highScore);
				// sessionStorageManager.setAppHighestRecord(highScore);
				sessionStorageManager.setIsNewBestRecrd(true);
				// this.screenBottomUI.printLeftTextWithAppHighestRecord(sessionStorageManager.getAppHighestRecord());
			}).bind(this)
		);

		this.setClickEnable(false);
		this.stageTimer = new StageTimer(
			Game.GAME_TIME_SEC,
			(function() {
				this.setClickEnable(false);

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

		this.initVariables();

		this.comboText = new ComboText();

		// game stage
		game.stage.backgroundColor = '#4d4d4d';
		graphics = game.add.graphics(0, 0);

		this.plusScoreGroup = game.add.group();


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


		this.startGame();
		// // this.countDown();
	},

	initVariables: function() {
		this.cards = [];
		this.card_selected_edge;
		this.card_characters = [];
		this.card_characters_count;
		this.initCardVariables();


		this.playingStageNo;
		this.activatedCardColumnNo;
		this.activatedCardRowNo;
		this.activatedCardCount;
		this.clearedCardCount;

		this.openCardInfoIndex = [];
		this.openCardInfoCharacter = [];

		this.reservedHideCard = [];

		this.isCardSelected;
		this.selectedCardCol;
		this.selectedCardRow;

		this.gameTimeEvents = [];
		this.showAndHideCardsEvent = null;


		this.cardCharacterIndexList;
		this.randStageCharacterList;
		this.randCharacterListAfterShuffling;

		this.comboCount = 0;
	},

	initCardVariables: function() {
		this.card_characters[0] = 'commoner';
		this.card_characters[1] = 'elf';
		this.card_characters[2] = 'knight';
		this.card_characters[3] = 'orc';
		this.card_characters[4] = 'wizard';
		this.card_characters[5] = 'halloween';
		this.card_characters[6] = 'holiday_bunny';
		this.card_characters[7] = 'patrick';
		this.card_characters[8] = 'santa';
		this.card_characters[9] = 'basketball';
		this.card_characters[10] = 'football';
		this.card_characters[11] = 'gym';
		this.card_characters[12] = 'hockey';
		this.card_characters[13] = 'soccer';
		this.card_characters_count = this.card_characters.length;
		this.cardCharacterIndexList = Phaser.ArrayUtils.numberArray(0, this.card_characters_count - 1);
		// console.log("cardCharacterIndexList : " + this.cardCharacterIndexList.length);

		for(var i = 0; i < DudeCard.MAX_CARD_COLUMN_NO; i++){
			for(var j = 0; j < DudeCard.MAX_CARD_ROW_NO; j++) {
				var index = j * DudeCard.MAX_CARD_COLUMN_NO + i;
				this.cards[index] = new DudeCard(
					game, i, j,
					this.card_characters,
					(function(col, row) {
						this.cardClicked(col, row);
					}).bind(this)
				);
				this.cards[index].setScale(0.5);
				this.cards[index].hide();
			}
		}

		this.card_selected_edge = game.add.sprite(200, 400, 'card_edge');
		this.card_selected_edge.anchor.set(0.5);
		this.card_selected_edge.smoothed = false;
		this.card_selected_edge.scale.set(0.5);
		this.hideSelectedCard();
	},


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

	/*
	countDown: function() {
		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: function() {
		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 }, 1000, Phaser.Easing.Linear.None, true);
		countDownTween.onComplete.add(this.tweenCountDown, this);

		this.countDownNumber--;
	},
	*/

	startGame: function() {
		this.playingStageNo = 1;

		this.stageTimer.start();
		this.startStage();
	},

	startStage: function() {
		this.isCardSelected = false;

		this.setOpenCardColumnRow();
		this.activatedCardCount = this.activatedCardColumnNo * this.activatedCardRowNo;
		this.clearedCardCount = 0;

		this.initOpenCardInfo();
		this.initCards();

		this.showAndHideCardIndex = 0;
		this.showAndHideCardsEvent = game.time.events.loop(
			DudeCard.SHOW_AND_HIDE_TIME_SECOND * 0.5 * Phaser.Timer.SECOND,
			this.showAndHideCards,
			this
		);
		this.stageTimer.pause();
	},

	startNextStage: function() {
		this.setClickEnable(false);
		this.playingStageNo++;

		var startStageTimeEvent = game.time.events.add(Game.NEXT_STAGE_DELAY_MS, this.startStage, this);
		this.gameTimeEvents[this.gameTimeEvents.length + 1] = startStageTimeEvent;
	},

	showAndHideCards: function() {
		for(var index = 0; index < DudeCard.MAX_CARD_ROW_NO * DudeCard.MAX_CARD_COLUMN_NO; index++) {
			if(index < this.showAndHideCardIndex)
				continue;

			var card = this.cards[index];
			if(card.isActivated == true) {
				card.startShowAndHideAnimation();
				this.showAndHideCardIndex = index + 1;

				return;
			}
		}

		this.setClickEnable(true);
		game.time.events.remove(this.showAndHideCardsEvent);
		this.stageTimer.resume();
	},

	setClickEnable: function(value) {
		this.isEnableClick = value;
	},

	setOpenCardColumnRow: function() {
		switch(this.playingStageNo) {
			case 1:
				this.activatedCardColumnNo = 2;
				this.activatedCardRowNo = 2;
			break;
			case 2:
				this.activatedCardColumnNo = 3;
				this.activatedCardRowNo = 2;
			break;
			case 3:
			case 4:
				this.activatedCardColumnNo = 4;
				this.activatedCardRowNo = 2;
			break;
			case 5:
			case 6:
				this.activatedCardColumnNo = 4;
				this.activatedCardRowNo = 3;
			break;
			case 7:
			case 8:
			case 9:
				this.activatedCardColumnNo = 4;
				this.activatedCardRowNo = 4;
			break;
			default:
				this.activatedCardColumnNo = 5;
				this.activatedCardRowNo = 4;
			break;
		}
	},

	initCards: function() {
		this.randStageCharacterList = Phaser.ArrayUtils.shuffle(this.cardCharacterIndexList);

		var characterListBeforeShuffling = [];
		for(var i = 0; i < this.activatedCardCount; i++) {
			var characterIndex = Math.floor(i / 2);
			characterListBeforeShuffling[i] = this.randStageCharacterList[characterIndex];
		}
		this.randCharacterListAfterShuffling = Phaser.ArrayUtils.shuffle(characterListBeforeShuffling);

		var randCharacterIndex = 0;
		for(var j = 0; j < DudeCard.MAX_CARD_ROW_NO; j++) {
			for(var i = 0; i < DudeCard.MAX_CARD_COLUMN_NO; i++) {
				var index = j * DudeCard.MAX_CARD_COLUMN_NO + i;
				if(i < this.activatedCardColumnNo && j < this.activatedCardRowNo) {
					this.cards[index].setActive(true);
					this.cards[index].move(this.activatedCardColumnNo, this.activatedCardRowNo);
					this.cards[index].show();
					this.cards[index].flipToBack();
					// this.cards[index].setCharacter(1);
					// this.cards[index].setCharacter(game.rnd.integerInRange(0, card_characters_count - 1));
					this.cards[index].setCharacter(this.randCharacterListAfterShuffling[randCharacterIndex]);
					randCharacterIndex++;
				} else {
					this.cards[index].hide();
					this.cards[index].setActive(false);
				}
			}
		}
	},

	initOpenCardInfo: function() {
		this.openCardInfoIndex[0]		= -1;
		this.openCardInfoCharacter[0]	= -1;
		this.openCardInfoIndex[1]		= -1;
		this.openCardInfoCharacter[1]	= -1;
	},

	hideSelectedCard: function() {
		this.isCardSelected = false;

		this.card_selected_edge.x = -100;
		this.card_selected_edge.y = -100;

		this.card_selected_edge.alpha = 0;
	},

	cardClicked: function(col, row) {
		if(this.isEnableClick == false) {
			console.log("It's not on stage");
			return;
		}

		var index = this.getCardIndex(col, row);

		if(this.isCardSelectEdgeActivated() == false		// card select edge is not activated
		|| this.isSelectedBefore(col, row) == false) {		// not selected card

			if(this.cards[index].isActivated == false)
				return;

			this.showSelectedCard(col, row);
			this.setSelectedCard(col, row);
			return;
		}

		this.hideSelectedCard();

		// opened card -> flip to back
		if(this.isFrontCard(col, row) == true) {
			this.flipToBack(col, row);

			if(this.isOpenedCard(col, row) == true)
				this.resetOpenCardInfo(col, row);

			this.setSelectedCard(col, row);
			return;
		}

		// closed card -> flip to front
		this.flipToFront(col, row);

		if(this.isOpenedCard(col, row) == false) {
			this.setOpenCardInfo(col, row);

			if(this.isCardSelectEdgeAll() == true) {	// selected 2 cards
				if(this.isSameCharacterCard() == true) {		// selected same cards
					this.clearSameTwoCards();
					this.increaseComboCount();
					this.addComboBonus();
				} else {										// selected different cards
					this.resetDifferentTwoCards();
					this.resetComboBonus();
				}
			}
		}

		// this.showOpenCardInfo();
		this.setSelectedCard(col, row);
	},

	setSelectedCard: function(col, row) {
		this.selectedCardCol = col;
		this.selectedCardRow = row;
	},

	isSelectedBefore: function(col, row) {
		if(this.selectedCardCol == col && this.selectedCardRow == row)
			return true;

		return false;
	},

	getCardIndex: function(col, row) {
		return index = row * DudeCard.MAX_CARD_COLUMN_NO + col;
	},

	isFrontCard: function(col, row) {
		return this.cards[this.getCardIndex(col, row)].isFront();
	},

	flipToFront: function(col, row) {
		var index = row * DudeCard.MAX_CARD_COLUMN_NO + col;
		this.cards[this.getCardIndex(col, row)].flipToFront();
	},

	flipToBack: function(col, row) {
		this.cards[this.getCardIndex(col, row)].flipToBack();
	},

	resetCards: function(col, row) {
		var index = this.getCardIndex(col, row);
		this.cards[index].show();
		index = this.selectedCardRow * DudeCard.MAX_CARD_COLUMN_NO + this.selectedCardCol;
		this.cards[index].hide(this.selectedCardCol, this.selectedCardRow);
	},

	showSelectedCard: function(col, row) {
		this.isCardSelected = true;

		var index = this.getCardIndex(col, row);
		this.card_selected_edge.x = this.cards[index].x;
		this.card_selected_edge.y = this.cards[index].y;

		this.card_selected_edge.alpha = 1;
	},

	showOpenCardInfo: function() {
		console.log(
			"card 1 (" + this.openCardInfoIndex[0] + ", " + this.openCardInfoCharacter[0] + "), card 2 ("
			 + this.openCardInfoIndex[1] + ", " + this.openCardInfoCharacter[1] + ")");
	},

	showReservedCardInfo: function() {
		console.log(this.reservedHideCard[0]);
		console.log(this.reservedHideCard[1]);
	},

	isCardSelectEdgeActivated: function() {
		return this.isCardSelected;
	},

	isCardSelectEdgeAll: function() {
		if(this.openCardInfoIndex[0] < 0)
			return false;

		if(this.openCardInfoIndex[1] < 0)
			return false;

		return true;
	},


	isSameCharacterCard: function() {
		if(this.openCardInfoIndex[0] < 0 || this.openCardInfoIndex[1] < 0)
			return false;

		if(this.openCardInfoCharacter[0] != this.openCardInfoCharacter[1])
			return false;

		return true;
	},

	clearSameTwoCards: function() {
		var card1 = this.cards[this.openCardInfoIndex[0]];
		this.resetOpenCardInfo(card1.getColumnNo(), card1.getRowNo());
		this.reservedHideCard[0] = card1;
		card1.setActive(false);
		card1.startWaitAndHideAnimation();

		var card2 = this.cards[this.openCardInfoIndex[1]];
		this.resetOpenCardInfo(card2.getColumnNo(), card2.getRowNo());
		this.reservedHideCard[1] = card2;
		card2.setActive(false);
		card2.startWaitAndHideAnimation();

		var tempPlusScore = new PlusScore(card2.x, card2.y, this.getScore());
		this.plusScoreGroup.add(tempPlusScore);
		this.scoreManager.plusScore(this.getScore());

		var checkStageClearedEvent = game.time.events.add(Phaser.Timer.SECOND * 0.5, this.checkStageCleared, this);
		this.gameTimeEvents[this.gameTimeEvents.length + 1] = checkStageClearedEvent;
	},

	checkStageCleared: function() {
		this.clearedCardCount += 2;
		if(this.activatedCardCount == this.clearedCardCount) {
			this.stageTimer.addBonusTime(this.getBonusTime());

			this.startNextStage();
		}
	},

	resetDifferentTwoCards: function() {
		var card1 = this.cards[this.openCardInfoIndex[0]];
		if(card1 == null)
			return;
		this.resetOpenCardInfo(card1.getColumnNo(), card1.getRowNo());
		card1.startWaitAndFlipToBackAnimation();

		var card2 = this.cards[this.openCardInfoIndex[1]];
		if(card2 == null)
			return;
		this.resetOpenCardInfo(card2.getColumnNo(), card2.getRowNo());
		card2.startWaitAndFlipToBackAnimation();
	},



	increaseComboCount: function() {
		this.comboCount++;
	},

	addComboBonus: function() {
		if(this.comboCount < 2)
			return;

		var comboBonusScore = this.comboCount * 10;
		this.comboText.show(this.comboCount, comboBonusScore);
		this.scoreManager.plusScore(comboBonusScore);
	},

	resetComboBonus: function() {
		this.comboCount = 0;
	},



	setOpenCardInfo: function(col, row) {
		var cardIndex = this.getCardIndex(col, row);

		for(var i = 0; i < 2; i++) {
			if(this.openCardInfoIndex[i] < 0) {
				this.openCardInfoIndex[i] = this.cards[cardIndex].getCardIndex();
				this.openCardInfoCharacter[i] = this.cards[cardIndex].getCharacter();

				break;
			}
		}
	},

	resetOpenCardInfo: function(col, row) {
		var cardIndex = this.getCardIndex(col, row);

		for(var i = 0; i < 2; i++) {
			if(this.openCardInfoIndex[i] == cardIndex) {
				this.openCardInfoIndex[i] = -1;
				this.openCardInfoCharacter[i] = -1;
			}
		}
	},

	isOpenedCard: function(col, row) {
		var cardIndex = this.getCardIndex(col, row);
		for(var i = 0; i < 2; i++) {
			if(this.openCardInfoIndex[i] == cardIndex)
				return true;
		}

		return false;
	},

	getScore: function() {
		return this.playingStageNo * 10;
	},

	getBonusTime: function() {
		return this.playingStageNo;
	},


	timeOver: function() {
		var timeOverText = new TimeOverText();
		if(!isExperienceMaestroAccount())
			this.updateResultRecord();

		this.activatedCardColumnNo = 0;
		this.activatedCardRowNo = 0;
		this.initCards();

		// game.time.events.remove(this.timeEvent);
		this.hideSelectedCard();

		for(var i = 0; i < this.gameTimeEvents.length; i++) {
			game.time.events.remove(this.gameTimeEvents[i]);
		}
		this.gameTimeEvents = [];

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

	updateResultRecord: function() {
		if(sessionStorageManager.getMaestroAccountType() < 100) {	// experience account
			this.dbConnectManager.updateResultRecord(
				sessionStorageManager.getMaestroID(),
				sessionStorageManager.getPlayerID(),
				sessionStorageManager.getPlayingAppID(),
				sessionStorageManager.getRecord()
			);
		}
	},

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

}


Game.GAME_TIME_SEC				= 60;
Game.NEXT_STAGE_DELAY_MS		= 500;