(* Config *)
(* $Id: config.ml,v 1.5 2004/10/26 09:44:54 berke Exp $ *)

type t = {
  mutable database_paths : (string * string) list;
  mutable install_cmd : string;
  mutable remove_cmd : string;
  mutable update_cmd : string;
  mutable print_cmd : string;
  mutable pager_cmd : string
}
;;

let gui_default = {
  database_paths = [("/var/lib/apt/lists/","_Packages$");("/var/lib/dpkg/","^status$")];
  install_cmd = "/etc/alternatives/x-terminal-emulator -e /usr/bin/sudo /usr/bin/apt-get install ${PACKAGE}=${VERSION}";
  remove_cmd = "/etc/alternatives/x-terminal-emulator -e /usr/bin/sudo /usr/bin/apt-get remove ${PACKAGE}=${VERSION}";
  update_cmd = "/etc/alternatives/x-terminal-emulator -e /usr/bin/sudo /usr/bin/apt-get update";
  print_cmd = "/usr/bin/a2ps -q";
  pager_cmd = "/etc/alternatives/pager"
}
;;
let cli_default = {
  database_paths = [("/var/lib/apt/lists/","_Packages$");("/var/lib/dpkg/","^status$")];
  install_cmd = "/usr/bin/sudo /usr/bin/apt-get install ${PACKAGE}=${VERSION}";
  remove_cmd = "/usr/bin/sudo /usr/bin/apt-get remove ${PACKAGE}=${VERSION}";
  update_cmd = "/usr/bin/sudo /usr/bin/apt-get update";
  print_cmd = "/usr/bin/a2ps";
  pager_cmd = "/etc/alternatives/pager"
}
;;

let duplicate x = { x with update_cmd = x.update_cmd };;
let overwrite x y =
  y.database_paths <- x.database_paths;
  y.install_cmd <- x.install_cmd;
  y.remove_cmd <- x.remove_cmd;
  y.update_cmd <- x.update_cmd;
  y.print_cmd <- x.print_cmd;
  y.pager_cmd <- x.pager_cmd
;;

let current = duplicate gui_default;;

let fp = Printf.fprintf;;

let directory = Filename.concat (Sys.getenv "HOME") ".ara";;

let path str = Filename.concat directory str;;

let ensure_directory_presence () =
  if not (Sys.file_exists directory) then
    Unix.mkdir directory 0o755 
;;

let save cfg fn =
  ensure_directory_presence ();
  let oc = open_out fn in
  fp oc "database_paths";
  List.iter (fun (x,y) -> fp oc " path %S %S" x y) cfg.database_paths;
  fp oc " end\n";
  fp oc "install_cmd %S\n" cfg.install_cmd;
  fp oc "remove_cmd %S\n" cfg.remove_cmd;
  fp oc "update_cmd %S\n" cfg.update_cmd;
  fp oc "print_cmd %S\n" cfg.print_cmd;
  fp oc "pager_cmd %S\n" cfg.pager_cmd;
  close_out oc
;;

exception Invalid_configuration_file of string;;

let load cfg fn =
  let sb = Scanf.Scanning.from_file fn in
  try
    while true do
      Scanf.bscanf sb " %[a-z0-9_] " (function
        | "database_paths" ->
            let rec loop pth =
              Scanf.bscanf sb " %s" (function
                | "path" ->
                    Scanf.bscanf sb " %S %S"
                      (fun x y -> loop ((x,y)::pth)) (* not tail rec *)
                | "end" ->
                    (* Debug.debug 10 (Debug.sf "database_paths [%s]"
                      (String.concat ";" (List.map
                        (fun (x,y) -> Printf.sprintf "%S,%S" x y) pth))); *)
                    cfg.database_paths <- pth
                | _ -> raise (Invalid_configuration_file
                  (Printf.sprintf "Error in database path specification in file %S" fn)))
            in
            loop []
        | "install_cmd" -> Scanf.bscanf sb "%S" (fun x -> cfg.install_cmd <- x)
        | "remove_cmd" -> Scanf.bscanf sb "%S" (fun x -> cfg.remove_cmd <- x)
        | "update_cmd" -> Scanf.bscanf sb "%S" (fun x -> cfg.update_cmd <- x)
        | "print_cmd" -> Scanf.bscanf sb "%S" (fun x -> cfg.print_cmd <- x)
        | "pager_cmd" -> Scanf.bscanf sb "%S" (fun x -> cfg.pager_cmd <- x)
        | x ->
            if x = "" && Scanf.Scanning.end_of_input sb then
              raise End_of_file (* Scanf bug (?) workaround *)
            else
              raise (Invalid_configuration_file
                      (Printf.sprintf "Unexpected token %S in file %S" x fn)))
    done
  with
  | End_of_file -> ()
;;

