uiPiece.src = "/pieces40.png"
var Game = {}
var Env = {}
var LastHover
var PreventClick
var Offset

function contains(sqs, sq) {
  for(var i in sqs)
    if(Object.same(sqs[i], sq))
      return true
}

Game.init = function() {
  Game.setup()

  $("#board")
    .chessBoard({ size: 44, border: 1, cache: "name2", view: Env.viewColor })
    .chessBoardSetupEvents()
    .bind("chess:square:enter", function(e, sq) {
      
      if( contains(this.highlights, sq) ) {
        LastHover = sq
        $(this).chessSquares([sq]).addClass("hover")      
      } else {
        LastHover = null
      }
      
    })
    .bind("chess:square:exit", function(e, sq) {
      $(this).chessSquares([sq]).removeClass("hover")
    })
    .bind("chess:square:click", function(e, sq, board) {
      if(PreventClick)
        return
      
      $(this).trigger("chess:startmove", [sq, board])
    })
    .bind("chess:startmove", Game.boardClick)
    
  Game.updater.pieces = new PieceUpdater({container: $("#board")[0], els: Game.chess.board.elements, uis: uiPiece.all, size: 44, transform: Game.transform}) 
  Game.updater.update({speed: 0})
}


Game.setup = function() {
  
  
  Offset = $("#board").offset()
  LastHover = null 
  PreventClick = false
  
  Game.chess = new Chess()

  if(!Game.chess.makeMovesFromString(MatchData.moves))
    throw("failed making moves: " + MatchData.moves)

  Game.transform = new Transform({size: 44, view: Env.viewColor})
  
  var confirm = $("<div id=ok></div>").click(Game.confirm)
  var undo = $("<div id=undo></div>").click(Game.undo)
  var $$ = $("<div id=confirm></div>").append(confirm).append(undo)
  $("#board").append($$)
  
  /* dragging */
  
  
    
    
}

Game.setupDragging = function() {
  $("#board .piece")
    .unbind('drag')
    .bind('dragstart', function( event ){
      var id = this.id.replace("piece_","") / 1
      var sq = Piece.factory.objects[id].sq
      $("#board").trigger("chess:startmove", [sq, $("#board")[0]])
      
      $(this).addClass("dragging")

    })
    .bind('drag',
      { distance: 2 },
      function( event ){
        $( this ).css({
          top: event.offsetY - Offset.top,
          left: event.offsetX - Offset.left
        });
    })
    .bind('dragend', function( event ){
      $(this).removeClass("dragging")
      var board = $("#board")[0]
      if(LastHover) {
        var sq = board.select
        var promote = ((sq[1] == 0 || sq[1] == 7) &&  Game.chess.board.at([sq]).letter == "P") ? "Q" : null
        Game.makeMove(sq, LastHover)
        
        /*var mv = new Move(sq, LastHover, Game.chess.state.current_turn, promote)
        Game.chess.move(mv)
        Game.updater.update({move: mv})*/
        board.select = null
      } else {
        var id = this.id.replace("piece_","") / 1
        var piece = Piece.factory.objects[id]
        piece.update = true
        Game.updater.update()
      }
      
      //$("#board").trigger("chess:unhighlight")
      Game.unhighlight()
       
      PreventClick = true
      setTimeout(function() { PreventClick = false}, 100)

    })

    Game.setupDraggingDone = true
}

Game.unhighlight = function() {
  $("#board .highlight").removeClass("highlight")
  $("#board .clicked").removeClass("clicked")
  $("#board .hover").removeClass("hover")
  
}

Game.isTurn = function() { 
  return Env.user_side == Game.chess.state.current_turn && Env.user_side != null && Game.inPlay()
}

Game.inPlay = function() {
  return MatchData.state.winner == null
}

Game.makeMove = function(from, to) {
  var promote = ((to[1] == 0 || to[1] == 7) &&  Game.chess.board.at(from).letter == "P") ? "Q" : null
  var mv = new Move(from, to, Game.chess.state.current_turn, promote)

  Game.chess.move(mv)
  //Game.updater.update({move: mv, noArrow: true})
  
  Game.updater.pieces.update({move: mv})
  $(".interact").removeClass("interact")
  
  if(Env.instant_move)
    setTimeout(function(s) { Game.confirm() }, 500)
  else {
    var sq = Game.chess.lastMove().to
    var xy = Game.transform.to_screen(sq)
    $("#confirm").css({top:xy[1], left:xy[0]}).fadeIn($.browser.msie ? 0 : 500)
  }
  
  $("#board")[0].select = null
  $("#board")[0].highlights = []
}

Game.confirm = function() {
  var mv = Game.chess.lastMove()
  Aerial.post_event({event:"move", data: mv.to_s()})
  $("#confirm").fadeOut($.browser.msie ? 0 : 500)

}

Game.undo = function(s) {
  var mv = Game.chess.lastMove()
  
  Game.chess.undo() 
  Game.updater.pieces.els = Game.chess.board.elements // reset !
  
  Game.updater.pieces.update({move: mv, undo: mv})
  $("#confirm").fadeOut($.browser.msie ? 0 : 500)
  $("#board")[0].select = null
  $("#board")[0].highlights = []
  return false
}

Game.boardClick = function(e, sq, board) {

  if(!Game.hasJoined() || PreventClick) 
    return


  if(board.select) {
    Game.unhighlight()
  }

    
  var $sq = $(this).chessSquares([sq])
  var piece = Game.chess.board.at(sq)

  var same_sq = Object.same(board.select, sq)
  
  if(board.select && (contains(board.highlights, sq) || same_sq ) ) {
    if(!same_sq) 
      Game.makeMove(board.select, sq)
    
    board.select = null
    board.highlights = null
  }
  else if(piece && Env.user_side == piece.side) {
    board.select = sq
    board.highlights = Game.chess.getToSqs(sq)
    $sq.addClass("clicked")
    $(this).chessSquares(board.highlights).addClass("highlight")
  }  
  

  

  
}

Game.hasJoined = function() {
  return Game.isTurn() && MatchData.players[Env.user_side].joined != null
}

Game.updater = {
  update: function(params) {
    params = params || {}
    
    var speed = params.speed // == null ? params.speed : null
    Game.updater.pieces.update(params)

    $(".interact").removeClass("interact")
    

    if(Game.hasJoined() ) 
      $(".piece_" + Env.user_side).addClass("interact")
    
    /*if( !Game.isTurn() ) 
      setTimeout(function() { Game.updater.start() }, speed*4)*/
    
    setTimeout(function(speed){ Game.updater.arrow(speed) }, speed == null ? 500 : speed, speed );
    
    if(!Game.setupDraggingDone)
      Game.setupDragging()
    
    GM.updateGameActions()
    GM.updateGameStatus()
    GM.updateWinText()
    
    CurrentMatches.afterMove()
    
  },
  start: function() {
    Game.updater.stop()
    Game.updateInterval = window.setInterval(Aerial.get_update, 20000)
  },
  stop: function() {
    if(Game.updateInterval) 
      clearInterval(Game.updateInterval)
  },
  inboundMove: function(string) {
    var mv = Game.chess.makeMovesFromString(string)[0]
    Game.updater.update({move:mv})
    Game.updater.stop()
  },
  arrow: function(speed) {
    var pos;
    
    if(Env.user_side == null)
      pos = Game.chess.state.current_turn == 0 ? "bot" : "top"
    else
      pos = Game.isTurn() ? "bot" : "top"
      
    var t = pos == "top" ? 180 : 460

    var $$ = $("#turn_arrow")
    
    $$.animate({"top": t}, speed)
    Game.inPlay() ? $$.show() : $$.hide()
  }
}

Game.handleEvent = function(e) {
  if(e.event == "move") {
    Game.chess.makeMoveFromString(e.data, e.side)
  }
  
  Game.updater.update()
  
}










var Aerial = {
  post_event: function(event) {
    $.ajax({
      type: "POST",
      url: "/play/event/" + MatchData.id,
      data: event, 
      success: function(s) {
        MatchData = eval("(" + s + ")")
       //Game.handleEvent(MatchData.last_event)
          Game.updater.update()
      }
    })
    return true
  },
  get_update: function() {
    $.ajax({
      url: "/play/update/" + MatchData.id,
      data: {state_id: MatchData.state_id}, 
      success: function(text) {
        if(text == " ")
          return
        MatchData = eval("(" + text + ")")
        Game.handleEvent(MatchData.last_event)
      }
    })
  }
}

/*


Aerial = 
  post_event: (event)
    $ ajax [
      type = "POST",
      url = "/play/event/" + MatchData id,
      data = event, 
      success = (s):
        MatchData = ("(" + s + ")") eval
        Game handleEvent(MatchData last_event)
     ]
    ..
    true
  .
  ,
  get_update: function() {
    $.ajax({
      url: "/play/update/" + MatchData.id,
      data: {state_id: MatchData.state_id}, 
      success: function(text) {
        if(text == " ")
          return
        MatchData = eval("(" + text + ")")
        Game.handleEvent(MatchData.last_event)
      }
    })
  }
}



*/

//AllowedEvents = %w(move giveup offer agree_offer cancel_offer)
var GM = {}

GM.availableEvents = function() {
  var events = {"View Fen":{event: "view_fen"} }
  
  if(!Game.inPlay())
    return events
    
  events["Give Up"] = {event: "giveup"}
  
  if(MatchData.state.offer) {
    if(MatchData.state.offerer == Env.opponent_side) {
      events["Accept " + MatchData.state.offer] = {event: "agree_offer", data: MatchData.state.offer}      
    }
    events["Cancel " + MatchData.state.offer] = {event: "cancel_offer", data: MatchData.state.offer}
  } else {
    events["Ask for Draw"] = {event: "offer", data: "draw"}
    //events["Ask for Takeback"] = {event: "offer", data: "takeback"}
  }

  if(!Game.isTurn()) {
    events["Nudge Opponent"] = {event: "nudge"}
  }
  return events
}

GM.updateGameActions = function() {
  var es = GM.availableEvents()
  
  $("#game_actions ul").html("")
  
  for(var i in es) {
    var e = es[i]
    if(e.event == "agree_offer" || e.event == "cancel_offer")
      continue
      
    var a = $("<a>").addClass("event").html(i)
    
    for(var i in e)
      a.attr(i, e[i])

    var li = $("<li>").append(a)    
    $("#game_actions ul").append(li)
  }
  
  $("#game_actions ul").addClass("hide")
  
  window.setTimeout(function() {
    $("#game_actions ul").removeClass("hide")
  }, 200)
   
}

GM.updateGameStatus = function() {
  var e = MatchData.last_event
  if(!e || e.side == null) return
  var user = MatchData.players[e.side].name

  if(Env.user_side == e.side) 
    user = "You"
    
  var s  = "Last: " + user + " "
  if(e.event == "move") {
    s += "moved " + e.data
  } else 
  if(e.event == "offer") {
    s += "offered a " + e.data
  } else 
  if(e.event == "agree_offer") {
    s += "agreed to " + e.data 
  } else 
  if(e.event == "cancel_offer") {
    s += "cancelled " + e.data + " request"
  } else 
  if(e.event == "resign") {
    s += "resigned " 
  } else
  if(e.event == "giveup") {
    s += "resigned"
  }

  if( e.event == "offer" && Env.user_side != null) {
    s += "<br>" 
    if(MatchData.state.offerer == Env.opponent_side)
      s += "<span class='event interact' event='agree_offer' data='" + e.data + "'>Accept?</span> or "
    s +="<span class='event interact' event='cancel_offer' data='" + e.data + "'>Cancel?</span>"
  }
  $("#game_status #status").html(s)
}

$().ready(function() {
  $(".event").live("click", function() {
    GM.userEvent({ event: $(this).attr("event"),data: $(this).attr("data") });
  })
})

GM.updateWinText = function() {
  
  for(var i in MatchData.players) {
    var p = MatchData.players[i]
    if(p.joined == null) {
      var col = ["white", "black"][p.side]
      $("."+col + "Player .winText").html("<img src='/images/icons/question_mark.png' style='width:30px' />")      
    }
  }
  var winner = MatchData.state.winner
  
  if(winner == null)
    return
  
  if(winner == 0.5) {
    $(".winText").html("Draw").css({fontSize: "14px", fontStyle: "italic"})
    return
  }
  
  var winnerColor = ["white", "black"][winner]
  $("."+winnerColor + "Player .winText").html("<img src='/images/icons/crownGold.gif' style='width:30px' />")
}

GM.userEvent = function(e) {

  console.log(e)
  if(e.event == "giveup" && !confirm("Are you sure you want to give up"))
    return
    
  if(e.event == "view_fen") {
    var x = MatchData.fen.replace(/ /g, "&nbsp;")

    $("#fen code").html(x)
    $.facybox({ div: '#fen_container' })
  }
  else {
    Aerial.post_event(e)
  }
}