(* ios othello player *)

open Ios
open XPrelude

let loginname = ref ""
    
let init host port name pwd print =
  connect host port;
  logon name pwd print false;
  loginname := name

(* just keeps getting till it gets a board, and returns it *)
let rec flushBoard () =
  match get() with
    Board b -> b
  | _ -> flushBoard ()


(* translates an IOS board into my representation and returns it *)
let readBoard iosb =
  (Board.of_array iosb.board iosb.turn_color iosb.last_move,
   if iosb.my_turn then iosb.turn_color else Board.opponent iosb.turn_color)

(* time is how many minutes to wait *)
let waitForMatch time =
  let initBoard = ref (Board.initial(), Board.Black)
  and start = Unix.time()
  and wait = float (time * 60) in
  put_str ("shout ready to play.\n");
  print_string "Waiting for a challenger...\n";
  (try while true do
    flush stdout;
    if time >= 0 && (Unix.time() -. start) > wait then begin
      print_string "Timed out waiting for an opponent.\n";
      exit 1
    end;
    match get() with
      Match_get m ->
	put (Accept m.op_name);
	Printf.printf "Accepted a game from %s\n" m.op_name;
	Printf.printf "I play %s\n" (Board.string_of_piece m.my_color);
	if m.stored then 
	  print_string "Accepted a stored game.\n";
	initBoard := readBoard (flushBoard ());
	raise Exit
    | _ ->  Unix.sleep 1
  done with Exit -> ());
  !initBoard

let challengeSomeone name rated time =
  put (Match_put ({ stored = false; is_rated = rated; my_time = time;
		   op_time = time; my_inc = 0; op_inc = 0;
		   my_def = 120; op_def = 120; my_color = Board.Black;
		   rnd_color = true; op_name = name;
		   max_win = 0; min_win = 0; min_loss = 0; max_loss = 0;
		   confirmation = false }:Ios.a_match));
  Printf.printf "Challenged %s, waiting for a response.\n" name;
  let initBoard = ref (Board.initial(), Board.Black) 
  and start = Unix.time() in
  (try while true do
    if Unix.time() -. start > 60.0 then begin
      print_string "Timed out waiting for response.\n";
      exit 1
    end;
    match get() with
      Game_create c ->
	Printf.printf "Game created with black = %s and white = %s.\n"
	  c.black c.white;
	initBoard := readBoard (flushBoard());
	raise Exit
    | _ -> Unix.sleep 1
  done with Exit -> ());
  Board.printBoard (fst !initBoard);
  !initBoard

      
let challengeAnyone rated time =
  print_string "About to challenge anyone.\n"; flush stdout;
  put Who_put;
  (try while true do
    match get() with
      Who_get who -> print_string "Got who list\n"; flush stdout; raise Exit
    | _ -> Unix.sleep 1
  done with Exit -> ());
  challenge time 0 120 None 700 1500 rated false;
  print_string "Challenged anyone, waiting for a response.\n"; flush stdout;
  let initBoard = ref (Board.initial(), Board.Black)
  and start = Unix.time() in
  (try while true do
    flush stdout;
    if Unix.time() -. start > 60.0 then begin
      print_string "Timed out waiting for response.\n";
      exit 1
    end;    
    match get() with
      Match_get m ->
	if m.confirmation then
	  Printf.printf "Got confirmation that I challenged %s\n" m.op_name
	else begin
	  put (Accept m.op_name);
	  Printf.printf "Accepted a game from %s\n" m.op_name;
	  Printf.printf "I play %s\n" (Board.string_of_piece m.my_color);
	  if m.stored then
	    print_string "Accepted a stored game.\n";
	  initBoard := readBoard (flushBoard());
	  raise Exit
	end
    | Game_create c ->
	Printf.printf "Game created with black = %s and white = %s\n"
	  c.black c.white;
	initBoard := readBoard (flushBoard());
	raise Exit
    | _ -> Unix.sleep 1
  done with Exit -> ());
  flush stdout;
  !initBoard

let iosPlayer brd =
  if (Board.blackPieces brd) > 2 || (Board.whitePieces brd) > 2 then begin
    (* this is not the first move of the game, send last move *)
    put (Move(Board.lastMove brd, 0.0, 0.0));
    ignore (flushBoard())
  end;
  if not ((Board.canMove brd Board.Black) ||
          (Board.canMove brd Board.White)) then
    None
  else begin
    let move = ref None in
    (try while true do
      flush stdout;
      match get() with
      	Match_get m ->
	  raise (Failure ("Recieved a match from "^m.op_name^" while playing."))
      | Game_end ->
          print_string "Recieved end of game, resigning.\n";
	  move := None;
	  raise Exit
      | Board b ->
	  move := Some b.last_move;
	  raise Exit
      | Moves m -> print_string "Got Moves list.\n[";
	  List.iter (function mv -> print_string (Board.string_of_move mv)) m;
	  print_string "]\n";
	  Unix.sleep 1
      | Game_create c -> print_string "Got game_create\n"; Unix.sleep 1
      | Look b ->  print_string "Received Look\n"; Unix.sleep 1
      | _ -> Unix.sleep 1
    done with Exit -> ());
    flush stdout;
    !move
  end
	  
