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.OpponentAI = function(playableCards, handCards, boardCards, enemyBoardCards, draftedCards) {	
	this.playableCards = playableCards;
	this.handCards = handCards;
	this.boardCards = boardCards;
	this.enemyBoardCards = enemyBoardCards;
	this.draftedCards = draftedCards;
	this.effectCalculator = new EHDI.GAME.components.EffectCalculator(true);

	this.weightMap = [];

	this.lookAhead = 2;
	this.choices = null;
}

EHDI.GAME.components.OpponentAI.prototype.chooseFromHand = function(level) {
	var card;
	switch(level) {
		case 1: card = this.greedyAlgo(); break;
		case 2: card = this.smartAlgo(); break;
		default: card = this.randomCard(this.handCards);
	}
	return card;
}

EHDI.GAME.components.OpponentAI.prototype.pickCardsToLeave = function(level, nCards) {
	var cardTypes = EHDI.GAME.CardManager.CARD_TYPES;
	var nTypes = Object.keys(cardTypes).length;
	var arbitrariness;
	var type;
	var n = 0;
	var cardsToLeave = [];
	var sortedBoardCards = this.boardCards.slice(0);

	switch(level) {
		case 1: arbitrariness = 0.4; break;
		case 2: arbitrariness = 0.2; break;
		default: arbitrariness = 0.7;
	}
	
	sortedBoardCards.sort(function(a, b) { return a.type.weight - b.type.weight});
	// console.log(sortedBoardCards);

	for(var i = sortedBoardCards.length-1; i >= 0; i--) {
		if(this.draftedCards.indexOf(sortedBoardCards[i]) < 0) {
			if((cardsToLeave.length < nCards && i <= nCards) || Math.random() >= arbitrariness) {
				// console.log("pick best card")
				cardsToLeave.push(sortedBoardCards[i]);		
				n++;
				if(n >= nCards)
					break;
			}
		}
	}

	return cardsToLeave;
}

EHDI.GAME.components.OpponentAI.prototype.randomCard = function(cards) {
	return cards[EHDI.GAME.utils.randomInt(0, cards.length)];
}

EHDI.GAME.components.OpponentAI.prototype.greedyAlgo = function() {
	this.weightMap = EHDI.GAME.utils.initArray(this.handCards.length, 0);
	var max = 0, maxIndex = 0;
	var mults = [];
	var points = [];

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

	for(var i = 0; i < this.handCards.length; i++) {
		if(!this.handCards[i].effect.isSpecial) {
			this.weightMap[i] = this.effectCalculator.calculate(this.handCards[i], this.boardCards, this.enemyBoardCards).pointsGained;
		} else {
			this.weightMap[i] = 0;
		}

		if(this.weightMap[i] > max) {
			maxIndex = i;
			max = this.weightMap[i];
		}
	}

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

	if(max == 0)
		return this.randomCard(this.handCards);

	return this.handCards[maxIndex];
}

EHDI.GAME.components.OpponentAI.prototype.smartAlgo = function() {
	this.choices = new EHDI.GAME.Tree(this.recentMove);
	var playerCards = this.deducePlayerCards();

	this.iterations = 0;
	if(this.handCards.length > 1) {
		this.generateSearchTree(this.choices.root, this.boardCards.slice(0), this.handCards.slice(0), this.enemyBoardCards.slice(0), playerCards, 1);

		var move = EHDI.GAME.utils.minimax(this.choices.root, true);

		while(move.parent != this.choices.root) {
			move = move.parent;
		}
		return move.move;
	} else {
		return this.handCards[0];
	}
}

EHDI.GAME.components.OpponentAI.prototype.generateSearchTree = function(parent, boardCards, handCards, enemyBoardCards, playerCards, turn) {
	var lookAhead = (this.handCards.length > this.lookAhead)? this.handCards.length-this.lookAhead:1;
	if(handCards.length <= lookAhead) {
		this.effectCalculator.resetState();
		// console.log(boardCards.length + " : " + enemyBoardCards.length);
		var score = this.effectCalculator.groupCalculate(boardCards, enemyBoardCards);
		this.iterations++;
		var node = new EHDI.GAME.Node(handCards[lookAhead-1], score);
		return node;
	}
	else {
		if(turn == 1) {
			for(var i = 0; i < handCards.length; i++) {
				var node = new EHDI.GAME.Node(handCards[i]);
				var nextBoardCards = boardCards.concat([handCards[i]]);
				var nextHandCards = handCards.slice();
				nextHandCards.splice(i, 1);

				turn = 0;
				parent.addChild(this.generateSearchTree(node, nextBoardCards, nextHandCards, enemyBoardCards, playerCards, turn));
			}
		} else {
			for(var i = 0; i < playerCards.length; i++) {
				var node = new EHDI.GAME.Node(playerCards[i]);
				var nextBoardCards = enemyBoardCards.concat([playerCards[i]]);
				var nextHandCards = playerCards.slice();
				nextHandCards.splice(i, 1);

				turn = 1;
				parent.addChild(this.generateSearchTree(node, boardCards, nextHandCards, nextBoardCards, handCards, turn));
			}
		}
		
		return parent;
	}
}

EHDI.GAME.components.OpponentAI.prototype.getHighestWeightedCard = function() {
	return Math.max.apply(Math, this.weightMap);
}

EHDI.GAME.components.OpponentAI.prototype.deducePlayerCards = function(handCards, boardCards, enemyBoardCards) {
	var handCards = handCards || this.handCards;
	var boardCards = boardCards || this.boardCards;
	var enemyBoardCards = enemyBoardCards || this.enemyBoardCards;
	var playerCards = [];

	for(var i = 0; i < this.playableCards.length; i++) {
		if(handCards.indexOf(this.playableCards[i]) < 0 
			&& boardCards.indexOf(this.playableCards[i]) < 0 
			&& enemyBoardCards.indexOf(this.playableCards[i]) < 0) {

			playerCards.push(this.playableCards[i]);
		}
	}
	return playerCards;
}

EHDI.GAME.components.OpponentAI.prototype.updateCardSets = function(cardSets) {
	this.playableCards = cardSets.playableCards || this.playableCards;
	this.handCards = cardSets.handCards || this.handCards;
	this.boardCards = cardSets.boardCards || this.boardCards;
	this.enemyBoardCards = cardSets.enemyBoardCards || this.enemyBoardCards;
	this.draftedCards = cardSets.draftedCards || this.draftedCards;
}