--  Copyright (2008-2013) Cédric Coussinet (cedric.coussinet@nomoseed.net)
--
--  This program is free software: you can redistribute it and/or modify
--  it under the terms of the GNU Affero General Public License as published
--  by the Free Software Foundation, either version 3 of the License, or
--  (at your option) any later version.
--
--  This program 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 Affero General Public License for more details.

--  You should have received a copy of the GNU Affero General Public License
--  along with this program. If not, see <http://www.gnu.org/licenses/>

with Ada.Directories;

with Ada.IO_Exceptions;

with Ada.Strings.Unbounded;

package body Nomo.Gen_Rule_Storages.Partial_Printing is

   package body CVS is

      procedure Put_Header (File : in out File_Type) is
      begin
         Put (File, "time");
         Put (File, ", id");
         Put (File, ", category");
         Put (File, ", type");
         Put (File, ", fitting_nbr");
         Put (File, ", relevance");
         Put (File, ", credibility");
      end Put_Header;

      procedure Put (File : in out File_Type;
                     This : in Partial_Rule_Storage;
                     T    : in Time) is
      begin
         Put (File, Time'Image (T));
         Put (File, "," & Positive'Image (This.Id));
         Put (File, "," & Type_Category'Image (Get_Category (This.Conclusion_Type)));
         Put (File, "," & Internal_Type_Index'Image (This.Conclusion_Type));
         Put (File, "," & Numerics.Fitting.Count'Image (This.Fitting_Nbr - 1));
         Put (File, "," & Real_Accurately_0_To_1'Image (This.Relevance));
         Put (File, "," & Real_0_To_1'Image (This.Credibility));
      end Put;

   end CVS;

   package body XML is

      procedure Put_Header (File : in out File_Type) is
      begin
         Put (File, "<?xml version=""1.0"" encoding=""Utf-8"" standalone=""No""?>");
         Put (File, "<rules>");
      end Put_Header;

      procedure Put (File : in out File_Type;
                     This : in Partial_Rule_Storage;
                     T    : in Time) is
      begin
         Put (File, "<rule time=""" & Time'Image (T) & """");
         Put (File, " id=""" & Positive'Image (This.Id) & """");
         Put (File, " category=""" & Type_Category'Image (Get_Category (This.Conclusion_Type)) & """");
         Put (File, " type=""" & Internal_Type_Index'Image (This.Conclusion_Type) & """");
         Put (File, " fitting_nbr=""" & Numerics.Fitting.Count'Image (This.Fitting_Nbr) & """");
         Put (File, " relevance=""" & Real_Accurately_0_To_1'Image (This.Relevance) & """");
         Put (File, " credibility=""" & Real_0_To_1'Image (This.Credibility) & """ />");
      end Put;

      procedure Put_Ending (File : in out File_Type) is
      begin
         Put (File, "</rules>");
      end Put_Ending ;

   end XML;

   package body DB is

      Rule_Id_Max : Positive;
      Is_New_Id   : Boolean;
      Program     : Ada.Strings.Unbounded.Unbounded_String;

      procedure Create (Path : in String) is
      begin
         Create (Log, Out_File, Path & "log.csv");
         Put (Log, "time");
         Put (Log, ", rule_id");
         Put (Log, ", fitting_nbr");
         Put (Log, ", relevance");
         Put_Line (Log, ", credibility");
         Open_Rule (Path);
      end Create;

      procedure Open_Rule (Path : in String) is
         use Ada.Strings.Unbounded;
         I : Natural;
         Buffer : Unbounded_String;
      begin
         if Ada.Directories.Exists (Path & "rule.csv") then
            Rule_Id_Max := 1;
            Is_New_Id := False;
            Open (Rule, In_File, Path & "rule.csv");
            while not End_Of_File (Rule) loop
               Buffer := To_Unbounded_String(Get_Line (Rule));
            end loop;
            Close (Rule);
            I := Index (Buffer, ", ", Length(Buffer), Ada.Strings.Backward) - 1;
            I := Index (Buffer, ", ", I, Ada.Strings.Backward) + 2;
            Program := Unbounded_Slice (Buffer, I, Index (Buffer, " ", I));
            I := Index (Program, ",", Length(Program), Ada.Strings.Backward);
            if I /= 0 then
               Program := Unbounded_Slice (Program, 1, I - 1);
            end if;
            Rule_Id_Max := Positive'Value (Slice(Buffer, 1, Index (Buffer, ",", 1) - 1));
            Open (Rule, Append_File, Path & "rule.csv");
         else
            Rule_Id_Max := Positive'Last;
         end if;
      end Open_Rule;


      procedure Open (Path : in String) is
      begin
         Open (Log, Append_File, Path & "log.csv");
         Open_Rule (Path);
      exception
         when Ada.IO_Exceptions.Name_Error =>
            Create (Path);
      end Open;

      procedure Put (This : in Partial_Rule_Storage;
                     T    : in Time) is
      begin
         Put (Log, Time'Image (T));
         Put (Log, "," & Positive'Image (This.Id));
         Put (Log, "," & Numerics.Fitting.Count'Image (This.Fitting_Nbr));
         Put (Log, "," & Real_Accurately_0_To_1'Image (This.Relevance));
         Put_Line (Log, "," & Real_0_To_1'Image (This.Credibility));
         if This.Id > Rule_Id_Max then
            declare
               use Ada.Strings.Unbounded;
               Rule_Id : constant String := Positive'Image (This.Id);
            begin
               if not (Is_New_Id) then
                  Is_New_Id := True;
                  New_Line (Rule);
               end if;
               Put (Rule, Rule_Id(2 .. Rule_Id'Last));
               Put (Rule, ", R" & Rule_Id (2 .. Rule_Id'Last));
               Put (Rule, ", " & To_String (Program));
               Put (Rule, ", " & To_String (Program));
               Put_Line (Rule, "," & Internal_Type_Index'Image (This.Conclusion_Type));
            end;
         end if;
      end Put;

      procedure Close is
      begin
         Close (Log);
         Close (Rule);
      end Close;

   end DB;

end Nomo.Gen_Rule_Storages.Partial_Printing;
