--  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.Characters.Handling;

with Nomo.Numerics.Reals.Elementary_Functions;

with Nomo.Printing;

package body Nomo.Internal_Messages.Premises.Printing is

   package body CVS is

      procedure Put_Header (File : in out File_Type;
                            I    : in Positive) is
         Index : constant String := Positive'Image (I) (2 .. Positive'Image (I)'Last);
      begin
         Put (File, ", ip_" & Index & "_category");
         Put (File, ", ip_" & Index & "_type");
         Put (File, ", ip_" & Index & "_property");
         Put (File, ", ip_" & Index & "_specificity");
         Put (File, ", ip_" & Index & "_credibility");
         Put (File, ", ip_" & Index & "_c_actuator");
         Put (File, ", ip_" & Index & "_c_tolerance");
         Put (File, ", ip_" & Index & "_timespan");
         Put (File, ", ip_" & Index & "_t_actuator");
         Put (File, ", ip_" & Index & "_t_tolerance");
         Put (File, ", ip_" & Index & "_information");
      end Put_Header;

      procedure Put_NA (File : in out File_Type) is
         use Nomo.Printing;
      begin
         for I in 1 .. 11 loop
            Put (File, ", " & NA);
         end loop;
      end Put_NA;

      procedure Put (File     : in out File_Type;
                     This     : in Internal_Premise;
                     Category : in Type_Category;
                     Id       : in Internal_Type_Index;
                     Property : in Premise_Property) is
         use Nomo.Printing;
         use Numerics.Reals.Elementary_Functions;
      begin
         Put (File, ", " & Type_Category'Image (Category));
         Put (File, "," & Internal_Type_Index'Image (Id));
         Put (File, ", " & Premise_Property'Image (Property));
         Put (File, "," & Real_Accurately'Image (This.Specificity_Log));
         Put (File, "," & Real_0_To_1'Image (This.Credibility));
         if This.Credibility_Tolerance = Zero_Plus then
            Put (File, ", 0.0");
            Put (File, ", " & NA);
         elsif This.Credibility_Tolerance = Positive_Infinity then
            Put (File, ", INF");
            Put (File, ", " & NA);
         else
            Put (File, "," & Real_0_To_1'Image (This.Actuator_Credibility));
            Put (File, "," & Real'Image (Sqrt (This.Credibility_Tolerance / 2.0)));
         end if;
         Put (File, "," & Time_Interval'Image (This.Time_Span));
         Put (File, "," & Time_Interval'Image (This.Actuator_Time_Span));
         if This.Time_Span_Tolerance = Zero_Plus then
            Put (File, ", 0.0");
         elsif This.Time_Span_Tolerance = Positive_Infinity then
            Put (File, ", INF");
         else
            Put (File, "," & Real'Image (Sqrt (This.Time_Span_Tolerance / 2.0)));
         end if;
         case This.Tolerance is
            when IN_TN_CN | IN_TN_CI | IN_TI_CN | IN_TI_CI | IN_TN_CP | IN_TI_CP | IN_TP_CP | IN_TP_CN | IN_TP_CI =>
               Put (File, "," & Positive_Integer'Image (This.Information));
            when others =>
               Put (File, ", " & NA);
         end case;
      end Put;

   end CVS;

   package body XML is

      procedure Put (File     : in out File_Type;
                     This     : in Internal_Premise;
                     Category : in Type_Category;
                     Id       : in Internal_Type_Index;
                     Property : in Premise_Property) is
      begin
         Put (File, "<premise category=""" & Type_Category'Image (Category) & """");
         Put (File, " type=""" & Internal_Type_Index'Image (Id) & """");
         Put (File, " property=""" & Premise_Property'Image (Property) & """");
         Put (File, " specificity_log=""" & Real_Accurately'Image (This.Specificity_Log) & """ />");
         case This.Tolerance is
            when IN_TN_CN | IN_TN_CI | IN_TI_CN | IN_TI_CI | IN_TN_CP | IN_TI_CP | IN_TP_CP | IN_TP_CN | IN_TP_CI =>
               Put (File, "<information value=""" & Positive_Integer'Image (This.Information) & """ tolerance=""0"" />");
            when others =>
               Put (File, "<information value=""" & Positive_Integer'Image (This.Information) & """ tolerance=""INF"" />");
         end case;
         Put (File, "<credibility value=""" & Real_0_To_1'Image (This.Credibility) & """");
         if This.Credibility_Tolerance = Zero_Plus then
            Put (File, " tolerance =""0.0""");
         elsif This.Credibility_Tolerance = Positive_Infinity then
            Put (File, " tolerance =""INF""");
         else
            Put (File, " tolerance =""" & Strictly_Positive_Real'Image (This.Credibility_Tolerance / 2.0) & """");
         end if;
         Put (File, " actuator ="""  & Real_0_To_1'Image (This.Actuator_Credibility) & """ />");
         Put (File, "<timespan value=""" & Time_Interval'Image (This.Time_Span) & """");
         if This.Time_Span_Tolerance = Zero_Plus then
            Put (File, " tolerance =""0.0""");
         elsif This.Time_Span_Tolerance = Positive_Infinity then
            Put (File, " tolerance =""INF""");
         else
            Put (File, " tolerance =""" & Strictly_Positive_Real'Image (This.Time_Span_Tolerance / 2.0) & """");
         end if;
         Put (File, " actuator ="""  & Time_Interval'Image (This.Actuator_Time_Span) & """ />");
         Put (File, "</premise>");
      end Put;

   end XML;

   package body DB is

      procedure Put (File     : in out File_Type;
                     T        : in Time;
                     Rule_Id  : in Positive;
                     Index    : in String;
                     This     : in Internal_Premise;
                     Id       : in Internal_Type_Index;
                     Property : in Premise_Property) is
         use Nomo.Printing;
         use Numerics.Reals.Elementary_Functions;
      begin
         Put (File, Time'Image (T));
         Put (File, "," & Positive'Image (Rule_Id));
         Put (File, "," & Index);
         Put (File, "," & Real_Accurately'Image (This.Specificity_Log));
         Put (File, ", " & Ada.Characters.Handling.To_Lower (Premise_Property'Image (Property)(1..10)));
         Put (File, "," & Internal_Type_Index'Image (Id));
         case This.Tolerance is
            when IN_TN_CN | IN_TN_CI | IN_TI_CN | IN_TI_CI | IN_TN_CP | IN_TI_CP | IN_TP_CP | IN_TP_CN | IN_TP_CI =>
               Put (File, "," & Positive_Integer'Image (This.Information));
            when others =>
               Put (File, ", " & NA);
         end case;
         Put (File, "," & Real_0_To_1'Image (This.Credibility));
         Put (File, "," & Real_0_To_1'Image (This.Actuator_Credibility));
         if This.Credibility_Tolerance = Zero_Plus then
            Put (File, ", 0.0");
         elsif This.Credibility_Tolerance = Positive_Infinity then
            Put (File, ", INF");
         else
            Put (File, "," & Real'Image (Sqrt (This.Credibility_Tolerance / 2.0)));
         end if;
         Put (File, "," & Time_Interval'Image (This.Time_Span));
         Put (File, "," & Time_Interval'Image (This.Actuator_Time_Span));
         if This.Time_Span_Tolerance = Zero_Plus then
            Put_Line (File, ", 0.0");
         elsif This.Time_Span_Tolerance = Positive_Infinity then
            Put_Line (File, ", INF");
         else
            Put_Line (File, "," & Real'Image (Sqrt (This.Time_Span_Tolerance / 2.0)));
         end if;
      end Put;

   end DB;

end Nomo.Internal_Messages.Premises.Printing;
