(* Config *)
(* $Id$ *)

module type BASE =
  sig
    val name : string
  end
;;

module type OPT =
  sig
    val config_file : string ref
    val user_specified_config_file : bool ref
  end
;;

module Make(B:BASE)(Opt:OPT) =
  struct
    let home = Sys.getenv "HOME"
    let directory = Filename.concat home ".ara"
    let primary_file () =
      let x = !Opt.config_file in
      let x =
        if not !Opt.user_specified_config_file && Filename.is_relative x then
          Filename.concat directory x
        else
          x
      in
      Opt.config_file := x;
      x
    let current =
      new Configurator.configurator
            ~defaults:["/etc/"^(B.name)^".config"]
            ~directory
            ~primary_file:(primary_file ())
          ()
    ;;

    module Convert =
      struct
        open Configfile;;
        open Oldconfig;;

        let convert cfg =
          Record(ref [B.name,handle (Record(ref [
            "database",
              handle (Record(ref [
                "paths",
                   handle
                     (List(List.map
                       (fun (x,y) -> Tuple[String x; String y])
                       cfg.database_paths))]));
            "commands",
              let ri = "/etc/alternatives/x-terminal-emulator -e /usr/bin/sudo " in
              handle (Record(ref [
                "run_interactive", handle (String("${COMMAND}"));
                "dist_upgrade", handle (String(
                  (if B.name = "ara" then ri else "")^"/usr/bin/apt-get dist-upgrade"));
                "upgrade", handle (String(
                  (if B.name = "ara" then ri else "")^"/usr/bin/apt-get upgrade"));
                "install", handle (String(cfg.install_cmd));
                "update", handle (String(cfg.update_cmd));
                "remove", handle (String(cfg.remove_cmd));
                "print", handle (String(cfg.print_cmd));
                "pager", handle (String(cfg.pager_cmd))]))]))])
        ;;
      end
    ;;

    let load () =
      let pf = primary_file () in
      current#set_primary pf;
      let converted = ref false in
      let tl = 
        try
          Oldconfig.load Oldconfig.current pf;
          converted := true;
          [Convert.convert Oldconfig.current]
        with
        | Sys_error(x) ->
            if !Opt.user_specified_config_file then
              begin
                Printf.eprintf "Could not load configuration file: %s.\n" x;
                exit 1
              end
            else
              []
        | f -> []
      in
      let l = current#load ~merge_with:tl () in
      if !converted && not !Opt.user_specified_config_file then
        begin
          Printf.printf "Converted older configuration file.\n%!";
          current#save;
          List.filter (fun (fn,_) -> fn <> pf) l
        end
      else
        l
    ;;
  end
;;
