(*
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 2 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*)

open Sql

let create_tables (rpmfind_db: db_connection): unit =
begin
	ignore (execute_query rpmfind_db "CREATE TABLE IF NOT EXISTS Packages ( \
	  ID INT(11) NOT NULL AUTO_INCREMENT,\
		filename VARCHAR(255) NOT NULL,\
		Name VARCHAR(255) NOT NULL,\
		Version VARCHAR(50) NOT NULL, \
		`Release` VARCHAR(50) NOT NULL, \
		Arch VARCHAR(15) NOT NULL, \
		Dist INT(11), \
		URL VARCHAR(255), \
		URLSrc VARCHAR(255), \
		Vendor INT(11), \
		Packager INT(11), \
		Category VARCHAR(255), \
		Summary VARCHAR(255), \
		Description TEXT, \
		Copyright VARCHAR(255), \
		Date INT(11), \
		Size INT(11), \
		Os VARCHAR(12), \
		PRIMARY KEY (ID), \
		KEY filename (filename(80)), \
		KEY Name (Name(15)) \
	)");
	ignore (execute_query rpmfind_db "CREATE TABLE IF NOT EXISTS Vendors ( \
    ID int(11) NOT NULL auto_increment, \
    Name VARCHAR(255) NOT NULL, \
    URL VARCHAR(255), \
    Key1 TEXT, \
    Key2 TEXT, \
    Key3 TEXT, \
    Description TEXT, \
    PRIMARY KEY (ID), \
    KEY Name (Name(10)) \
	)");
	ignore (execute_query rpmfind_db "CREATE TABLE IF NOT EXISTS Distributions ( \
    ID int(11) NOT NULL auto_increment, \
    Name varchar(255) NOT NULL, \
    URL varchar(255), \
    Key1 text, \
    Key2 text, \
    Key3 text, \
    Description text, \
    PRIMARY KEY (ID), \
    KEY Name (Name(10)) \
	)")
end;;

let add_packages (rpmfind_db: db_connection) (pkgs: pkg_metadata list): unit =
let package_add = prepare_statement rpmfind_db "INSERT INTO Packages (filename, Name, Version, `Release`, Arch, URL, URLSrc, Vendor, Packager, Category, Summary, Description, Copyright, Size, Os) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
and vendor_find = prepare_statement rpmfind_db "SELECT ID FROM Vendors WHERE Name = ?"
and vendor_add = prepare_statement rpmfind_db "INSERT INTO Vendors (Name) VALUES (?)"
and distribution_find = prepare_statement rpmfind_db "SELECT ID FROM Distributions WHERE Name = ?"
and distribution_add = prepare_statement rpmfind_db "INSERT INTO Distributions (Name) VALUES (?)" in
let get_vendor_id (vendor: string): int =
begin
	execute_statement vendor_find [| DBString (255, vendor) |];
	if !Options.verbose then
	begin
		prerr_endline ("[MySQL] fetching vendor for '" ^ vendor ^ "'...")
	end;
	let res = fetch_statement vendor_find in
	try
		match (List.hd res).(0) with DBInt x -> x | _ -> 73
	with
		Failure _ -> execute_statement vendor_add [| DBString (255, vendor) |]; Int64.to_int (statement_insert_id vendor_add)
end in
let get_distribution_id (distribution: string): int =
begin
	execute_statement distribution_find [| DBString (255, distribution) |];
	if !Options.verbose then
	begin
		prerr_endline ("[MySQL] fetching distribution for '" ^ distribution ^ "'...")
	end;
	let res = fetch_statement distribution_find in
	try
		match (List.hd res).(0) with DBInt x -> x | _ -> 73
	with
		Failure _ -> execute_statement distribution_add [| DBString (255, distribution) |]; Int64.to_int (statement_insert_id distribution_add)
end in
begin
	List.iter (fun pkg ->
		if !Options.verbose then
		begin
			prerr_endline ("[MySQL] Package: " ^ pkg.name ^ ", v" ^ pkg.version)
		end;
		let dash_index = String.rindex pkg.version '-' in
		let pkg_version = String.sub pkg.version 0 dash_index
		and pkg_release = String.sub pkg.version (dash_index + 1) ((String.length pkg.version) - dash_index - 1) 
		and packager_id = get_vendor_id pkg.maintainer
		and vendor_id = get_distribution_id pkg.distribution in
			execute_statement package_add [|
				(* filename *) DBString (255, pkg.filename);
				(* Name *) DBString (255, pkg.name);
				(* Version *) DBString (50, pkg_version);
				(* Release *) DBString (50, pkg_release);
				(* Arch *) DBString (15, match pkg.architecture with Specific s -> s | _ -> "any");
				(* URL *) DBString (255, pkg.url);
				(* URLSrc *) DBString (255, pkg.source_package);
				(* Vendor *) DBInt vendor_id;
				(* Packager *) DBInt packager_id;
				(* Category *) DBString (255, pkg.section);
				(* Summary *) DBString (255, pkg.summary);
				(* Description *) DBText pkg.description;
				(* Copyright *) DBString (255, pkg.license);
				(* Size *) DBInt (Int32.to_int pkg.installed_size);
				(* OS *) DBString (12, pkg.os)
			|]
	) pkgs 
end

let output_rpmfind (pkgs: pkg_metadata list): unit =
begin
	prerr_endline "[RPMFind] Writing rpmfind data...";
	let rpmfind_db = open_database () in
	begin
		if !Options.create_tables then create_tables rpmfind_db;
		add_packages rpmfind_db pkgs
	end
end
