with Ada.Calendar.Formatting;
with Ada.Strings.Fixed;
use Ada.Strings;
package body Libsens.Util is
   
   function Integer_Image (Value : in Integer) return String is
   begin
      if Value < 0 then
	 return 
	   '-' & Integer'Image(Value)(Fixed.Index_Non_Blank(Integer'Image(Value)(2..Integer'Image(Value)'Last))..Integer'Image(Value)'Last);
      else
	 return 
	   Integer'Image(Value)(Fixed.Index_Non_Blank(Integer'Image(Value))..Integer'Image(Value)'Last);
      end if;
   end Integer_Image;
   
      procedure Difference_In_Years(Top_Date : in Time;
                                 Bot_Date : in Time;
                                 Years    : out Natural;
                                 Months   : out Natural;
                                 Days     : out Natural;
                                 Houres   : out Natural;
                                 Minutes  : out Natural;
                                 Second   : out Natural;
                                 Rest     : out Duration) is      
      
      function Is_Leap_Year (Year : Integer) return Boolean is
      begin
         return (Year rem 4 = 0) and ((Year rem 100 /= 0) or (Year rem 16 = 0));
      end Is_Leap_Year;
      
      pragma Inline (Is_Leap_Year);
      
      Days_Months_Count : constant array (Month_Number) of Day_Number := (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
      
      
      function Last_Days(Years , Months : in Natural) return Natural is         
      begin         
         if Months = 1 then
            return Days_Months_Count(12);
         elsif Months /= 3 then
            return Days_Months_Count(Months-1);
	 elsif Is_Leap_Year(Years) then
            return Days_Months_Count(2) + 1;
         else
            return Days_Months_Count(2);
         end if;
      end Last_Days;

      
      Top_Seconds : constant Day_Duration := Seconds(Top_Date);
      Bot_Seconds : constant Day_Duration := Seconds(Bot_Date);
      Top_Day     : constant Day_Number := Day(Top_Date);
      Bot_Day     : constant Day_Number := Day(Bot_Date);
      Top_Year    : constant Year_Number := Year(Top_Date);
      Bot_Year    : constant Year_Number := Year(Bot_Date);
      Top_Month   : constant Month_Number := Month(Top_Date);
      Bot_Month   : constant Month_Number := Month(Bot_Date);
      
      Years_Number  : Integer := 0;
      Months_Number : Integer := 0;
      Days_Number   : Integer := 0;            
      
      Total_Duration : Duration := Bot_Seconds - Top_Seconds;
   begin
      
      if Top_Date > Bot_Date then
         raise Constraint_Error;
      end if;
      
      Years    := 0;
      Months   := 0;
      Days     := 0;
      Houres   := 0;
      Minutes  := 0;
      Second   := 0;
      Rest     := 0.0;
      
      Years_Number := (Bot_Year - Top_Year - 1);
      
      Months_Number := Bot_Month;
      
      if (Bot_Month > Top_Month) or ((Bot_Month = Top_Month) and (Bot_Day >= Top_Day)) then         

         Years_Number := Years_Number + 1;
         
      else         
         Months_Number := Bot_Month + 12;
      end if;
      
      Months_Number := (Months_Number - Top_Month - 1);
      
      if Bot_Day >= Top_Day then

         Months_Number := Months_Number + 1;
         Days_Number := Bot_Day - Top_Day;
      else
         Days_Number := Last_Days (Bot_Year, Bot_Month);
	 Days_Number := Days_Number - Top_Day;
	 Days_Number := Days_Number + Bot_Day;
      end if;
      Days := Days_Number;
      Months := Months_Number;
      Years := Years_Number;
      
      if Bot_Seconds >= Top_seconds then
         Total_Duration := (Bot_Seconds - Top_Seconds);
      else
         Total_Duration := (86400.0 - Top_Seconds) + Bot_Seconds;
         Days := Days - 1;
      end if;
      Formatting.Split(Total_Duration, Houres, Minutes, Second, Rest);         
   end Difference_In_Years;

end Libsens.Util;