(* Types *)

type tile = int * int * int

type terrain = {
  grid: tile array array;
  dims: int * int;
}

type resource = {
  r_pos: int * int;
  r_kind: string;
}

type building = {
  b_pos: int * int;
  b_kind: int;
  b_owner: int;
}

type unite = {
  u_pos: int * int;
  u_kind: string;
  u_owner: int;
}

(* Init-functions *)

let new_tile x y d =
  (x, y, d)

let new_terrain width height =
  let grid = Array.init height (fun y -> Array.init width (fun x -> new_tile x y 0)) in
  { grid; dims = (width, height); }

let new_resource pos kind = {
  r_pos = pos;
  r_kind = kind;
}

let new_building pos kind owner = {
  b_pos = pos;
  b_kind = kind;
  b_owner = owner;
}

let new_unite pos kind owner = {
  u_pos = pos;
  u_kind = kind;
  u_owner = owner;
}

(* Game-state *)

type game_state = {
  terrain: terrain;
  resources: resource list;
  buildings: building list;
  unites: unite list;
}

let init_state () =
  let unite1 = new_unite (10, 10) "worker" 0 in
  {
    terrain = new_terrain 68 44;
    resources = [];
    buildings = [];
    unites = unite1 :: [];
  }

(* Updates *)

let update_unite unite =
  (unite)

let update_building building =
  (building)

let update_state state =
  let unites = List.map update_unite state.unites in
  let buildings = List.map update_building state.buildings in
  { state with unites; buildings; }

(* Canvas *)

let width, height = (680, 440)

let canvas = Canvas.getElementById Canvas.document "my_canvas"
let ctx = Canvas.getContext canvas "2d"

let bg_color = "#111"

let fill_rect color (x, y) =
  Canvas.fillStyle ctx color;
  Canvas.fillRect ctx x y 10 10;
  ()
;;

(* Draw *)

let draw_resource r =
  fill_rect "#ec4" r.r_pos;
;;

let draw_building b =
  fill_rect "#59e" b.b_pos;
;;

let draw_unite u =
  fill_rect "#4d8" u.u_pos;
;;

(* Display *)

let display_game state =

  (* Background *)
  Canvas.fillStyle ctx bg_color;
  Canvas.fillRect ctx 0 0 width height;

  (* Draw Elements *)
  List.iter draw_resource state.resources;
  List.iter draw_building state.buildings;
  List.iter draw_unite state.unites;
  ()
;;

(* Events *)

let keychange_event ev =
  ()

let mousechange_event ev =
  ()

(* Main *)

let () =
  let state = ref (init_state ()) in

  let animate () =
    state := update_state !state;
    display_game !state;
    ()
  in

  Canvas.addKeyEventListener Canvas.window "keydown" keychange_event true;
  Canvas.addMouseEventListener Canvas.window "mousedown" mousechange_event true;

  let _ = Canvas.setInterval animate (1000/20) in
  ()
;;