/* main.js – runs the demo with your prototype-based grid */

var json = use('json')
var draw2d = use('prosperon/draw2d')

var blob = use('blob')

/*──── import our pieces + systems ───────────────────────────────────*/
var Grid           = use('grid');              // your new ctor
var MovementSystem = use('movement').MovementSystem;
var startingPos    = use('pieces').startingPosition;
var rules          = use('rules');

/*──── build board ───────────────────────────────────────────────────*/
var grid = Grid(8, 8);
grid.width = 8;   // (the ctor didn't store them)
grid.height = 8;

var mover = MovementSystem(grid, rules);
startingPos(grid);

/*──── networking and game state ─────────────────────────────────────*/
var gameState = 'waiting'; // 'waiting', 'searching', 'server_waiting', 'connected'
var isServer = false;
var opponent = null;
var myColor = null; // 'white' or 'black'
var isMyTurn = false;

function updateTitle() {
  var title = "Misty Chess - ";
  
  switch(gameState) {
    case 'waiting':
      title += "Press S to start server or J to join";
      break;
    case 'searching':
      title += "Searching for server...";
      break;
    case 'server_waiting':
      title += "Waiting for player to join...";
      break;
    case 'connected':
      if (myColor) {
        title += (mover.turn == myColor ? "Your turn (" + myColor + ")" : "Opponent's turn (" + mover.turn + ")");
      } else {
        title += mover.turn + " turn";
      }
      break;
  }
  
  log.console(title)
}

// Initialize title
updateTitle();

/*──── mouse → click-to-move ─────────────────────────────────────────*/
var selectPos = null;
var hoverPos = null;
var holdingPiece = false;

var opponentMousePos = null;
var opponentHoldingPiece = false;
var opponentSelectPos = null;

function handleMouseButtonDown(e) {
  if (e.which != 0) return;
  
  // Don't allow piece selection unless we have an opponent
  if (gameState != 'connected' || !opponent) return;
  
  var mx = e.mouse.x;
  var my = e.mouse.y;
  
  var c = [floor(mx / 60), floor(my / 60)];
  if (!grid.inBounds(c)) return;
  
  var cell = grid.at(c);
  if (length(cell) && cell[0].colour == mover.turn) {
    selectPos = c;
    holdingPiece = true;
    // Send pickup notification to opponent
    if (opponent) {
      send(opponent, {
        type: 'piece_pickup',
        pos: c
      });
    }
  } else {
    selectPos = null;
  }
}

function handleMouseButtonUp(e) {
  if (e.which != 0 || !holdingPiece || !selectPos) return;
  
  // Don't allow moves unless we have an opponent and it's our turn
  if (gameState != 'connected' || !opponent || !isMyTurn) {
    holdingPiece = false;
    return;
  }
  
  var mx = e.mouse.x;
  var my = e.mouse.y;
  
  var c = [floor(mx / 60), floor(my / 60)];
  if (!grid.inBounds(c)) {
    holdingPiece = false;
    return;
  }
  
  if (mover.tryMove(grid.at(selectPos)[0], c)) {
    log.console("Made move from", selectPos, "to", c);
    // Send move to opponent
    log.console("Sending move to opponent:", opponent);
    send(opponent, {
      type: 'move',
      from: selectPos,
      to: c
    });
    isMyTurn = false; // It's now opponent's turn
    log.console("Move sent, now opponent's turn");
    selectPos = null;
    updateTitle();
  }
  
  holdingPiece = false;
  
  // Send piece drop notification to opponent
  if (opponent) {
    send(opponent, {
      type: 'piece_drop'
    });
  }
}

function handleMouseMotion(e) {
  var mx = e.pos.x;
  var my = e.pos.y;
  
  var c = [floor(mx / 60), floor(my / 60)];
  if (!grid.inBounds(c)) {
    hoverPos = null;
    return;
  }
  
  hoverPos = c;
  
  // Send mouse position to opponent in real-time
  if (opponent && gameState == 'connected') {
    send(opponent, {
      type: 'mouse_move',
      pos: c,
      holding: holdingPiece,
      selectPos: selectPos
    });
  }
}

function handleKeyDown(e) {
  // S key - start server
  if (e.scancode == 22 && gameState == 'waiting') { // S key
    startServer();
  }
  // J key - join server  
  else if (e.scancode == 13 && gameState == 'waiting') { // J key
    joinServer();
  }
}

/*──── drawing helpers ───────────────────────────────────────────────*/
/* ── constants ─────────────────────────────────────────────────── */
var S = 60;                               // square size in px
var light = [0.93,0.93,0.93,1];
var dark  = [0.25,0.25,0.25,1];
var allowedColor = [1.0, 0.84, 0.0, 1.0]; // Gold for allowed moves
var myMouseColor = [0.0, 1.0, 0.0, 1.0];     // Green for my mouse
var opponentMouseColor = [1.0, 0.0, 0.0, 1.0]; // Red for opponent mouse

/* ── draw one 8×8 chess board ──────────────────────────────────── */
function drawBoard() {
  for (var y = 0; y < 8; ++y)
    for (var x = 0; x < 8; ++x) {
      var isMyHover = hoverPos && hoverPos[0] == x && hoverPos[1] == y;
      var isOpponentHover = opponentMousePos && opponentMousePos[0] == x && opponentMousePos[1] == y;
      var isValidMove = selectPos && holdingPiece && isValidMoveForTurn(selectPos, [x, y]);
      
      var color = ((x+y)&1) ? dark : light;
      
      if (isValidMove) {
        color = allowedColor; // Gold for allowed moves
      } else if (isMyHover && !isOpponentHover) {
        color = myMouseColor; // Green for my mouse
      } else if (isOpponentHover) {
        color = opponentMouseColor; // Red for opponent mouse
      }
      
      draw2d.rectangle(
        { x: x*S, y: y*S, width: S, height: S },
        { thickness: 0 },
        { color: color }
      );
    }
}

function isValidMoveForTurn(from, to) {
  if (!grid.inBounds(to)) return false;
  
  var piece = grid.at(from)[0];
  if (!piece) return false;
  
  // Check if the destination has a piece of the same color
  var destCell = grid.at(to);
  if (length(destCell) && destCell[0].colour == piece.colour) {
    return false;
  }
  
  return rules.canMove(piece, from, to, grid);
}

/* ── draw every live piece ─────────────────────────────────────── */
function drawPieces() {
  grid.each(function (piece) {
    if (piece.captured) return;
    
    // Skip drawing the piece being held (by me or opponent)
    if (holdingPiece && selectPos && 
        piece.coord[0] == selectPos[0] && 
        piece.coord[1] == selectPos[1]) {
      return;
    }
    
    // Skip drawing the piece being held by opponent
    if (opponentHoldingPiece && opponentSelectPos && 
        piece.coord[0] == opponentSelectPos[0] && 
        piece.coord[1] == opponentSelectPos[1]) {
      return;
    }

    var r = { x: piece.coord[0]*S, y: piece.coord[1]*S,
              width:S, height:S };

    draw2d.image(piece.sprite, r);
  });
  
  // Draw the held piece at the mouse position if we're holding one
  if (holdingPiece && selectPos && hoverPos) {
    var piece = grid.at(selectPos)[0];
    if (piece) {
      var r = { x: hoverPos[0]*S, y: hoverPos[1]*S,
                width:S, height:S };
      
      draw2d.image(piece.sprite, r);
    }
  }
  
  // Draw opponent's held piece if they're dragging one
  if (opponentHoldingPiece && opponentSelectPos && opponentMousePos) {
    var opponentPiece = grid.at(opponentSelectPos)[0];
    if (opponentPiece) {
      var r = { x: opponentMousePos[0]*S, y: opponentMousePos[1]*S,
                width:S, height:S };
      
      // Draw with slight transparency to show it's the opponent's piece
      draw2d.image(opponentPiece.sprite, r);
    }
  }
}

function update(dt)
{
  return {}
}

function draw()
{
  draw2d.clear()
  drawBoard()
  drawPieces()
  return draw2d.get_commands()
}

function startServer() {
  gameState = 'server_waiting';
  isServer = true;
  myColor = 'white';
  isMyTurn = true;
  updateTitle();
  
  $portal(e => {
    log.console("Portal received contact message");
    // Reply with this actor to establish connection
    log.console ($self)
    send(e, $self);
    log.console("Portal replied with server actor");
  }, 5678);
}

function joinServer() {
  gameState = 'searching';
  updateTitle();
  
  function contact_fn(actor, reason) {
    log.console("CONTACTED!", actor ? "SUCCESS" : "FAILED", reason);
    if (actor) {
      opponent = actor;
      log.console("Connection established with server, sending join request");
      
      // Send a greet message with our actor object
      send(opponent, {
        type: 'greet',
        client_actor: $self
      });
    } else {
      log.console(`Failed to connect: ${reason}`);
      gameState = 'waiting';
      updateTitle();
    }
  }
  
  $contact(contact_fn, {
    address: "192.168.0.149",
    port: 5678
  });
}

$receiver(e => {
  if (e.kind == 'update')
    send(e, update(e.dt))
  else if (e.kind == 'draw')
    send(e, draw())
  else if (e.type == 'game_start' || e.type == 'move' || e.type == 'greet')
    log.console("Receiver got message:", e.type, e);
  
  if (e.type == 'greet') {
    log.console("Server received greet from client");
    // Store the client's actor object for ongoing communication
    opponent = e.client_actor;
    log.console("Stored client actor:", opponent);
    gameState = 'connected';
    updateTitle();
    
    // Send game_start to the client
    log.console("Sending game_start to client");
    send(opponent, {
      type: 'game_start',
      your_color: 'black'
    });
    log.console("game_start message sent to client");
  }
  else if (e.type == 'game_start') {
    log.console("Game starting, I am:", e.your_color);
    myColor = e.your_color;
    isMyTurn = (myColor == 'white');
    gameState = 'connected';
    updateTitle();
  } else if (e.type == 'move') {
    log.console("Received move from opponent:", e.from, "to", e.to);
    // Apply opponent's move
    var fromCell = grid.at(e.from);
    if (length(fromCell)) {
      var piece = fromCell[0];
      if (mover.tryMove(piece, e.to)) {
        isMyTurn = true; // It's now our turn
        updateTitle();
        log.console("Applied opponent move, now my turn");
      } else {
        log.console("Failed to apply opponent move");
      }
    } else {
      log.console("No piece found at from position");
    }
  } else if (e.type == 'mouse_move') {
    // Update opponent's mouse position
    opponentMousePos = e.pos;
    opponentHoldingPiece = e.holding;
    opponentSelectPos = e.selectPos;
  } else if (e.type == 'piece_pickup') {
    // Opponent picked up a piece
    opponentSelectPos = e.pos;
    opponentHoldingPiece = true;
  } else if (e.type == 'piece_drop') {
    // Opponent dropped their piece
    opponentHoldingPiece = false;
    opponentSelectPos = null;
  } else if (e.type == 'mouse_button_down') {
    handleMouseButtonDown(e)
  } else if (e.type == 'mouse_button_up') {
    handleMouseButtonUp(e)
  } else if (e.type == 'mouse_motion') {
    handleMouseMotion(e)
  } else if (e.type == 'key_down') {
    handleKeyDown(e)
  }
})
