/*****************************************************************************
 *
 *  Define the ComputerPlayer Object and Functions
 *
 *****************************************************************************/
function ComputerPlayer(aName, playerIndex, theSkillLevel, theGame, theBag)
{
    this.init(aName, playerIndex, theSkillLevel, theGame, theBag);
}

ComputerPlayer.prototype.isComputerPlayer = function()
{
    return true;
}

ComputerPlayer.prototype.isActive = function()
{
	return this.active;
}



ComputerPlayer.prototype.activate = function()
{
	this.active = true;
	showLayerByName('turnIndicator');
	Utility.moveTo
	(
		document.getElementById('turnIndicator'),
		this.scoreBoard.anchorLeft-24,
		this.scoreBoard.anchorTop+20
	);
	this.scoreBoard.emphasize();
}

ComputerPlayer.prototype.deactivate = function()
{
	this.active = false;
	this.scoreBoard.deemphasize();
}

ComputerPlayer.prototype.init = function(aName, playerIndex, theSkillLevel, theGame, theBag)
{
	if (aName != null)
	{
		this.name = aName;
		this.playerIndex = playerIndex;
		this.skillLevel = theSkillLevel;
		this.game = theGame;
		this.board = theGame.getBoard();
		this.bag = theBag;
		this.hand = new Array();
		this.refillHand();
		this.active = false;
		this.scoreBoard = new ScoreBoard(playerIndex);
		this.anchor = getElementPosition('anchor');

		this.selectedTile = null;
		this.selectedSpace = null;
		this.selectedOrientation = null;

		this.swapDialog = new Dialog(250, 200, Language.translate('TileSwapDisplayDialogHeader'));
	}
}

ComputerPlayer.prototype.getPlayerIndex = function()
{
	return this.playerIndex;
}

ComputerPlayer.prototype.getScoreBoard = function()
{
	return this.scoreBoard;
}

ComputerPlayer.prototype.getName = function()
{
    return this.name;
}

ComputerPlayer.prototype.takeTurn = function()
{
	this.game.desiresSwap = false;

	var moves = this.analyzeMoves();
	if (moves.length > 0)
	{
		var move = moves[0];
		this.selectedTile = move.tile;
		this.selectedSpace = move.space;
		this.selectedOrientation = move.orientation;

		if (this.scoreBoard.canSwapTiles(this.hand, move.tile))
		{
			this.game.desiresSwap = this.decideIfWantToSwap(this.selectedTile, this.hand);
		}
	}
	this.game._endTurn();

}


ComputerPlayer.prototype.getSelectedTile = function()
{
	return this.selectedTile;
}

ComputerPlayer.prototype.setSelectedTile = function(tile)
{
	this.selectedTile = tile;
}

ComputerPlayer.prototype.getSelectedSpace = function()
{
	return this.selectedSpace;
}

ComputerPlayer.prototype.setSelectedSpace = function(space)
{
	this.selectedSpace = space;
}

ComputerPlayer.prototype.getSelectedOrientation = function()
{
	return this.selectedOrientation;
}

ComputerPlayer.prototype.setSelectedOrientation = function(orientation)
{
	this.selectedOrientation = orientation;
}

ComputerPlayer.prototype.swapTiles = function(callback)
{
	if (this.scoreBoard.canSwapTiles(this.hand))
	{
		var _this = this;
		var wrapper = function()
		{
			_this.hand = _this.bag.swap(_this.hand, 6);
			callback();
		};

		dd.elements[this.swapDialog.getId()].moveTo(100+this.anchor.left, 150+this.anchor.top);

		this.swapDialog.activate
		(
			this.getSwapDialogContent(this.hand, this.swapDialog.getId()),
			wrapper
		);
		return;
	}

	this.refillHand();
	callback();
}

ComputerPlayer.prototype.isInstantWinner = function()
{
	return this.scoreBoard.isInstantWinner();
}

ComputerPlayer.prototype.refillHand = function()
{
	while ((this.hand.length < 6) && this.bag.hasMoreTiles())
	{
		this.hand.push(this.bag.draw());
	}
}

ComputerPlayer.prototype.removeTileFromHand = function(tile)
{
	var newHand = new Array();
	for (var i=0; i<this.hand.length; i++)
	{
		if (tile.getTileId() != this.hand[i].getTileId())
		{
			newHand.push(this.hand[i]);
		}
	}
	this.hand = newHand;
}


ComputerPlayer.prototype.scoreTilePlacement = function(tileScore)
{
	return this.scoreBoard.scoreTilePlacement(tileScore);
}

ComputerPlayer.prototype.analyzeMoves = function()
{
	var moves = new Array();
	var spaces = this.board.getEdges();
	for (var i=0; i<this.hand.length; i++)
	{
		var candidateMoves = this.analyzeTile(this.hand[i], spaces);
		if (candidateMoves != null)
		{
			for (var j=0; j<candidateMoves.length; j++)
			{
				moves.push(candidateMoves[j]);
			}
		}
	}

	if (moves.length > 0)
	{
		moves.sort(this.sortMoves);
	}

	return moves;
}


ComputerPlayer.prototype.analyzeTile = function(tile, spaces)
{
	var bestMoves = new Array();
	tile.setOrientation(0);
	for (var i=0; i<spaces.length; i++)
	{
		for (var k=0; k<6; k++)
		{
			var candidateMove = this.analyzeOrientation(tile, spaces[i]);
			if (candidateMove != null)
			{
				bestMoves.push(candidateMove);
			}
			tile.rotate(true);
		}
	}

	return bestMoves;
}

ComputerPlayer.prototype.analyzeOrientation = function(tile, space)
{
	if ((space == null) || space.isOccupied())
	{
		return null;
	}
	var neighbor = space.navigate(tile.getOrientation());
	if ((neighbor == null) || neighbor.isOccupied())
	{
		return null;
	}

	if (this.board.initialMoves > 0)
	{
		// we can't allow an orientation that would spin the tile
		// in a direction that prevents it from touching a fixed space
		if ((space.findFixedNeighbor() == null) &&
		    (neighbor.findFixedNeighbor() == null))
		{
			return null;
		}
	}

	// must evaluate the following placement
	// points gained
	// points blocked
	// likelihood of not getting points in a low color
	// low color preference
	// saving back doubles for good opportunities
	// chance of ingenious

	// is there a push my luck scenario?

	var tileScore = this.board.scoreTile(tile, space);

	var weight = 0;

	if (this.scoreBoard.getScore(tile.pivot) < 18)
	{
		weight += tileScore.pivotScore;
	}
	if (this.scoreBoard.getScore(tile.floater) < 18)
	{
		weight += tileScore.floatScore;
	}

	if ((this.board.initialMoves > 0) && tile.isDouble())
	{
		weight -= 2;
	}

	var offset = this.scoreBoard.getSymbolDesireWeight(tileScore.tile.pivot);
	offset += this.scoreBoard.getSymbolDesireWeight(tileScore.tile.floater);

	// if the weight is high and my offset is high then I might want to throw up
	// a block to prevent others from scoring in an area where I don't need to score

	return new Move(tile, tile.getOrientation(), tileScore, space, weight + offset);
}


ComputerPlayer.prototype.flySelectedTile = function()
{
	var flyFunc = this.getFlyTileFunction();

	/*
	document.getElementById('anchor').appendChild(this.selectedTile.getTileDiv());
	Utility.moveTo
	(
		this.selectedTile.getTileDiv(),
		this.scoreBoard.getX(),
		this.scoreBoard.getY()
	);
	*/
	this.game.sharedDragControl.setTile(this.selectedTile);

	dd.elements['control0'].moveTo
	(
		this.scoreBoard.getX(),
		this.scoreBoard.getY()
	);
	dd.elements['control0'].show();

	this.intervalId = setInterval(flyFunc, 5);
}

ComputerPlayer.prototype.getFlyTileFunction = function()
{
	// create closure function having access to the 'this' reference
	var _this = this;
	var f = function()
	{
		var space = _this.getSelectedSpace();
		var tile = _this.getSelectedTile();

		var tx = dd.elements['control0'].x;
		var ty = dd.elements['control0'].y;

		var spaceDiv = document.getElementById(_this.board.getSpaceDiv(space));
		var sx = parseInt(spaceDiv.style.left) + _this.anchor.left;
		var sy = parseInt(spaceDiv.style.top) + _this.anchor.top - Symbol.HEIGHT;

		if ((tx == sx) && (ty == sy))
		{
			clearInterval(_this.intervalId);
			dd.elements['control0'].hide();
			_this.game.sharedDragControl.clearTile();
			//document.getElementById('anchor').removeChild(_this.selectedTile.getTileDiv());
			_this.completeTurn();
		}
		else
		{
			if ((Math.abs(sx - tx) < 50) && (Math.abs(sy - ty) < 50))
			{
				while (tile.getOrientation() != _this.selectedOrientation)
				{
					_this.game.sharedDragControl.rotate();
				}
			}

			if (tx != sx)
			{
				if (tx < sx)
				{
					tx++;
					if (tx < (sx-3)) { tx += 4; }
				}
				else
				{
					tx--;
					if (tx > (sx+3)) { tx -= 4; }
				}
			}
			if (ty != sy)
			{
				if (ty < sy)
				{
					ty++;
					if (ty < (sy-3)) { ty += 4; }
				}
				else
				{
					ty--;
					if (ty > (sy+3)) { ty -= 4; }
				}
			}
			//Utility.moveTo(tile.getTileDiv(), tx, ty);
			dd.elements['control0'].moveTo(tx, ty);
		}
	};

	return f;
}

ComputerPlayer.prototype.completeTurn = function()
{
	game.completeTurn();
}

ComputerPlayer.prototype.sortMoves = function(r1, r2)
{
    if (r1 == null)
    {
        return 1;
    }

    if (r2 == null)
    {
        return -1;
    }

    if (r1.weight > r2.weight)
    {
        return -1;
    }

    if (r1.weight < r2.weight)
    {
        return 1;
    }
    return 0;
}


ComputerPlayer.prototype.getSwapDialogContent = function(hand, id)
{
	var html = '<p>';
	html += '<center><table><tr>';
	for (var i=0; i<hand.length; i++)
	{
		var tile = hand[i];
		if (tile != null)
		{
			html += '<td>' + tile.getHtml() + '</td>';
		}
	}
	html += '</tr></table><p>' +
			Language.translate('PlayerIsSwappingTiles') + '<p></center>' +
			this.swapDialog.getCloseButtonHtml();
	return html;
}

ComputerPlayer.prototype.decideIfWantToSwap = function(selectedTile, hand)
{
	var scores = this.scoreBoard.scores;
	var lowestScore = this.scoreBoard.getScore(scores[0]);

	var symbols = new Array();
	for (var i=0; i<scores.length; i++)
	{
		var score = this.scoreBoard.getScore(scores[i]);
		if ((score == lowestScore) || (score == (lowestScore + 2)))
		{
			symbols.push(scores[i]);
		}
	}

	var cnt = 0;
	for (var i=0; i<symbols.length; i++)
	{
		var symbol = symbols[i];
		for (var j=0; j<hand.length; j++)
		{
			var tile = hand[j];
			if (tile != selectedTile)
			{
				if (tile.pivot == symbol) { cnt++; }
				if (tile.floater == symbol) { cnt++; }
			}
		}
	}

	return cnt < (.2 * hand.length);
}