open Printf

type t = (int, Deck.card Queue.t) Hashtbl.t
exception Empty_level of int

let create () = Hashtbl.create 10

let next_card cardboxes level =
    try Queue.peek (Hashtbl.find cardboxes level)
    with
        | Queue.Empty
        | Not_found -> raise (Empty_level level)

let count cardboxes level =
    try Queue.length (Hashtbl.find cardboxes level)
    with Not_found -> 0

let max cardboxes =
    Hashtbl.fold
        (fun level queue max -> if level > max then level else max)
        cardboxes
        0

let min cardboxes =
    Hashtbl.fold
        (fun level queue min -> if level < min then level else min)
        cardboxes
        max_int
    
        
let get_level cardboxes level =
    try
        Hashtbl.find cardboxes level
    with
        | Not_found -> 
              let newq = Queue.create () in
              Hashtbl.add cardboxes level newq;
              newq

let correct cardboxes level =
    let this_level = get_level cardboxes level in
    let next_level = get_level cardboxes (level+1) in

    Queue.push (Queue.pop this_level) next_level

let incorrect cardboxes level =
    let this_level = get_level cardboxes level in
    let zero_level = get_level cardboxes 0 in

    Queue.push (Queue.pop this_level) zero_level

open Deck
let of_deck deck =
    let cardboxes = create () in
    List.iter (fun (card, level) ->
                   Queue.push card (get_level cardboxes level))
        (Deck.to_list deck);
    cardboxes

let to_deck cardboxes =
    Hashtbl.fold 
        (fun level queue deck -> ();
             Queue.fold 
                 (fun deck card -> Deck.add ~level card deck)
                 deck
                 queue)
        cardboxes
        Deck.empty
                          
