var core = use('core')
var camera = use('camera')
var compositor = use('compositor')
var input = use('input')
var shape = use('shape2d')
var sprite_factory = use('sprite')
var text2d = use('text2d')

var Grid = use('grid')
var MovementSystem = use('movement').MovementSystem
var startingPos = use('pieces').startingPosition
var rules = use('rules')

var S = 60
var GW = S * 8, GH = S * 8

var game_cam = camera.make({width: GW, height: GH, pos: {x: GW / 2, y: GH / 2}})
var hud_cam = camera.make({width: GW, height: GH, pos: {x: GW / 2, y: GH / 2}})

input.configure({
  action_map: {
    select: ['mouse_button_left'],
    cancel: ['escape', 'mouse_button_right']
  }
})

// Build board
var grid = Grid(8, 8)
grid.width = 8
grid.height = 8
var mover = MovementSystem(grid, rules)
startingPos(grid)

// Board squares (shape2d)
var light_color = {r: 0.93, g: 0.93, b: 0.85, a: 1}
var dark_color = {r: 0.45, g: 0.55, b: 0.35, a: 1}
var select_color = {r: 1, g: 0.84, b: 0, a: 1}
var valid_color = {r: 0.6, g: 0.8, b: 0.4, a: 1}

var board_shapes = []
var bx = 0, by = 0
for (by = 0; by < 8; by++) {
  var row = []
  for (bx = 0; bx < 8; bx++) {
    var col = ((bx + by) & 1) ? dark_color : light_color
    push(row, shape.rect({
      pos: {x: bx * S + S / 2, y: by * S + S / 2},
      width: S, height: S,
      fill: {r: col.r, g: col.g, b: col.b, a: col.a},
      plane: 'game', layer: 0
    }))
  }
  push(board_shapes, row)
}

// Piece sprites — one per piece, keyed by piece object
var piece_sprites = {}
var piece_id = 0
grid.each(function(p) {
  piece_id++
  p._id = piece_id
  piece_sprites[piece_id] = sprite_factory({
    image: p.sprite,
    pos: {x: p.coord[0] * S + S / 2, y: p.coord[1] * S + S / 2},
    width: S, height: S,
    anchor_x: 0.5, anchor_y: 0.5,
    plane: 'game', layer: 1
  })
})

// Selection state
var selectPos = null
var validMoves = []

// Mouse position in grid coords
var hover_gx = -1, hover_gy = -1

// Status text
var status_label = text2d({
  text: "White's turn", pos: {x: 10, y: GH - 20},
  plane: 'hud', size: 14, color: {r: 1, g: 1, b: 1, a: 1}
})

function update_status() {
  status_label.text = mover.turn + "'s turn"
}

function reset_board_colors() {
  var x = 0, y = 0
  for (y = 0; y < 8; y++) {
    for (x = 0; x < 8; x++) {
      var col = ((x + y) & 1) ? dark_color : light_color
      board_shapes[y][x].fill = {r: col.r, g: col.g, b: col.b, a: col.a}
    }
  }
}

function highlight_selection() {
  reset_board_colors()
  if (!selectPos) return

  // Highlight selected square
  board_shapes[selectPos[1]][selectPos[0]].fill = {
    r: select_color.r, g: select_color.g, b: select_color.b, a: select_color.a
  }

  // Highlight valid moves
  var i = 0
  for (i = 0; i < length(validMoves); i++) {
    var m = validMoves[i]
    board_shapes[m[1]][m[0]].fill = {
      r: valid_color.r, g: valid_color.g, b: valid_color.b, a: valid_color.a
    }
  }
}

function compute_valid_moves(from) {
  validMoves = []
  var piece = grid.at(from)[0]
  if (!piece) return

  var x = 0, y = 0, to = null, dest = null
  for (y = 0; y < 8; y++) {
    for (x = 0; x < 8; x++) {
      to = [x, y]
      dest = grid.at(to)
      if (length(dest) && dest[0].colour == piece.colour) continue
      if (rules.canMove(piece, from, to, grid))
        push(validMoves, to)
    }
  }
}

function sync_piece_sprites() {
  grid.each(function(p) {
    var spr = piece_sprites[p._id]
    if (!spr) return
    if (p.captured) {
      spr.visible = false
    } else {
      spr.pos.x = p.coord[0] * S + S / 2
      spr.pos.y = p.coord[1] * S + S / 2
      spr.visible = true
    }
  })
}

// Input handler
var game_input = {
  on_input: function(action, data) {
    if (!data.pressed) return

    if (action == 'cancel') {
      selectPos = null
      validMoves = []
      highlight_selection()
      return
    }

    if (action == 'select' && hover_gx >= 0 && hover_gx < 8 && hover_gy >= 0 && hover_gy < 8) {
      var clicked = [hover_gx, hover_gy]
      var cell = grid.at(clicked)

      if (selectPos) {
        // Try to move
        var is_valid = false
        var i = 0
        for (i = 0; i < length(validMoves); i++) {
          if (validMoves[i][0] == clicked[0] && validMoves[i][1] == clicked[1]) {
            is_valid = true
            break
          }
        }

        if (is_valid) {
          var src_piece = grid.at(selectPos)[0]
          if (src_piece && mover.tryMove(src_piece, clicked)) {
            sync_piece_sprites()
            update_status()
          }
          selectPos = null
          validMoves = []
        } else if (length(cell) && cell[0].colour == mover.turn) {
          // Select different piece
          selectPos = clicked
          compute_valid_moves(selectPos)
        } else {
          selectPos = null
          validMoves = []
        }
      } else {
        // Select piece
        if (length(cell) && cell[0].colour == mover.turn) {
          selectPos = clicked
          compute_valid_moves(selectPos)
        }
      }
      highlight_selection()
    }
  }
}
input.player1().possess(game_input)

var comp_config = {
  clear: {r: 0.15, g: 0.15, b: 0.2, a: 1},
  planes: [
    {name: 'game', camera: game_cam, resolution: {width: GW, height: GH}, presentation: 'letterbox'},
    {name: 'hud', camera: hud_cam, resolution: {width: GW, height: GH}, presentation: 'stretch'}
  ]
}

core.start({
  width: 640, height: 640, title: "Chess",

  input: function(ev) {
    if (ev.type == 'mouse_motion') {
      // Convert pixel coords to grid coords via camera
      var wp = game_cam.window_to_world(ev.pos.x, ev.pos.y)
      if (wp) {
        hover_gx = floor(wp.x / S)
        hover_gy = floor(wp.y / S)
      }
    }
  },

  update: function(dt) {
  },

  render: function() {
    return compositor.execute(compositor.compile(comp_config))
  }
})
