-- Skywalker is another attempt of A. i. written with Ada.
-- Skywalker is Copyright (C) 2024 Manuel De Girardi ; 
--
--   This program 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.
--
--   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 General Public License for more details.
--
--   You should have received a copy of the GNU General Public License
--   along with this program; if not, write to the Free Software
--   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
--
-- Date := "2024-11-13 06:51:20"
-- Version := "0.0.10r"
with Ada.Wide_Text_Io;
use Ada.Wide_Text_Io;
--with Computer.Bank;
with Gnat.Os_Lib;
use Gnat.Os_Lib;

with Ada.Calendar.Formatting;

with Ada.Characters.Handling;
use Ada.Characters;

package body Sky.Accountant is
   
      package W_Io renames Ada.Wide_Text_Io;
   
   
   procedure Create(Activity : out Balance_Record;
		    From : in Outvoice_Record) is
   -- Write all account_line to States.
   -- Check Outvoice with accounting.
   begin
      null;
   end Create;
   
   procedure billed(Activity : in out Balance_Record;
		    Invoice : in Invoice_Record;
		    
		    Payed : out Boolean) is
      -- if Is_Payed(Invoice) then must be added to to account num
      
   begin
      
      

      Payed := Is_Payed(Invoice);      

      if Payed then

	 Activity.TVA_Out :=
	   --  Fixed_Total
	   --  (Fixed_Total
	   --     (Balance.Balance.TVA_in +
	   --  	 (Fixed_Total
	   --  	    (Fixed_Total(Fixed_Total(Invoice.Total_Ht))) / Fixed_Total(100.0))) * 
	   --     Fixed_Total(Invoice.TVA_Rate));
	   Balance.Balance.TVA_Out + (Fixed_Total(Invoice.Total_TTC - Invoice.Total_Ht));

	 Activity.Capital := 
	   Activity.Capital - Invoice.Total_TTC;

      end if;
      
      
   end Billed;
   
   procedure Charge(Activity : in out Balance_Record;
		    Outvoice : in Outvoice_Record;
		    
		    Payed : out Boolean) is
      -- if Is_Payed(Outvoice) then must be added to to account num
      
   begin
      
      
      Payed := Is_Payed(Outvoice);
      
      if Payed then
	 
	 Activity.TVA_in := Activity.TVA_In + Outvoice.Total_Tva;
	 

	 Activity.Material := 
	   Activity.Material + Outvoice.Total_TTC;
	 

      end if;
      
   end Charge;
   
   procedure Open(Activity : in out Balance_Record;
		  Accounting_States : in Accounting_Record) is
   begin
      null;
   end Open;
     
   
   procedure Close(Activity : in out Balance_Record;
		   Accounting_States : in Accounting_Record) is
      Tmp : Fixed_Total := Activity.Material;
   begin
      Activity.Material := (Tmp - Activity.TVA_In) + Activity.TVA_Out;
      
      Activity.Capital := Activity.Capital + Activity.Material;
      
      Activity.TVA_In := 0.0;      
      Activity.TVA_Out := 0.0;
      Activity.Material := 0.0;
      
   end Close;
   
      
   function Is_Payed(Voice : in Invoice_Record'Class) return Boolean is
      Payed : Boolean := False;
   begin
      if Voice.Total_TTC = 0.0 then
	 return True;
      elsif Balance.Balance.Capital >= Voice.Total_TTC then
	 return True;
      else
	 W_Io.Put_Line(Handling.To_Wide_String(Fixed_Total'Image(Balance.Balance.Capital) & "<" & Fixed_Total'Image(Voice.Total_TTC)));
      end if;
      return Payed;
   end Is_Payed;
     
   function Is_Payed(Voice : in Outvoice_Record'Class) return Boolean is
      Payed : Boolean := True;
   begin
      return Payed;
   end Is_Payed;
   
   procedure Line_Add (To : in out Abstracted_Voice;
		       Line : in Account_Line_Type) is
   begin
      To.Accounting(To.Line_Last + 1) := Line;      
      To.Line_Last := To.Line_Last + 1;
      To.Total_Ht := To.Total_HT + Line.Total_HT;
      To.Total_TTC := To.Total_TTC + Line.Total_TTC;
      To.Total_TVA := To.Total_TVA + Line.Total_TVA;      
   end Line_Add;
   
   procedure Line_Remove (To : in out Abstracted_Voice;
			  Line_Num : in Account_Line_Range) is
   begin
      if Line_Num = 0 or Line_Num > To.Line_Last then
	 raise Spec_Error;
      end if;
      for Line in 1..To.Line_Last loop
	 if To.Accounting(Line).Line_Num = Line_Num then
	    
	    To.Total_Ht := To.Total_Ht - To.Accounting(Line).Total_Ht;
	    To.Total_TVA := To.Total_TVA - To.Accounting(Line).Total_TVA;
	    To.Total_TTC := To.Total_TTC - To.Accounting(Line).Total_TTC;
	    
	    for Iter in Line..To.Line_Last - 1 loop
	       To.Accounting(Iter) := To.Accounting(Iter + 1);
	    end loop;
	    To.Accounting(To.Line_Last) := Null_Line;
	    To.Line_Last := To.Line_Last - 1;
	    exit;
	 end if;
      end loop;
      
      --  To.Total_Ht := To.Total_Ht - To.Accounting(Line_Num).Total_Ht;
      --  To.Total_TTC := To.Total_TTC - To.Accounting(Line_Num).Total_TTC;
      --  To.Total_TVA := To.Total_TVA - To.Accounting(Line_Num).Total_TVA;
      
      --  for Iter in Line_Num..To.Line_Last - 1 loop
      --  	 To.Accounting(Iter) := To.Accounting(Iter + 1);
      --  end loop;
      --  To.Accounting(To.Line_Last) := Null_Line;
      --  To.Line_Last := To.Line_Last - 1;
	 
   end Line_Remove;
   
   procedure Add(To : in out Accounting_Record;
		 Invoice : in Invoice_Record) is
   begin
      if To.Invoice_Last < To.Billed'Length then
	 To.Billed(To.Invoice_Last + 1) := Invoice;
	 To.Invoice_Last := To.Invoice_Last + 1;
      end if;
      
   end Add;
   procedure Add(To : in out Accounting_Record;
		 Outvoice : in Outvoice_Record) is
   begin
      if To.outvoice_Last < To.Charges'Length then
	 To.Charges(To.Outvoice_Last + 1) := Outvoice;
	 To.Outvoice_Last := To.Outvoice_Last + 1;
      end if;
   end Add;
   
   procedure Invoice_Remove(To : in out Accounting_Record;
			    Invoice_num : in Voice_Num_Range) is
   begin
      if To.Invoice_Last /= 0 then
	 for Voice in 1..To.Invoice_Last loop
	    if To.Billed(Voice).voice_Num = Invoice_Num then
	       for Iter in Voice..To.inVoice_Last - 1 loop
		  To.Billed(Iter) := To.Billed(Iter + 1);
		  
	       end loop;
	       To.Billed(To.inVoice_Last) := Null_Invoice;
	       To.invoice_Last := To.invoice_Last - 1;		 
	       exit;
	    end if;
	 end loop;
      end if;
   end Invoice_Remove;
   procedure Outvoice_Remove(To : in out Accounting_Record;
		    Outvoice_num : in Voice_Num_range) is
   begin
      if To.Outvoice_Last /= 0 then
	 for Voice in 1..To.Outvoice_Last loop
	    if To.Charges(Voice).voice_Num = Outvoice_Num then
	       for Iter in Voice..To.outvoice_Last - 1 loop
		  To.Charges(Iter) := To.Charges(Iter + 1);
		  
	       end loop;
	       To.Charges(To.outvoice_Last) := Null_Outvoice;
	       To.outvoice_Last := To.outvoice_Last - 1;		 
	       exit;
	    end if;
	 end loop;
      end if;
   end Outvoice_Remove;
   
   
   procedure Voice_Save(Voice : in Abstracted_Voice; Filename : in String) is
      File : W_Io.File_Type;
   begin
      if Is_Regular_File(Filename) then
	 W_Io.Open(File, W_Io.Append_File, Filename, Form => "WCEM=8");
      else
	 W_Io.Create(File, W_Io.Out_File, Filename, Form => "WCEM=8");
      end if;
      
      W_Io.Put_Line(File, Handling.To_Wide_String(Voice_Num_Range'Image(Voice.Voice_Num)));
      W_Io.Put_Line(File, Handling.To_Wide_String(Account_Num_Range'Image(Voice.Account_Num)));
      W_Io.Put_Line(File, Handling.To_Wide_String(Fixed_Total'Image(Voice.Total_Ht)));
      W_Io.Put_Line(File, Handling.To_Wide_String(Fixed_Total'Image(Voice.Total_TVA)));
      W_Io.Put_Line(File, Handling.To_Wide_String(Fixed_Total'Image(Voice.Total_TTC)));
      W_Io.Put_Line(File, Voice.Peer_Name);
      W_Io.Put_Line(File, Handling.To_Wide_String(Formatting.Image(Voice.Date)));
      W_Io.Close(File);
   end Voice_Save;
   
   function Save(voice : in Invoice_Record; Filename : in String) return Boolean is
   begin
      Voice_Save(Abstracted_Voice(Voice), Filename);
      return True;
   exception
      when others =>
	 return False;
   end Save;
   function Save(voice : in Outvoice_Record; Filename : in String) return Boolean is
   begin
      Voice_Save(Abstracted_Voice(Voice), Filename);
      return True;
   exception
      when others =>
	 return False;
   end Save;
   
   
   procedure Restore (Voice : out Abstracted_Voice; File : in out W_Io.File_Type) is
   begin

      Voice.Voice_Num := Voice_Num_Range'Value(Handling.To_String(W_Io.Get_Line(File)));

      Voice.Account_Num := Account_Num_Range'Value(Handling.To_String(W_Io.Get_Line(File)));

      Voice.Total_Ht := Fixed_Total'Value(Handling.To_String(W_Io.Get_Line(File)));

      Voice.Total_TVA := Fixed_Total'Value(Handling.To_String(W_Io.Get_Line(File)));

      Voice.Total_TTC := Fixed_Total'Value(Handling.To_String(W_Io.Get_Line(File)));

      Voice.Peer_Name := W_Io.Get_Line(File);

      Voice.Date := Formatting.Value(Handling.To_String(W_Io.Get_Line(File)));

   end Restore;
   procedure Invoices_Restore(Invoices : out Invoice_Array; Last : out Natural; Filename : in String) is
      File : W_Io.File_Type;
   begin

      if Is_Regular_File(Filename) then
	 W_Io.Open(File, W_Io.In_File, Filename, Form => "WCEM=8");
      end if;

      Last := 0;
      while not W_Io.End_Of_File(File) loop

	 Restore(Abstracted_Voice(Invoices(Last + 1)), File);
	 Last := Last + 1;
	 
      end loop;
      W_Io.Close(File);
   end Invoices_Restore;
   procedure OutVoices_Restore(Outvoices : out Outvoice_Array; Last : out Natural; Filename : in String) is
      File : W_Io.File_Type;
   begin

      if Is_Regular_File(Filename) then
	 W_Io.Open(File, W_Io.In_File, Filename, Form => "WCEM=8");
      end if;

      Last := 0;
      while not W_Io.End_Of_File(File) loop

	 Restore(Abstracted_Voice(Outvoices(Last + 1)), File);
	 Last := Last + 1;
	 
      end loop;
      W_Io.Close(File);
   end Outvoices_Restore;
   

end Sky.Accountant ;