open Lwt
open Lwt.Syntax
open Printf
open Packet

module CmdMap = Map.Make(Int)
let handlers = let open Handlers in let open Cmdid in CmdMap.(empty
  |> add cmd_player_get_token_cs_req Login.on_player_get_token
  |> add cmd_player_login_cs_req Login.on_player_login
  |> add cmd_player_login_finish_cs_req Login.on_player_login_finish
  |> add cmd_player_heart_beat_cs_req Player.on_player_heartbeat
  |> add cmd_get_basic_info_cs_req Player.on_get_basic_info
  |> add cmd_get_avatar_data_cs_req Avatar.on_get_avatar_data
  |> add cmd_get_bag_cs_req Item.on_get_bag
  |> add cmd_get_multi_path_avatar_info_cs_req Avatar.on_get_multi_path_avatar_info
  |> add cmd_get_mission_status_cs_req Mission.on_get_mission_status
  |> add cmd_get_cur_lineup_data_cs_req Lineup.on_get_cur_lineup_data
  |> add cmd_get_cur_scene_info_cs_req Scene.on_get_cur_scene_info
  |> add cmd_start_cocoon_stage_cs_req Battle.on_start_cocoon_stage
  |> add cmd_p_v_e_battle_result_cs_req Battle.on_pve_battle_result
)

let handle pk =
  match CmdMap.find_opt pk.cmd handlers with
  | Some handler -> Some (handler pk)
  | None -> printf "unhandled cmd: %d\n%!" pk.cmd; None

let rec run ic oc =
  let open Packet in
  let* pk = read ic in

  let head = Hex.show (Hex.of_string pk.head) in
  let body = Hex.show (Hex.of_string pk.body) in

  printf "packet cmd: %d, head: %s, body: %s\n%!" pk.cmd head body;

  let* () = match handle pk with
    |Some res -> (Lwt_list.iter_s (fun pk -> write oc pk) res.packets)
  | None -> return_unit
  in

  run ic oc
