------------------------------------------------------------------------------
--                              G N A T L I B                               --
--                                                                          --
--                     Copyright (C) 2006-2015, AdaCore                     --
--                                                                          --
-- This library is free software;  you can redistribute it and/or modify it --
-- under terms of the  GNU General Public License  as published by the Free --
-- Software  Foundation;  either version 3,  or (at your  option) any later --
-- version. This library is distributed in the hope that it will be useful, --
-- but WITHOUT ANY WARRANTY;  without even the implied warranty of MERCHAN- --
-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE.                            --
--                                                                          --
--                                                                          --
--                                                                          --
--                                                                          --
--                                                                          --
-- You should have received a copy of the GNU General Public License and    --
-- a copy of the GCC Runtime Library Exception along with this program;     --
-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
-- <http://www.gnu.org/licenses/>.                                          --
--                                                                          --
------------------------------------------------------------------------------

with Ada.Calendar.Formatting;   use Ada.Calendar, Ada.Calendar.Formatting;
with Ada.Environment_Variables; use Ada.Environment_Variables;
with Ada.Strings.Unbounded;     use Ada.Strings.Unbounded;
with Ada.Text_IO;               use Ada.Text_IO;
with Ada.Unchecked_Conversion;

with GNAT.Calendar.Time_IO; use GNAT.Calendar.Time_IO;
with GNATCOLL.Email.Utils;  use GNATCOLL.Email.Utils;

procedure Test_Email_Date is

   --  The following declarations are copied from the GNAT implementation of
   --  Ada.Calendar.

   type Time_Rep is range -2 ** 63 .. +2 ** 63 - 1;
   Nanos_In_Day : constant := 86_400_000_000_000;
   Ada_Low  : constant Time_Rep := -(61 * 366 + 188 * 365) * Nanos_In_Day;
   Ada_High : constant Time_Rep :=  (60 * 366 + 190 * 365) * Nanos_In_Day;
   Epoch_Offset : constant Time_Rep := (136 * 365 + 44 * 366) * Nanos_In_Day;

   function "+" is new Ada.Unchecked_Conversion (Time_Rep, Time);
   function To_Rep is new Ada.Unchecked_Conversion (Time, Time_Rep);

   procedure Set_Time_Zone (TZ : String) is
      procedure tzset;
      pragma Import (C, tzset);
   begin
      Set ("TZ", TZ);
      tzset;
   end Set_Time_Zone;

   procedure Run_Tests (TZ : String) is
      type Timestamp is record
         Rep  : Time_Rep;
         Desc : Unbounded_String;
      end record;

      function "+" (S : String) return Unbounded_String
        renames To_Unbounded_String;

   begin
      Set_Time_Zone (TZ);

      declare
         --  Initialize test points after setting TZ

         Timestamps : array (Natural range <>) of Timestamp :=
           (
            (Ada_Low,                 +"Low bound, invalid in negative TZs"),
            (-Epoch_Offset,           +"UNIX epoch"),
            (Ada_Low + Nanos_In_Day,  +"Valid in all TZs"),
            (To_Rep (Ada.Calendar.Time_Of (2012, 11, 6, 12_754.0)),
                                      +"2012-11-06T03:32:34 local time"),
            (To_Rep (Time_Of (2012, 11, 6, 12_754.0, Time_Zone => 0)),
                                      +"2012-11-06T03:32:34Z"),
            (To_Rep (Time_Of (2012, 12, 31, 0.0, Time_Zone => 0)),
                                      +"2012-12-31T00:00:00Z"),
            (0,                       +"Zero"),
            (Ada_High - Nanos_In_Day, +"Valid in all TZs"),
            (Ada_High - 1,            +"High bound-1, invalid in positive TZs"),
            (Ada_High,                +"High bound, invalid in >= 0 TZs")
           );

         T : Time;

      begin
         New_Line;
         Put_Line ("---------- TZ=" & TZ);
         for TS of Timestamps loop
            T := +TS.Rep;
            New_Line;
            begin
               Put_Line ("Timestamp:      "  & TS.Rep'Img
                                       & " " & To_String (TS.Desc));
               Put_Line ("G-CATTIO:        " & Image (T, "%c"));
               Put_Line ("Format_Date:     " & Format_Date (T, Use_GMT => False));
            exception
               when Time_Error =>
                  Put_Line ("Invalid in " & TZ);
            end;

            begin
               Put_Line ("Format_Time:     " & Format_Time (T));
               Put_Line ("Format_Date GMT: " & Format_Date (T, Use_GMT => True));
               Put_Line ("Format_Date nTZ: " & Format_Date (T, No_TZ   => True));
            exception
               when Time_Error =>
                  Put_Line ("Invalid in UTC");
            end;
         end loop;
      end;
   end Run_Tests;

begin
   Run_Tests ("GMT");
   Run_Tests ("EST");
   Run_Tests ("Europe/Paris");
end Test_Email_Date;
