/*
 * Copyright © 2009 Bjoern Guenzel
 *
 */
//MochiKit.Logging.logger.useNativeConsole = false;

function HalmaController() {
	
}

HalmaController.getTime = function() {
	return (new Date()).getTime();
}

HalmaController.CPU = 1;
HalmaController.HUMAN = 2;

HalmaController.prototype.init = function(){
	this.halma = new Halma("BOARD_STAR_HALMA_2_PLAYERS", Halma.BOARD_STAR_HALMA_2_PLAYERS.playerConstellations[0]);
	this.playerTypes = [HalmaController.HUMAN, HalmaController.CPU];
	this.halmaView = new HalmaView(this.halma, this);
	this.halmaView.createBoard();

	this.moves = [];
	this.possibleMoves = [];
	this.possibleTargets = [];
	this.allowFastMoves = true;
	this.halmaView.updateActivePlayer();

	this.maxAITime = 0;

	if(this.playerTypes[this.halma.activePlayer] == HalmaController.CPU) {//xxx too tightly coupled to halma.activePlayer
		window.setTimeout(bind(this.computeComputerMove,this),0);
	}

        try {
	    this.halmaView.setAIMessage("init Web Workers");
            this.worker = new Worker("scripts/aiWorker.js");
	    this.halmaView.setAIMessage("using Web Workers");
        } catch (e) {
            log("web worker creation failed");
	    this.halmaView.setAIMessage("Browser does not support Web Workers");
        }
}

HalmaController.prototype.computeComputerMove = function() {
	log("computeComputerMove");

	var timeBefore = HalmaController.getTime();

        var aiCallback = bind(function(event){
	    //log("resulting move: "+event.data);
	    var move = evalJSON(event.data);
	    var aiTime = HalmaController.getTime()-timeBefore;

	    if (aiTime > this.maxAITime) {
		this.maxAITime = aiTime;
	    }

	    log("maxAITime at move "+(this.halma.history.length+1)+": "+this.maxAITime);

	    this.submitMove(move);

	}, this);

        if(this.worker) {
            log("using ai web worker");
            this.worker.onmessage = aiCallback;
            this.worker.onerror = function(error) {
                alert("something went wrong with the AI, sorry :-(");
            };
            var gameState = this.halma.getSerializableGameStateWithoutHistory();
            this.worker.postMessage(serializeJSON(gameState));
        } else {
            log("using classic blocking AI");
            var ai = new HalmaAI(this.halma.cloneWithoutHistory(), this);
	    var move = ai.computeMove();
	    aiCallback({data: serializeJSON(move)});//mimick structure of web worker event
        }

};

HalmaController.prototype.clickField = function(x,y){
	log("clicked "+x+", "+y);
	
	if(this.playerTypes[this.halma.activePlayer] == HalmaController.CPU || this.isAnimating) {//xxx to tightly coupled to halma.activePlayer
		log("can't evalute click, it is the computers turn");
		return;
	}

	var clickedTile = this.halma.getPosition(x,y);

	if(this.halma.isActivePlayPiece(clickedTile)){
		log("start new move");
		//start new move entry, forget old entries
		if(this.moves.length > 1 && !this.allowFastMoves) {
		    this.halmaView.movePiece(this.moves[0], this.moves[this.moves.length-1], [[this.moves[this.moves.length-1], this.moves[0]]], function(){});//FIXME visually undo moves
		}
		this.halmaView.hidePossibleMoves(this.possibleTargets);
		this.moves = [[x,y]];

		this.possibleMoves = [];
		this.halma.collectPossibleMoves(this.moves, 0, -1, this.possibleMoves, []);
		//log("possible moves: "+repr(this.possibleMoves));
		this.possibleTargets = map(function(pm) {log("pm: "+repr(pm));return pm[0];}, this.possibleMoves);

		//log("possible targets: "+repr(this.possibleTargets));

		this.halmaView.showPossibleMoves(this.possibleTargets);
		
	} else if(this.moves.length > 0 && Halma.isEmptyTile(clickedTile)) {
		if(this.moves.length > 1 && arrayEqual(this.moves[this.moves.length-1], [x,y])) {
			//double click, submit move		
			this.submitMove(this.moves, this.possibleTargets);
		} else {
			//check target is valid
			var possibleMove = filter(function(pMove){return arrayEqual(pMove[0], [x,y]);},this.possibleMoves);
		
			if(possibleMove.length > 0) {
				log("last move: "+this.moves[this.moves.length-1]);
				if(!this.allowFastMoves) {
				    this.halmaView.movePiece(this.moves[this.moves.length-1], [x,y], [this.moves[this.moves.length-1], [x,y]], function(){});//FIXME callback
				}

				//update of entered move (not yet submitted)
				if(this.allowFastMoves){
					log("submit, possible move: "+possibleMove);
					this.moves = possibleMove[0][1];
					this.submitMove(this.moves, this.possibleTargets);
				} else {			
					this.moves.push([x,y]);
				}				
			} else {
				log("impossible move");
			}
		}
	}
}

HalmaController.prototype.submitMove = function(moves, possibleTargetsToHide){
	log("submit move: "+moves);
	if(this.halma.doMove(moves)) {
		//if(possibleTargetsToHide){
			this.halmaView.hidePossibleMoves(possibleTargetsToHide);	
		//}

		var callback = bind(function(){
			this.halmaView.addMoveToHistory(moves);
			this.moves = [];
			this.possibleMoves = [];
			this.possibleTargets = [];
			this.halmaView.updateActivePlayer();
			this.halmaView.updateWinner();

			this.isAnimating = false;
			if(this.playerTypes[this.halma.activePlayer] == HalmaController.CPU && this.halma.winner == null) {//xxx too tightly coupled to halma.activePlayer
			    window.setTimeout(bind(this.computeComputerMove,this),0);
			}
		    }, this);

		if(!possibleTargetsToHide || this.allowFastMoves) {
			//remote player, computer player or fast move, so move stone
			var origin = moves[0];
			var target = moves[moves.length-1];
			this.isAnimating = true;
			this.halmaView.movePiece(origin,target, moves, callback);
		} else {
		    callback();
		}

	}
}

function init(){
	var halmaController = new HalmaController();
	halmaController.init();
}

//init game when web site loaded
connect(window,"onload",init);



