open ENIAM_LCGtypes
open XTTypes
open Xstd

let rec equiv_nodes = function (*
  | Tuple l1, Tuple l2 ->
    let s1 = List.sort Pervasives.compare l1 in
    let s2 = List.sort Pervasives.compare l2 in
    List.for_all2 equiv_nodes s1 s2 *)
  | Dot, Dot -> true
  | Node n1, Node n2 -> n1.lemma = n2.lemma
  | _ -> false

let equiv_partition results =
  let rec helper acc = function
    | [] -> acc
    | h :: t ->
        let a,b = List.partition (fun x -> equiv_nodes (snd h, snd x)) t in
        helper ((h :: a) :: acc) b in
  helper [] results

let rec get_measure = function
  | Tuple l -> Xlist.fold l 0 (fun acc x -> get_measure x + acc)
  | Dot -> 0
  | Node n ->
    (if n.orth = "" then 0 else 1) +
    (if n.lemma = "" then 0 else 1) +
    (if n.pos = "" then 0 else 1) +
    (if n.weight = 0. then 0 else 1) +
    (if n.id = 0 then 0 else 1) +
    (if n.symbol = Dot then 0 else 1) +
    (if n.arg_symbol = Dot then 0 else 1) +
    (if n.arg_dir = "" then 0 else 1) +
    (if n.attrs = [] then 0 else 1) +
    (if n.args = Dot then 0 else 1)
  | _ -> failwith "get_measure"

let get_representant ls =
  Xlist.fold (List.tl ls) (List.hd ls) (fun acc x ->
    if get_measure x > get_measure acc then x else acc)

let get_node = function
  | Node n -> {n with args=Dot}
  | _ -> failwith "get_node"

let rec simplify_variant = function
  | Variant(str,terms) ->
    let equivs = equiv_partition terms in
    let equivs = List.map (fun ls ->
       let ls_string = String.concat "V" (Xlist.map ls fst) ^ "|" in
       let representant = get_representant (List.map snd ls) in
       match representant with
       | Dot -> ls_string, Dot
       | Node n ->
         let rest = List.map (function (str,Node n) -> str,n.args
                                | _ -> failwith "simplify_variant__rest") ls in
         let args = simplify_variant (Variant(ls_string,rest)) in 
         ls_string, Node{n with args = args}
       | _ -> failwith "simplify_variant__representant") equivs in
    if List.length equivs = 1
    then let _,one = List.hd equivs in one
    else Variant(str,equivs)
  | _ -> failwith "simplify_variant"

let merge_results results =
  simplify_variant (Variant("PARSER_",results))
