(*
This file is part of Ceve.

Ceve is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.

Ceve is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Ceve; if not, write to the Free Software
Foundation, Inc., 52 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*)

open Napkin
open Options

let dose_of_field (name: string) (contents: string): string * string * string list =
begin
	try
		let newline_index = String.index contents '\n' in
		let first_line = String.sub contents 0 newline_index in
		let next_lines = Str.split (Str.regexp_string "\n") (String.sub contents (newline_index + 1) ((String.length contents) - newline_index - 1)) in
			(name, first_line, next_lines)
	with Not_found -> (name, contents, [])
end;;

let dose_of_dependencies (deps: (string, string, string) versioned list): string =
begin
	String.concat ", " (List.sort compare (Tools.uniq (List.map string_of_versioned (List.filter (
		fun d -> match d with
		| Unit_version (u, _) -> not (Tools.starts_with "rpmlib" u)
		| Glob_pattern g -> true)
	deps))))
end;;

let dose_of_dep_expression (deps: (string, string, string) versioned list list): string =
begin
	String.concat ", " (List.sort compare (Tools.uniq (List.filter (fun z -> z <> "")
	(List.map (fun x ->
		String.concat " | " (List.sort compare (Tools.uniq (List.map string_of_versioned (List.filter (fun d ->
			match d with
			| Unit_version (u, _) -> not (Tools.starts_with "rpmlib" u)
			| Glob_pattern g -> true
		) x))))
	) deps))))
end

let to_dose (pkg: default_package): (string * string * string list) list =
begin
	[
		("Architecture", pkg.pk_architecture, []);
		("Conflicts", dose_of_dependencies pkg.pk_conflicts, []);
		("Depends", dose_of_dep_expression pkg.pk_depends, []);
		("Enhances", dose_of_dep_expression pkg.pk_enhances, []);
		("Essential", (if pkg.pk_essential then "yes" else "no"), []);
		("Installed-Size", Int64.to_string pkg.pk_installed_size, []);
		dose_of_field "Package" pkg.pk_unit;
		("Pre-Depends", dose_of_dep_expression pkg.pk_pre_depends, []);
		("Provides", dose_of_dependencies (List.filter (fun d -> 
			match d with
			| Unit_version (u, _) -> not (Tools.starts_with "rpmlib" u)
			| Glob_pattern g -> true) pkg.pk_provides), []);
		("Recommends", dose_of_dep_expression pkg.pk_recommends, []);
		("Replaces", dose_of_dependencies pkg.pk_replaces, []);
		("Size", Int64.to_string pkg.pk_size, []);
		("Source", (let (x, y) = pkg.pk_source in x ^ " " ^ y), []);
		("Suggests", dose_of_dep_expression pkg.pk_suggests, []);
		dose_of_field "Version" pkg.pk_version
	]
end;;

let output_dose (pkgs: default_package list): unit =
let module DBO = Dosebase.Out in
let set_type = if !dose_type <> "" then 
  !dose_type
else
  match !input_type with
	| Debian | DebianCache -> "debian"
	| RPM | HDList -> "rpm"
	| Pkgsrc -> "pkgsrc"
	| _ -> "unknown"
in	
let db = DBO.open_out ~set_type !output_dir in
begin
	prerr_endline "[Dose] adding packages...";
	List.iter (fun pkg ->
		if !verbose then
		begin
			prerr_endline ("[Dose] adding package " ^ pkg.pk_unit ^ ")")
		end;
	  DBO.add_package db ~archive:!dose_archive ~day:(Lifetime.day_of_ymd !dose_date) (to_dose pkg)
  ) pkgs;
	prerr_endline "[Dose] closing database...";
	DBO.close_out db
end;;
