var EHDI = EHDI || Object.create(null);

EHDI.GAME = EHDI.GAME || Object.create(null);

EHDI.GAME.Managers = (function() {
	var container, cardsInPlay = [], cardPool = [], cardContainer;

	var CardManager = (function() {
		var instance;

		function create() {
			var public = {};

			var card_data = EHDI.Assets.fetch("card_data").card_data;

			//weight corresponds to the possible points that can be gained if you have that type of card
			public.CARD_TYPES = {
				ANIMAL: {val: 0, name: "Animal", weight: 27},
				// GROUNDLOST: {val: 1, name: "Ground/Lost", weight: 31},
				GROUNDLOST: {val: 1, name: "Danger/Rescue", weight: 31},
				PLANT: {val: 2, name: "Plant", weight: 33},
				OIL: {val: 3, name: "Artifacts", weight: 24},
				MANWOMAN: {val: 4, name: "Male/Female", weight: 41},
				TIMECOIN: {val: 5, name: "Time/Flame", weight: 43}
			}

			public.CARD_BACK = EHDI.Assets.images["pb_card_b"];
			public.CARD_G_FRAME = EHDI.Assets.images["pb_card_green_frame"];
			public.CARD_G_OVERLAY = EHDI.Assets.images["pb_card_green_overlay"];
			public.ICO_ANIMAL = EHDI.Assets.images["pb_ico_animal"];
			public.ICO_ARTIFACT = EHDI.Assets.images["pb_ico_artifacts"];
			public.ICO_DANGER = EHDI.Assets.images["pb_ico_danger"];
			public.ICO_FLAME = EHDI.Assets.images["pb_ico_flame"];
			public.ICO_MAN = EHDI.Assets.images["pb_ico_man"];
			public.ICO_PLANT = EHDI.Assets.images["pb_ico_plant"];
			public.ICO_RESCUE = EHDI.Assets.images["pb_ico_rescue"];
			public.ICO_TIME = EHDI.Assets.images["pb_ico_time"];
			public.ICO_WOMAN = EHDI.Assets.images["pb_ico_woman"];

			public.initCards = function(stage) {
				var card;
				//namespaces
				var el = EHDI.GAME.EffectList.EFFECTS;
				var cardTypes = public.CARD_TYPES;

				cardsInPlay = [];
				cardPool = [];

				container = stage;
				cardContainer = new EHDI.aka.Container();
				container.addChild(cardContainer);
				EHDI.GAME.CardInteractions.init(stage, cardContainer);
				EHDI.GAME.CardAnimationManager.init(stage);

				for (var i = 0; i < EHDI.GAME.NO_OF_CARDS; i++) {
					var zero = ((i+1) < 10)? "0":"";
					// card = new EHDI.GAME.components.Card(EHDI.Assets.fetch("pb_card_f_"+zero+(i+1)+"_s").texture, EHDI.Assets.fetch("pb_card_f_"+zero+(i+1)).texture);
					card = new EHDI.GAME.components.Card(card_data[i], EHDI.Assets.images["pb_card_f_"+zero+(i+1)])
					EHDI.GAME.utils.center(card);
					card.position.x += i;
					card.position.y += i;
					card.interactive = false;
					card.setFacedDown();
					cardsInPlay.push(card);
					cardContainer.addChild(card);
				}
				//cards
				cardsInPlay[0].type = cardTypes.ANIMAL;
				cardsInPlay[0].effect = new EHDI.GAME.components.Effect(el.GAIN.HAVE_CARDS, [cardTypes.MANWOMAN, cardTypes.TIMECOIN, cardTypes.PLANT], 10);

				cardsInPlay[1].type = cardTypes.GROUNDLOST;
				cardsInPlay[1].effect = new EHDI.GAME.components.Effect(el.GAIN.HAVE_CARDS, [cardTypes.PLANT, cardTypes.ANIMAL, cardTypes.TIMECOIN], 7);

				cardsInPlay[2].type = cardTypes.PLANT;
				cardsInPlay[2].effect = new EHDI.GAME.components.Effect(el.GAIN.PER_PAIR, [cardTypes.TIMECOIN, cardTypes.MANWOMAN], 4);

				cardsInPlay[3].type = cardTypes.GROUNDLOST;
				cardsInPlay[3].effect = new EHDI.GAME.components.Effect(el.DOUBLE.SYMBOL.AFTER);

				cardsInPlay[4].type = cardTypes.GROUNDLOST;
				cardsInPlay[4].effect = new EHDI.GAME.components.Effect(el.GAIN.HAVE_CARDS, [cardTypes.PLANT, cardTypes.ANIMAL, cardTypes.OIL], 7);

				cardsInPlay[5].type = cardTypes.PLANT;
				cardsInPlay[5].isAngel = true;
				cardsInPlay[5].effect = new EHDI.GAME.components.Effect(el.DOUBLE.SYMBOL.BEFORE);

				cardsInPlay[6].type = cardTypes.OIL;
				cardsInPlay[6].effect = new EHDI.GAME.components.Effect(el.GAIN.FOR_EACH.SPECIFIC_CARD, [cardTypes.GROUNDLOST], 3);

				cardsInPlay[7].type = cardTypes.OIL;
				cardsInPlay[7].effect = new EHDI.GAME.components.Effect(el.GAIN.MOST_OF.EACH_TYPE, [], 4);

				cardsInPlay[8].type = cardTypes.OIL;
				cardsInPlay[8].isAngel = true;
				cardsInPlay[8].effect = new EHDI.GAME.components.Effect(el.DOUBLE.EFFECT);

				cardsInPlay[9].type = cardTypes.MANWOMAN;
				cardsInPlay[9].effect = new EHDI.GAME.components.Effect(el.GAIN.HAVE_CARDS, [cardTypes.MANWOMAN, cardTypes.TIMECOIN, cardTypes.GROUNDLOST, cardTypes.ANIMAL, cardTypes.OIL], 10);

				cardsInPlay[10].type = cardTypes.TIMECOIN;
				cardsInPlay[10].effect = new EHDI.GAME.components.Effect(el.GAIN.PER_PAIR, [cardTypes.GROUNDLOST, cardTypes.PLANT], 4);

				cardsInPlay[11].type = cardTypes.MANWOMAN;
				cardsInPlay[11].effect = new EHDI.GAME.components.Effect(el.GAIN.MOST_OF.SPECIFIC_CARD, [cardTypes.PLANT], 5);

				cardsInPlay[12].type = cardTypes.TIMECOIN;
				cardsInPlay[12].effect = new EHDI.GAME.components.Effect(el.GAIN.HAVE_CARDS, [cardTypes.MANWOMAN, cardTypes.GROUNDLOST, cardTypes.OIL], 7);

				cardsInPlay[13].type = cardTypes.TIMECOIN;
				cardsInPlay[13].effect = new EHDI.GAME.components.Effect(el.GAIN.FOR_EACH.SPECIFIC_CARD, [cardTypes.MANWOMAN], 3);

				cardsInPlay[14].type = cardTypes.MANWOMAN;
				cardsInPlay[14].effect = new EHDI.GAME.components.Effect(el.GAIN.MOST_OF.SPECIFIC_CARD, [cardTypes.TIMECOIN], 5);

				cardsInPlay[15].type = cardTypes.ANIMAL;
				cardsInPlay[15].effect = new EHDI.GAME.components.Effect(el.GAIN.HAVE_CARDS, [cardTypes.MANWOMAN, cardTypes.TIMECOIN, cardTypes.GROUNDLOST], 7);

				cardsInPlay[16].type = cardTypes.PLANT;
				cardsInPlay[16].effect = new EHDI.GAME.components.Effect(el.GAIN.FOR_EACH.SPECIFIC_CARD, [cardTypes.ANIMAL], 3);

				cardsInPlay[17].type = cardTypes.ANIMAL;
				cardsInPlay[17].effect = new EHDI.GAME.components.Effect(el.GAIN.FOR_EACH.MISSING_TYPE, [], 3);
				//end of cards
				for (var i = 0; i < EHDI.GAME.NO_OF_CARDS; i++) {
					cardsInPlay[i].createLarge();
				}
				cardPool = cardsInPlay.slice(0);
				container.opponent.playableCards = container.opponent.playableCards.concat(cardPool.slice(0));
			}

			public.shuffle = function(cards) {
				container.showFooter(true, "SHUFFLING...");
				var sfxShuffle = EHDI.GAME.soundManager.playSFX("card_shuffle");
				sfxShuffle.on("complete", function(){
					EHDI.GAME.soundManager.stopSFX("card_shuffle");
					EHDI.GAME.CardAnimationManager.playShuffleAnim();
				})
			}

			public.distributeCards = function(cards) {
				var cards = cards || cardsInPlay;
				var player = container.player, opponent = container.opponent;
				var handIndex = 0;

				container.showFooter(false);
				EHDI.GAME.CardAnimationManager.playGiveCardsAnim();

				for(var i = 0; i < cards.length; i++) {
					if(i % 2 == 0) {
						cards[i].handIndex = handIndex;
						handIndex++;
						player.addCardToHand(cards[i]);
					}
					else {
						cards[i].handIndex = -1;
						opponent.addCardToHand(cards[i]);
					}
				}
			}

			public.switchCards = function() {
				var cardSet1 = container.player.handCards;
				var cardSet2 = container.opponent.handCards;
				var temp;

				if(cardSet1.length <= 0 && cardSet2.length <= 0) {
					return;
				}

				EHDI.GAME.CardAnimationManager.compressCards();

				temp = container.player.handCards;
				container.player.setCardsInHand(cardSet2);
				container.opponent.setCardsInHand(cardSet1);
			}

			public.nextRound = function(cardsToLeave) {
				var index;
				_resetCards();

				for(var i = 0; i < cardsToLeave.length; i++) {
					index = cardsInPlay.indexOf(cardsToLeave[i]);
					if(index > -1)
						cardsInPlay.splice(index, 1);
				}

				container.player.setForNextRound();
				container.opponent.setForNextRound();

				container.player.addCardToBoardAnim(null, null, false);
				container.opponent.addCardToBoardAnim();

				public.shuffle();
			}

			public.resetGame = function() {
				EHDI.GAME.CardAnimationManager.skipAnimation();
				var player = container.player;
				var opponent = container.opponent;

				cardsInPlay = cardPool.slice(0);

				opponent.stopThinking();
				opponent.setForNewGame();
				player.setForNewGame();

				_hardResetCards();
				public.shuffle();
			}

			public.beginCalculation = function() {
				var player = container.player;
				var opponent = container.opponent;

				public.setInteractivity(cardPool, false);

				if(container.round.val >= 3)
					opponent.calculateFinal(player.calculateFinal.bind(player, container.gameOver.bind(container)));
				else
					opponent.calculateFinal(player.calculateFinal.bind(player, _draftingMode));
			}

			public.setInteractivity = function(cards, val) {
				for(var i = 0; i < cards.length; i++) {
					cards[i].interactive = val;
				}
			}

			function _draftingMode() {
				EHDI.GAME.CardManager.setInteractivity(cardPool, true);
				EHDI.GAME.CardInteractions.draftingMode();
			}

			function _resetCards() {
				for(var i = 0; i < cardsInPlay.length; i++) {
					if(!cardsInPlay[i].isDrafted)
						cardsInPlay[i].resetState();
				}
			}

			function _hardResetCards() {
				for(var i = 0; i < cardsInPlay.length; i++) {
					cardsInPlay[i].resetState();
				}
			}

			return public;
		}

		return {
			getInstance: function() {
				if(!instance)
					instance = create();
				return instance;
			}
		}

	})();

	var CardAnimationManager = (function() {
		var instance, currentTl, childIndex = null, data, animContainer;

		function create() {
			var public = {};
			var tlManager = EHDI.GAME.TimelineManager;

			var _setShuffleTl;
			var _startShuffleTl;
			var _giveCardsTl;
			var _switchTl;
			var _compressTl;

			public.init = function(container) {
				_setShuffleTl = new TimelineLite({delay: 0.3, onComplete: _shuffleAnim, paused:true});
				_startShuffleTl = new TimelineLite({delay: 0.3, onComplete: EHDI.GAME.CardManager.distributeCards, paused:true});
				_giveCardsTl = new TimelineLite({delay: 0.3, paused:true});
				_switchTl = new TimelineLite({delay: 0.3, onComplete: _onSwitchComplete, paused:true});
				_compressTl = new TimelineLite({delay: 0.3, onComplete: public.switchCardsAnim, paused:true});
				animContainer = new EHDI.aka.Container();
				container.addChild(animContainer);
			}

			public.play = function() {
				tlManager.play();
			}

			public.pause = function() {
				tlManager.pause();
			}

			public.skipAnimation = function() {
				tlManager.skip();
			}

			public.playShuffleAnim = function(cards) {
				var cards = cards || cardsInPlay;
				container.diffContainer.visible = false;

				EHDI.GAME.utils.resetTimeline(_setShuffleTl);
				_moveToContainer(animContainer, cards);

				_compileCardsAnim(_setShuffleTl, cards, EHDI.GAME.sceneManager.getStageWidth()/2, EHDI.GAME.sceneManager.getStageHeight()/2, 0.2, 1, 1);
				tlManager.add(_setShuffleTl);
			}

			public.playGiveCardsAnim = function(cards) {
				var cards = cards || cardsInPlay;
				var playerCardsPos = {x: 600, y: 500};
				var oppCardsPos = {x: 80, y: 90};

				EHDI.GAME.utils.resetTimeline(_giveCardsTl);

				for(var i = 0; i < cards.length; i++) {
					if(i % 2 == 0)
						_giveCardsTl.to(cards[i].position, 0.05, {x: playerCardsPos.x, y: playerCardsPos.y, onStart: _gaveCard.bind(cards[i], true)});
					else {
						_giveCardsTl.to(cards[i].position, 0.05, {x: oppCardsPos.x, y: oppCardsPos.y, onStart: _gaveCard.bind(cards[i], false)});
					}
					playerCardsPos.x += cards[i].width/5.5;
					oppCardsPos.x += cards[i].width/5.5;
				}

				_giveCardsTl.call(container.showRound.bind(container, _setPlayable));
				tlManager.add(_giveCardsTl);
			}

			public.switchCardsAnim = function() {
				var cardSet1 = container.player.handCards;
				var cardSet2 = container.opponent.handCards;
				var handIndex = 0;

				EHDI.GAME.utils.resetTimeline(_switchTl);
				_moveToContainer(animContainer, cardSet1.concat(cardSet2));

				_compileCardsAnim(_switchTl, cardSet2, cardSet2[0].position.x, cardSet2[0].position.y, 0.2, 0, 0, "compile1");
				_compileCardsAnim(_switchTl, cardSet1, cardSet1[0].position.x, cardSet1[0].position.y, 0.2, 0, 0, "compile1");

				_compileCardsAnim(_switchTl, cardSet2, cardSet1[0].position.x, cardSet1[0].position.y, 0.2, 0, 0, "compile2");
				_compileCardsAnim(_switchTl, cardSet1, cardSet2[0].position.x, cardSet2[0].position.y, 0.2, 0, 0, "compile2");

				for(var i = 0; i < cardSet1.length; i++) {
					_switchTl.to(cardSet1[i].position, 0.1, {x: cardSet2[i].position.x, y: cardSet2[i].position.y, onComplete: _onSwitchCard.bind(cardSet1[i], true, handIndex)});
					_switchTl.to(cardSet2[i].position, 0.1, {x: cardSet1[i].position.x, y: cardSet1[i].position.y, onComplete: _onSwitchCard.bind(cardSet2[i], false, -1)});
					handIndex++;
				}
				tlManager.add(_switchTl);
				_switchTl.call(_moveToContainer, [cardContainer, cardSet1.concat(cardSet2)]);
			}

			public.compressCards = function() {
				var cardSet1 = container.player.handCards;
				var cardSet2 = container.opponent.handCards;
				var playerCardsPos = {x: 610, y: 500};
				var oppCardsPos = {x: 90, y: 90};

				EHDI.GAME.utils.resetTimeline(_compressTl);

 				for(var i = 0; i < cardSet1.length; i++) {
 					_compressTl.to(cardSet1[i].position, 0.1, {x: playerCardsPos.x, y: playerCardsPos.y}, "compressCard");
 					_compressTl.to(cardSet2[i].position, 0.1, {x: oppCardsPos.x, y: oppCardsPos.y}, "compressCard");
 					playerCardsPos.x += cardSet1[i].width/2.5;
					oppCardsPos.x += cardSet2[i].width/2.5;
 				}
				tlManager.add(_compressTl);
			}

			function _onSwitchComplete() {
				var player = container.player;
				var opponent = container.opponent;
				container.opponent.nextTurn();
				EHDI.GAME.CardManager.setInteractivity(container.player.handCards, true);
			}

			function _onSwitchCard(val, handIndex) {
				if(val) {
					this.setFacedUp();
					EHDI.GAME.CardInteractions.setOnHandListeners(this);
				}
				else {
					this.setFacedDown();
				}
				this.handIndex = handIndex;
			}

			function _shuffleAnim(cards) {
				var cards = cards || cardsInPlay;

				EHDI.GAME.utils.resetTimeline(_startShuffleTl);

				cards = EHDI.GAME.utils.shuffle(cards);
				cardsInPlay = cards;

				for(var i = 0; i < cards.length; i++) {
					if(i % 2 == 0)
						_startShuffleTl.to(cards[i].position, 0.2, {x: "-=100",
						onStart: EHDI.GAME.soundManager.playSFX, onStartParams: ["card_deal"]});
					else
						_startShuffleTl.to(cards[i].position, 0.2, {x: "+=100",
						onStart: EHDI.GAME.soundManager.playSFX, onStartParams: ["card_deal"]});
				}

				_compileCardsAnim(_startShuffleTl, cards, EHDI.GAME.sceneManager.getStageWidth()/2, EHDI.GAME.sceneManager.getStageHeight()/2, 0.2, 1, 1);
				_startShuffleTl.call(_moveToContainer, [cardContainer, cards]);

				tlManager.add(_startShuffleTl);
			}

			function _compileCardsAnim(tl, cards, x, y, delay, dx, dy, label) {
				var dx = dx || 0;
				var dy = dy || 0;
				var label = label || "compile";
				var cards = cards || cardsInPlay;
				var newX = x;
				var newY = y;

				for(var i = 0; i < cards.length; i++) {
					cards[i].interactive = false;

					tl.to(cards[i].position, delay, {x: newX, y: newY, onComplete: _onCompileComplete.bind(cards[i])}, label);

					newX += dx;
					newY += dy;
				}
			}

			function _onCompileComplete() {
				this.setFacedDown();
			}

			function _gaveCard(val) {
				if(val) {
					this.toggleScaled(false);
					this.setFacedUp();
					EHDI.GAME.soundManager.playSFX("card_place");
				}
				else
					this.setFacedDown();
				setTimeout(EHDI.GAME.utils.bringToFront.bind(null, this), 1);
				EHDI.GAME.CardInteractions.setOnHandListeners(this);
			}

			function _setPlayable() {
				for(var i = 0; i < cardsInPlay.length; i++) {
					if(!cardsInPlay[i].facedDown) {
						cardsInPlay[i].interactive = true;
					}
				}
			}

			function _moveToContainer(c, cards) {
				for(var i = 0; i < cards.length; i++) {
					c.addChild(cards[i]);
				}
			}

			return public;
		}

		return {
			getInstance: function() {
				if(!instance)
					instance = create();
				return instance;
			}
		}

	})();

	var TimelineManager = (function() {
		var instance, activeTimelines = [];

		function create() {
			var public = {};

			public.add = function(tl) {
				var showedSkip = false;
				if(tl.duration() > 1) {
					setTimeout(container.showSkipButton.bind(container, true), 300);
					showedSkip = true;
				}
				tl.call(_onCompleteTl, [tl, showedSkip]);
				activeTimelines.push(tl);
				tl.play();
			}

			public.play = function() {
				for(var i = 0; i < activeTimelines.length; i++) {
					if(activeTimelines[i].paused())
						activeTimelines[i].play();
				}
			}

			public.pause = function() {
				for(var i = 0; i < activeTimelines.length; i++) {
					if(activeTimelines[i].isActive()) {
						activeTimelines[i].pause();
					}
				}
			}

			public.skip = function() {
				for(var i = 0; i < activeTimelines.length; i++) {
					if(activeTimelines[i].isActive()) {
						activeTimelines[i].progress(1, false);
					}
				}
				container.showSkipButton(false);
			}

			public.dispose = function() {
				for(var i = 0; i < activeTimelines.length; i++) {
					activeTimelines[i].kill();
				}
			}

			public.activeTimelinesCount = function() {
				return activeTimelines.length;
			}

			function _onCompleteTl(tl, showedSkip) {
				// console.log("remove "+tl.lmao)
				activeTimelines.splice(activeTimelines.indexOf(tl), 1);
				if(showedSkip)
					container.showSkipButton(false);
			}

			return public;
		}

		return {
			getInstance: function() {
				if(!instance)
					instance = create();
				return instance;
			}
		}

	})();

	return {
		CardManager: CardManager,
		CardAnimationManager: CardAnimationManager,
		TimelineManager: TimelineManager
	}
})();