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

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

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

EHDI.GAME.components.EffectCalculator = function(simulation, parent) {
	this.lastCardEffect = 0;
	this.activeDoubleSymbol = {};
	this.revert(this.activeDoubleSymbol);

	this.parent = parent;
	this.simulation = simulation;
	this.timeline = new TimelineLite({delay: 0.4, paused:true});

	this.effectMap = [];
	this.multiplierMap = [];
}

EHDI.GAME.components.EffectCalculator.prototype.calculate = function(card, playerCards, opponentCards) {
	var pointsToGain = 0;

	// console.log(playerCards.length)
	pointsToGain = this.getEffectResult(card, playerCards, opponentCards);

	// this.lastCardEffect = pointsToGain;
	// console.log(pointsToGain)
	return pointsToGain;
}

EHDI.GAME.components.EffectCalculator.prototype.getEffectResult = function(card, playerCards, opponentCards) {
	var pointsToGain = 0;
	switch(card.effect.type) {
		case 0: pointsToGain = this.haveCards(card, playerCards, opponentCards); break;
		case 1: pointsToGain = this.perPair(card, playerCards, opponentCards); break;
		case 2: pointsToGain = this.forEachSpecificCard(card, playerCards, opponentCards); break;
		case 3: pointsToGain = this.forEachMissingType(card, playerCards, opponentCards); break;
		case 4: pointsToGain = this.mostOfEachType(card, playerCards, opponentCards); break;
		case 5: pointsToGain = this.mostOfSpecificCard(card, playerCards, opponentCards); break;
		case 6: pointsToGain = this.doubleEffect(card, playerCards, opponentCards); break;
		case 7: pointsToGain = this.doubleSymbolBefore(card, playerCards, opponentCards); break;
		case 8: pointsToGain = this.doubleSymbolAfter(card, playerCards, opponentCards); break;
	}

	return pointsToGain;
}

EHDI.GAME.components.EffectCalculator.prototype.groupCalculate = function(boardCards, enemyBoardCards) {
	var score = 0;
	var nextBc = [];
	var mults = [];
	var points = [];
	var totalCards = boardCards.concat(enemyBoardCards);

	for(var i = 0; i < totalCards.length; i++) {
		mults.push(totalCards[i].symbolMultiplier);
		points.push(totalCards[i].pointsGained);
	}

	for(var i = 0; i < boardCards.length; i++) {
		nextBc = boardCards.slice(0, i+1);
		score += this.calculate(nextBc[i], nextBc, enemyBoardCards.slice(0, i+1)).pointsGained;
	}

	for(var i = 0; i < totalCards.length; i++) {
		totalCards[i].symbolMultiplier = mults[i];
		totalCards[i].pointsGained = points[i];
	}

	return score;
}

EHDI.GAME.components.EffectCalculator.prototype.calculateFinal = function(boardCards, enemyBoardCards, callback) {
	console.log("calculate");
	this.timeline.eventCallback("onComplete", callback);

	var sBoardCards = this.sortToCalculate(boardCards);
	var affectedChildIndex;
	var childIndex;
	var cardContainer = sBoardCards[0].parent;
	var gameScene = cardContainer.parent;
	var totalPointsGained = 0;
	var el = EHDI.GAME.EffectList.EFFECTS;

	var onFocus = function(card) {
	 	EHDI.GAME.soundManager.playSFX("card_select");
		childIndex = cardContainer.getChildIndex(card);
		EHDI.GAME.utils.bringToFront(card);
	}
	var deFocus = function(card) {
		cardContainer.setChildIndex(card, childIndex);
	}
	var onFocusAffected = function(card, showSprite, initCard) {
		// card.oldIndex = cardContainer.getChildIndex(card);
		// card.addFilter(new EHDI.GAME.filters.GlowFilter(15, 2, 1, 0xFFFFFF, 0.1));
		card.toggleBrightness(true);
		if(showSprite) {
			if(initCard.effect.isSpecial && initCard.effect.type != el.DOUBLE.EFFECT.val)
				card.setDoubledSymbol(showSprite);
		}
	};
	var deFocusAffected = function(card) {
		// cardContainer.setChildIndex(card, card.oldIndex);
		// card.filters.shift();
		// card.filters = null;
		card.toggleBrightness(false);
		// console.log(card.filters)
	};
	var computeScores = function(card, pointsGained) {
		if(card.effect.isSpecial && card.effect.type != el.DOUBLE.EFFECT.val)
			return;

		var val = "+"+pointsGained;

		EHDI.GAME.utils.spawnNumberSprite(this.timeline, gameScene, card.x - 40, card.y - 50, val);
		if(pointsGained > 0) {
	    	// console.log(pointsGained);
	    	// this.parent.points += pointsGained;
	    	this.parent.addScore(pointsGained);
			// gameScene.updateScores();
		}
	}

	EHDI.GAME.utils.resetTimeline(this.timeline);

	for(var i = 0; i < sBoardCards.length; i++) {
		var result = this.getEffectResult(sBoardCards[i], boardCards, enemyBoardCards);
		totalPointsGained += result.pointsGained;
		sBoardCards[i].pointsGained = result.pointsGained;

		this.timeline.call(onFocus.bind(this, sBoardCards[i]));
		this.timeline.to(sBoardCards[i].scale, 0.2, {x: "+=0.3", y: "+=0.3"});

		for(var j = 0; j < result.affectedCards.length; j++) {
			var card = result.affectedCards[j];
			// card.oldIndex = cardContainer.getChildIndex(card);
			this.timeline.to(card.position, 0.2, {y: "-=60", onStart: onFocusAffected.bind(this, card, result.showSprite, sBoardCards[i])});
		}
		this.timeline.call(computeScores.bind(this, sBoardCards[i], result.pointsGained));
		// this.timeline.to(sBoardCards[i], 0, {onComplete: computeScores.bind(this, sBoardCards[i], result.pointsGained)})
		// timeline.to(sBoardCards[i].scale, 0.3, {delay: 0.5, x: "-=0.3", y: "-=0.3", onStart: computeScores.bind(this, result.pointsGained), onComplete: deFocus.bind(this, sBoardCards[i])});

		this.timeline.to(sBoardCards[i].scale, 0.2, {delay: 1, x: "-=0.3", y: "-=0.3"});
		this.timeline.call(deFocus.bind(this, sBoardCards[i]));

		for(var j = 0; j < result.affectedCards.length; j++) {
			var card = result.affectedCards[j];
			this.timeline.to(card.position, 0.2, {y: "+=60", onComplete: deFocusAffected.bind(this, card)});
		}

	}

	EHDI.GAME.TimelineManager.add(this.timeline);

	return totalPointsGained;
}

EHDI.GAME.components.EffectCalculator.prototype.sortToCalculate = function(boardCards) {
	var sortedBoardCards = boardCards.slice(0);
	var cards = [];
	var el = EHDI.GAME.EffectList.EFFECTS;

	for(var i = 0; i < sortedBoardCards.length; i++) {
		if(sortedBoardCards[i].effect.isSpecial)
			cards.push(sortedBoardCards[i]);
	}

	for(var i = 0; i < cards.length; i++) {
		var card = sortedBoardCards.splice(sortedBoardCards.indexOf(cards[i]), 1);
		if(card[0].effect.type == el.DOUBLE.EFFECT.val)
			sortedBoardCards.push(card[0]);
		else
			sortedBoardCards.unshift(card[0]);
	}

	// console.log(sortedBoardCards);

	return sortedBoardCards;
}

EHDI.GAME.components.EffectCalculator.prototype.revert = function(activeDoubleSymbol) {
	activeDoubleSymbol.val = false;
	activeDoubleSymbol.multiplier = 2;
}

//this: the effect to be calculated
EHDI.GAME.components.EffectCalculator.prototype.haveCards = function(card, playerCards, opponentCards) {
	var cardsToCompare = card.effect.cardsToCompare.slice(0);
	var pointsGained = 0;
	var affectedCards = [];
	var initLength = cardsToCompare.length;
	var pCards = playerCards.slice(0);
	pCards.push(card);

	for(var i = 0; i < cardsToCompare.length; i++) {
		for(var j = 0; j < pCards.length; j++) {
			if(cardsToCompare[i].val == pCards[j].type.val) {
				affectedCards.push(pCards[j]);
				cardsToCompare.splice(i, 1);
				i--;
				break;
			}
		}
	}
	if(cardsToCompare.length < 1)
		pointsGained = card.effect.points;
	else
		affectedCards = [];

	return {
		affectedCards: affectedCards,
		pointsGained: pointsGained
	};
}

EHDI.GAME.components.EffectCalculator.prototype.perPair = function(card, playerCards, opponentCards) {
	var pointsGained = 0;
	var affectedCards = [];
	// var matchesCard1 = 0;
	var matchedCards1 = [];
	// var matchesCard2 = 0;
	var matchedCards2 = [];

	for(var i = 0; i < playerCards.length; i++) {
		if(playerCards[i].type.val == card.effect.cardsToCompare[0].val) {
			for(var j = 0; j < playerCards[i].symbolMultiplier; j++)
				matchedCards1.push(playerCards[i]);
		}
		else if(playerCards[i].type.val == card.effect.cardsToCompare[1].val) {
			for(var j = 0; j < playerCards[i].symbolMultiplier; j++)
				matchedCards2.push(playerCards[i]);
		}
	}

	var i = 0;
	while(matchedCards1.length > 0 && matchedCards2.length > 0) {
		if(affectedCards.indexOf(matchedCards1[i]) < 0)
			affectedCards.push(matchedCards1[i]);

		if(affectedCards.indexOf(matchedCards2[i]) < 0)
			affectedCards.push(matchedCards2[i]);

		matchedCards1.splice(i, 1);
		matchedCards2.splice(i, 1);

		pointsGained += card.effect.points;
	}

	return {
		affectedCards: affectedCards,
		pointsGained: pointsGained
	};
}

EHDI.GAME.components.EffectCalculator.prototype.forEachSpecificCard = function(card, playerCards, opponentCards) {
	var pointsGained = 0;
	var affectedCards = [];

	for(var i = 0; i < playerCards.length; i++) {
		if(playerCards[i].type.val == card.effect.cardsToCompare[0].val) {
			pointsGained += card.effect.points * playerCards[i].symbolMultiplier;
			affectedCards.push(playerCards[i]);
		}
	}

	return {
		affectedCards: affectedCards,
		pointsGained: pointsGained
	};
}

EHDI.GAME.components.EffectCalculator.prototype.forEachMissingType = function(card, playerCards, opponentCards) {
	var pointsGained = 0;
	var affectedCards = [];
	var nTypes = Object.keys(EHDI.GAME.CardManager.CARD_TYPES).length;
	var types = EHDI.GAME.utils.initArray(nTypes);

	for(var i = 0; i < playerCards.length; i++) {
		types[playerCards[i].type.val] = true;
	}

	for(var i = 0; i < types.length; i++) {
		if(!types[i]) {
			pointsGained += card.effect.points;
		}
	}

	return {
		affectedCards: affectedCards,
		pointsGained: pointsGained
	};
}

EHDI.GAME.components.EffectCalculator.prototype.mostOfEachType = function(card, playerCards, opponentCards) {
	var pointsGained = 0;
	var affectedCards = [];
	var nTypes = Object.keys(EHDI.GAME.CardManager.CARD_TYPES).length;
	var playerTypes = EHDI.GAME.utils.initArray(nTypes, 0);
	var oppTypes = EHDI.GAME.utils.initArray(nTypes, 0);

	for(var i = 0; i < playerCards.length; i++) {
		playerTypes[playerCards[i].type.val] += playerCards[i].symbolMultiplier;
	}

	for(var i = 0; i < opponentCards.length; i++) {
		oppTypes[opponentCards[i].type.val] += opponentCards[i].symbolMultiplier;
	}

	for(var i = 0; i < playerTypes.length; i++) {
		if(playerTypes[i] > oppTypes[i]) {
			pointsGained += card.effect.points;
		}
	}

	return {
		affectedCards: affectedCards,
		pointsGained: pointsGained
	};
}

EHDI.GAME.components.EffectCalculator.prototype.mostOfSpecificCard = function(card, playerCards, opponentCards) {
	var pointsGained = 0;
	var affectedCards = [];
	var playerType = 0;
	var oppType = 0;

	for(var i = 0; i < playerCards.length; i++) {
		if(playerCards[i].type.val == card.effect.cardsToCompare[0].val) {
			playerType += playerCards[i].symbolMultiplier;
			affectedCards.push(playerCards[i]);
		}
	}

	for(var i = 0; i < opponentCards.length; i++) {
		if(opponentCards[i].type.val == card.effect.cardsToCompare[0].val)
			oppType += opponentCards[i].symbolMultiplier;
	}

	if(playerType > oppType)
		pointsGained = card.effect.points;

	return {
		affectedCards: affectedCards,
		pointsGained: pointsGained
	};
}

EHDI.GAME.components.EffectCalculator.prototype.getLastNonAngelCard = function(cards, startFrom) {
	var lastCard;

	for(var i = startFrom; i >= 0; i--) {
		if(!cards[i].isAngel) {
			lastCard = cards[i];
			break;
		}
	}

	return lastCard;
}

//what if this card has an effect on the last card?
EHDI.GAME.components.EffectCalculator.prototype.doubleEffect = function(card, playerCards, opponentCards) {
	var pointsGained = 0;
	var affectedCards = [];
	var cardIndex = playerCards.indexOf(card);
	var lastCard = this.getLastNonAngelCard(playerCards, cardIndex-1);
	var sprite = null;

	if(lastCard) {
		pointsGained = lastCard.pointsGained;
		affectedCards.push(lastCard);
	}

	if(!this.simulation) {
		sprite = new EHDI.aka.PixiText("x2", {fontFamily: "Exo-Bold", fontSize: "60px", fill: 0xFF0000});
		if(lastCard) {
			sprite.position.set(lastCard.width, -lastCard.height);
		}
	}

	return {
		affectedCards: affectedCards,
		pointsGained: pointsGained,
		showSprite: sprite
	};
}

EHDI.GAME.components.EffectCalculator.prototype.doubleSymbolBefore = function(card, playerCards, opponentCards) {
	var pointsGained = 0;
	var cardIndex = playerCards.indexOf(card);
	var affectedCards = [];
	var sprite = null;
	var lastCard;

	if(cardIndex >= 1) {
		lastCard = this.getLastNonAngelCard(playerCards, cardIndex-1);
		if(lastCard) {
			lastCard.symbolMultiplier *= 2;
		}
	}

	if(!this.simulation) {
		sprite = new EHDI.aka.PixiText("x2", {fontFamily: "Exo-Bold", fontSize: "60px", fill: 0x00BFFF});
		if(lastCard) {
			sprite.text = "x" + lastCard.symbolMultiplier;
			affectedCards.push(lastCard);
		}
	}

	return {
		affectedCards: affectedCards,
		pointsGained: pointsGained,
		showSprite: sprite
	}
}

EHDI.GAME.components.EffectCalculator.prototype.doubleSymbolAfter = function(card, playerCards, opponentCards) {
	var pointsGained = 0;
	var cardIndex = playerCards.indexOf(card);
	var affectedCards = [];
	var sprite = null;
	var nextCard;

	if(cardIndex < playerCards.length-1) {
		nextCard = playerCards[cardIndex+1];
		if(nextCard) {
			nextCard.symbolMultiplier *= 2;
		}
	}

	if(!this.simulation) {
		sprite = new EHDI.aka.PixiText("x2", {fontFamily: "Exo-Bold", fontSize: "60px", fill: 0x00BFFF});
		if(nextCard) {
			sprite.text = "x" + nextCard.symbolMultiplier;
			affectedCards.push(nextCard);
		}
	}

	return {
		affectedCards: affectedCards,
		pointsGained: pointsGained,
		showSprite: sprite
	}
}

EHDI.GAME.components.EffectCalculator.prototype.resetState = function() {
	this.lastCardEffect = 0;
	this.activeDoubleSymbol = {};
	this.revert(this.activeDoubleSymbol);
}