open Common_options;;
open Type_options;;

type action = 
    Split of string 
  | Test of string
  | Join

exception Not_enough_part
exception Invalid_format

(* Return (part of the list which correspond to the net arg, part of the list wich doesn't
   correspond to the net arg) *)
   
let filter_network arg files_lst =
  let is_arg_network options =
    let extracted_network =
      match options with 
        ValModule(top) ->
          begin
          match find_option "file_network" top with 
          ValString(net) 
        | ValIdent(net) ->
          net
        | _ ->
          raise Invalid_format
        end
      | _ ->
        raise Invalid_format
    in
    extracted_network = arg 
  in
  List.partition is_arg_network files_lst
;;

let test_network arg files_lst =
  let (lst,_) = filter_network arg files_lst
  in
  lst <> []
;;

let load_files_ini filename =
  let options = 
          load_option filename
  in
  let done_files =
    match find_option "done_files" options with
    ValList(x) -> x
    | _ -> raise Invalid_format
  in
  let files =
    match find_option "files" options with
    ValList(x) -> x
    | _ -> raise Invalid_format
  in
  (done_files,files)
;;

let save_files_ini filename (done_files,files) =
  save_option filename (
    Options(Id("done_files",ValList(done_files)),
    Options(Id("files",ValList(files)),Eof)
  ))
;;

let _ = 
  let action = ref Join
  in
  let filename_part0 = ref None
  in
  let filename_part1 = ref None
  in
  let filename_part2 = ref None
  in
  let quiet = ref false
  in
  let _ = Arg.parse [
    ("--split", Arg.String ( fun x -> action := Split x ),
       "Split file '-f0', put entry with source network arg in '-f1', rest in '-f2'");
    ("--test", Arg.String ( fun x -> action := Test x),
      "Test if file '-f0' contains source network arg");
    ("--join", Arg.Unit ( fun () -> action := Join ),
      "Joind file '-f1' and '-f2', put result in '-f0'");
    ("-f0", Arg.String ( fun x -> filename_part0 := Some x ),
      "Which '-f0' to use");
    ("-f1", Arg.String ( fun x -> filename_part1 := Some x ),
      "Which '-f1' to use");
    ("-f2", Arg.String ( fun x -> filename_part2 := Some x ),
      "Which '-f2' to use");
    ("-q", Arg.Set quiet,
      "Run quietly");
    ]
    ( fun _ -> () )
    "Usage mldonkey_files [options] where options are :"
  in
  try 
  begin
    match (!action,!filename_part0,!filename_part1,!filename_part2) with
      (Join      ,Some(part0),Some(part1),Some(part2)) ->
      let (done_files1,files1) = load_files_ini part1
      in
      let (done_files2,files2) = load_files_ini part2
      in
      save_files_ini part0 (done_files1@done_files2,files1@files2)
    | (Split(net),Some(part0),Some(part1),Some(part2)) ->
      let (done_files0,files0) = 
        load_files_ini part0
      in
      let (files1,files2) = 
        filter_network net files0
      in
      save_files_ini part1 ([]         ,files1);
      save_files_ini part2 (done_files0,files2)
    | (Test(net), Some(part0), _, _) ->
      let (done_files0,files0) =
        load_files_ini part0
      in
      if test_network net files0 then
        (
          (
            if !quiet then 
              ()
            else
              Printf.printf "File %s contains source from network %s.\n" part0 net
          );
          exit 0
        )
      else
        (
          (
            if !quiet then
              ()
            else
              Printf.printf "File %s doesn't contain source from network %s.\n" part0 net
          );
          exit 1
        )
    | (Join,    None,_,_)
    | (Split(_),None,_,_)
    | (Test(_), None,_,_)
    | (Join,    _,None,_)
    | (Split(_),_,None,_)
    | (Join,    _,_,None)
    | (Split(_),_,_,None) ->
      raise Not_enough_part
  end
  with Not_found ->
    raise Invalid_format
;;
