////////////////////
//  Tres en Raya  //
////////////////////

PRESENCE.GAME.TER = (function(P,$,undefined){
  
	//Gamecore
	var CORE = P.GAME
		
  //Games variables
	var game;             //Game and player are objects defined in the gamecore.
	var name = "Tic Tac Toe"
  var player = null;
  var currentPlayer = null;
	var playing=true;
	
	
	//We must define our ACTION object.
	//The information exchanged between players is performed through the exchange of action type objects.
	//We can define our own types of actions, with different fields
  //function action(player,square) {
    //this.player = player;
    //this.square = square;
		//this.type = "general";
  //}
	
	function action(player,square) {
    this.player = player;
    this.square = square;
    this.type = "general";
  }
	
  //Html Divs
  var divID = null;
  var containerDivId = 'tresEnRayaContainerDivID';
  var messageDivId = 'tresEnRayaMessageDivID';

  //Boardgame variables
  var board = [];
  var boardDimension = null;
  var squareDimension = null;
  var middleSquareDimension = null;



  ////////////////
  //   STARTER  //
	////////////////
	//The core will invoke this method automatically to start the game.
	//*myPlayer = myself
	//*myGame = Game object (is the same for all players)
	//*myDivID = Div to render the game
  var init = function(myPlayer,myGame,myDivID){
		player = myPlayer;
		game = myGame;
		divID = myDivID;
		
		//Setting options
    game.options = settingOptions(myGame.options);

    //Init Graphics
    drawBoard();
		
		//Init Logic
    settingBoard();
		
		//Init Events
    setBoardEvents();
    
		//Init game variables
    currentPlayer = game.players[0];
		playing=true;
		
		//Start Play!
    if(player.id==currentPlayer.id){
      showMessage("You start!")
    } else {
      showMessage(currentPlayer.name + " starts!")
    }
  };


  //Set defaults for unspecified options
  var settingOptions = function(myOptions){

    if (!('theme' in myOptions)){
      myOptions['theme'] = "Modern"
    } 

    if (!('rounds' in myOptions)){
      myOptions['rounds'] = "1"
    }

    //Apply default options for non specified opts.
    return myOptions;
  };



  ////////////////////////////////
  //    CORE CONFIG CALLBACKS   //
  ////////////////////////////////
	
	//Optional methods that can be invoked by the core
		
  //The Core provides basic validation
	//We can include our own validation conditions here!
	//The core will invoke this method automatically in the validation process
  var validateParams = function(myPlayer,myGame,myDivID){
    if(myGame.players.length != 2){
      return new CORE.createValidationResult(false,"This game needs two players");
    }
    return new CORE.createValidationResult(true,"Ok");  
  }
	
	
	//MinimumRequirements to execute this game
  var minimumRequirements = function(){
		var requirements = new Array();
    return requirements;
  }



  /////////////////////////////////     
  // GAMECORE CALLS & CALLBACKS  //     * To send our actions to other players we will use the << sendAction >> method.   
  /////////////////////////////////     * When some player send us a action, the core will invoke the << onActionReceived >> method.

  var sendAction = function(action){
    CORE.sendAction(game,action)
    return;
  }

  var onActionReceived = function(action){
    processAction(action);
    return;
  }



  /////////////////////////
  // ACTION MANAGEMENT  //     * These methods are not mandatory, but are highly recommended.   
  ////////////////////////


  //Processes an action of any player
  var processAction = function(action){
		
    if(playing==false){
      return
    }

    //Check if the action is legal.
    if(!checkAction(action)){
      showMessage("Ilegal action")
      return false
    }

    if(player.id==action.player.id){
      //Notify my actions!
      sendAction(action)
    }

    //Update logic
    updateLogic(action)

    //Update Graphics
    updateInterface(action)

    //Check for winner
		//If there is a winner, checkWinner() will return the winner's name.
		//If not, it will return "finish" if the game is over without a winner, or null if the game is not over.
    var winner = checkWinner()
    if(winner!=null){
			processWinner(winner)
      finishGame()
      return
    }

    //We continue with the next turn if the game is not over.
    nextTurn();
  }


  //Check if the action is legal.
  var checkAction = function(action){
    
    if(currentPlayer.id!=action.player.id){
      //The player has made an action out of his turn.
      return false;
    }
    
    if(board[action.square][2]!=0){
      //Square is already occupied by another figure.
      return false;
    }

    return true;
  }
	
	
	//If we have a turn-based game we probably need a nextTurn method.
	//This is an example
  var nextTurn = function(){
    var playersQuantity = game.players.length;
    var indexActualPlayer = game.players.indexOf(currentPlayer);
    if(indexActualPlayer==(playersQuantity-1)){
      currentPlayer=game.players[0];
    } else {
      currentPlayer=game.players[indexActualPlayer+1];
    }
    if(player.id==currentPlayer.id){
      showMessage("Is your turn!")
    } else {  
      showMessage(currentPlayer.name + " turn")
    }
  }



  ///////////////////////   
  // TER GAME METHODS  //      
  ///////////////////////

  var drawBoard = function(){
    var containerDiv = document.createElement('div');
    containerDiv.setAttribute('id', containerDivId);
    containerDiv.setAttribute('class', 'tresEnRayaContainerDivClass');
    $("#" + divID).append(containerDiv);

    var messageDiv = document.createElement('div');
    messageDiv.setAttribute('id', messageDivId);
    $(messageDiv).addClass('tresEnRayaMessageDivClass')
    $(messageDiv).addClass('tresEnRayaMessageTheme' + game.options['theme'])
    $("#" + divID).append(messageDiv);

    var p = document.createElement('p');
    p.setAttribute('id', messageDivId + "p");
    $(p).addClass('tresEnRayaMessagePTheme' + game.options['theme'])
    $("#" + messageDivId).append(p);
    
		var messageDivHeight = 12;

    //Adjust dimensions
    var parentWidth = $("#" + divID).width();
    var parentHeight = $("#" + divID).height();
    var maxDimension = 300;
    var minDimension = 100;

    var dimension = Math.max(Math.min(parentWidth,parentHeight,maxDimension),minDimension)
    boardDimension = dimension - messageDivHeight;
    
    $("#" + containerDivId).height(boardDimension)
    $("#" + containerDivId).width(boardDimension);
		$("#" + messageDivId).width(boardDimension);

    //Apply Theme
    $("#" + containerDivId).addClass('tresEnRayaContainerTheme' + game.options['theme'])
  };


  var settingBoard = function(){
    squareDimension = boardDimension/3;
    middleSquareDimension = squareDimension/2;
    //board[squareID] = [x,y,ElementInSquare {0=none,1=circle,2=aspa}]
    board[0] = [middleSquareDimension,middleSquareDimension,0]
    board[1] = [middleSquareDimension+squareDimension,middleSquareDimension,0]
    board[2] = [boardDimension-middleSquareDimension,middleSquareDimension,0]
    board[3] = [middleSquareDimension,middleSquareDimension+squareDimension,0]
    board[4] = [middleSquareDimension+squareDimension,middleSquareDimension+squareDimension,0]
    board[5] = [boardDimension-middleSquareDimension,middleSquareDimension+squareDimension,0]
    board[6] = [middleSquareDimension,boardDimension-middleSquareDimension,0]
    board[7] = [middleSquareDimension+squareDimension,boardDimension-middleSquareDimension,0]
    board[8] = [boardDimension-middleSquareDimension,boardDimension-middleSquareDimension,0]
  };


  var setBoardEvents = function(){
    $("#" + containerDivId).click(function (event) {
      var offsetX = event.pageX - $("#" + containerDivId).offset().left
      var offsetY = event.pageY - $("#" + containerDivId).offset().top

      if($(event.target).is('img')){
        return;
      }

      if(currentPlayer.id!=player.id){
        return;
      }
      square = getSquare(offsetX,offsetY)
			
      var actionNew = new action(currentPlayer,square);
      processAction(actionNew)
    });
  };


  var getSquare = function(x,y){
    for(var i=0; i<board.length; i++){
      if((Math.abs(x-board[i][0])<middleSquareDimension)&&(Math.abs(y-board[i][1])<middleSquareDimension)){
        return i;
      }
    }
    return 0;
  }

  var showMessage = function(msg){
    $("#" + messageDivId + "p").html(msg)
  }

  var finishGame = function(){
    playing = false;
  }

  var updateLogic = function(action){
		if(action.player.id == game.players[0].id){
			var r = 1;
		} else {
			var r = 2;
		}
    board[action.square][2]=r;
  }

  var updateInterface = function(action){
    var img = document.createElement('img');

    if(action.player.id==game.players[0].id){
      var figure = "circle";
    } else {
      var figure = "aspa";
    }

    $(img).attr("src","/assets/games/ter/" + game.options['theme'].toLowerCase() + "_" + figure + ".png");
    $("#" + containerDivId).append(img);
    $(img).addClass('tresEnRayaImgTheme' + game.options['theme'])
		
		var figureSizePercent = 0.8;
		var xdisplacement = -squareDimension*figureSizePercent/2*0.7;
    var ydisplacement = 13;
		
    $(img).width(squareDimension*figureSizePercent)
    $(img).height(squareDimension*figureSizePercent)
    $(img).css("top",board[action.square][1]+ydisplacement)
    $(img).css("left",board[action.square][0]+xdisplacement)
    return;
  }


  //Return winner's name if exists and null if don't exits.
  //Return "finish" when the game is blocked.
  var checkWinner = function(){
    
    //Check for finish game without winner.
    var finish=true;
    for(var i=0; i<board.length; i++){
      if(board[i][2]==0){
        finish = false;
        break;
      }
    }
    if(finish){
      return "finish";
    }

    //Check winner
    //Check if exists three squares with the same symbol consecutively

    //Check horizontal
    if((board[0][2]==board[1][2])&&(board[1][2]==board[2][2])&&(board[2][2]!=0)){
      return game.players[board[0][2]-1];
    }
    if((board[3][2]==board[4][2])&&(board[4][2]==board[5][2])&&(board[5][2]!=0)){
      return game.players[board[3][2]-1];
    }
    if((board[6][2]==board[7][2])&&(board[7][2]==board[8][2])&&(board[8][2]!=0)){
      return game.players[board[6][2]-1];
    }

    //Check vertical
    if((board[0][2]==board[3][2])&&(board[3][2]==board[6][2])&&(board[6][2]!=0)){
      return game.players[board[0][2]-1];
    }
    if((board[1][2]==board[4][2])&&(board[4][2]==board[7][2])&&(board[7][2]!=0)){
      return game.players[board[1][2]-1];
    }
    if((board[2][2]==board[5][2])&&(board[5][2]==board[8][2])&&(board[8][2]!=0)){
      return game.players[board[2][2]-1];
    }

    //Check diagonals
    if((board[0][2]==board[4][2])&&(board[4][2]==board[8][2])&&(board[8][2]!=0)){
      return game.players[board[0][2]-1];
    }
    if((board[6][2]==board[4][2])&&(board[4][2]==board[2][2])&&(board[2][2]!=0)){
      return game.players[board[6][2]-1];
    }

    return null;
  }


  var processWinner = function(winner){
    if(winner!="finish"){
      if(player.id==winner.id){
        showMessage("You have won the game")
      } else {
        showMessage(winner.name + " has won the game")
      }
    } else {
      showMessage("Finished game");
    }
  }

  //Getters
  var getName = function(){
    return name
  }
	
  var getGame = function(){
    return game;
  }
	
	var getBoard = function(){
    return board;
  }
	
	var getMyplayer = function(){
    return player;
  }
	
	var getCurrentPlayer = function(){
    return currentPlayer;
  }


  return {
    init: init,
		getName: getName,
		validateParams: validateParams,
		minimumRequirements: minimumRequirements,
		onActionReceived: onActionReceived
  };

}) (PRESENCE, jQuery);