-- 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-17 09:31:40 ; 
-- Version := 0.2.0r ; 
with Gnat.Os_Lib;
use Gnat.Os_Lib;
with Ada.Direct_Io;
package body Sky.Stocks_manager is
   procedure Stock_Add (To : in out Stocks_Manager;
			Stock : in Stock_Record) is
      -- Spec_Error is raised if no space left.
   begin
      if To.Stock_Last = Stock_Num_Max then
	 raise Spec_Error;
      end if;
      To.Stocks(To.Stock_Last + 1) := Stock;
      To.Stock_Last := To.Stock_Last + 1;
   end Stock_Add;
   
   procedure Update_Stock(To: in out Stocks_Manager;
			  Stock : in Stock_Record) is
      -- If the stock more Qt is over Quantity_Range'last, Spec_error is raised.
      Done : Boolean := False;
   begin
      
      if To.Stock_Last = 0 then
	 raise Not_An_Stock;
      end if;

      for Iter in 1..To.Stock_Last loop
	 if To.Stocks(Iter).Name = Stock.Name then
	    
	    if To.Stocks(Iter).Quantity + Stock.Quantity <= Quantity_Range'Last then
	       To.Stocks(Iter).Quantity := 
		 To.Stocks(Iter).Quantity + Stock.Quantity;
	       
	       To.Stocks(Iter).Unit_Ht := Stock.Unit_Ht;
	       To.Stocks(Iter).TVA_Rate :=Stock.TVA_Rate;
	       
	       Done := True;
	       exit;
	    else
	       
	       raise Spec_Error;
	    end if;
	 end if;
      end loop;
      if not Done then
	 raise Not_An_Stock;

      end if;

   end Update_Stock;
   procedure Stock_Remove (From : in out Stocks_Manager;
			   Stock_Num : in Stock_Num_Range) is
      -- Not_An_Stock is raised when not Stock_Num is not an stock.
      Done : Boolean := False;      
   begin
      if From.Stock_Last = 0 then
	 raise Not_An_Stock;
      end if;
      for Iter in 1..From.Stock_Last loop
	 if From.Stocks(Iter).Num = Stock_Num then
	    for Last in Iter..From.Stock_Last-1 loop
	       From.Stocks(Last) := From.Stocks(Last+1);
	    end loop;
	    From.Stocks(From.Stock_Last) := Null_Stock;
	    From.Stock_Last := From.Stock_Last - 1;
	    Done := True;
	    exit;
	 end if;
      end loop;
      if not Done then
	 raise Not_An_Stock;
      end if;
   end Stock_Remove;
   
   procedure Add_To_Stock(From : in out Stocks_Manager;
			  Stock_Num : in Stock_Num_Range;
			  Qt  : in Quantity_Range) is
      Done : Boolean := False;
   begin
      if From.Stock_Last = 0 then
	 raise Not_An_Stock;
      end if;
      for Iter in 1..From.Stock_Last loop
	 if From.Stocks(Iter).Num = Stock_Num then
	    if From.Stocks(Iter).Quantity + Qt <= Quantity_Range'Last then
	       From.Stocks(Iter).Quantity := 
		 From.Stocks(Iter).Quantity + Qt;
	       Done := True;
	       exit;
	    else
	       raise Spec_Error;
	    end if;
	 end if;
      end loop;
      if not Done then
	 raise Not_An_Stock;
      end if;
   end Add_To_Stock;
   
   
   procedure Add_To_Stock(From : in out Stocks_Manager;
			  Name : in Wstring_32;
			  Qt  : in Quantity_Range) is
      -- If the stock more Qt is over Quantity_Range'last, Spec_error is raised.
      Done : Boolean := False;
   begin
      if From.Stock_Last = 0 then
	 raise Not_An_Stock;
      end if;
      for Iter in 1..From.Stock_Last loop
	 if From.Stocks(Iter).Name = Name then
	    if From.Stocks(Iter).Quantity + Qt <= Quantity_Range'Last then
	       From.Stocks(Iter).Quantity := 
		 From.Stocks(Iter).Quantity + Qt;
	       Done := True;
	       exit;
	    else
	       raise Spec_Error;
	    end if;
	 end if;
      end loop;
      if not Done then
	 raise Not_An_Stock;
      end if;
   end Add_To_Stock;
   
   
   procedure Remove_From_Stock(From : in out Stocks_Manager;
			       Name : in Wstring_32;
			       Qt  : in Quantity_Range) is
      Done : Boolean := False;
   begin
      if From.Stock_Last = 0 then
	 raise Not_An_Stock;
      end if;
      for Iter in 1..From.Stock_Last loop
	 if From.Stocks(Iter).Name = Name then
	    
	    if From.Stocks(Iter).Quantity + Qt > Quantity_Range'First then
	       From.Stocks(Iter).Quantity := 
		 From.Stocks(Iter).Quantity - Qt;
	       Done := True;
	       exit;
	    else
	       raise Spec_Error;
	    end if;
	 end if;
      end loop;
      if not Done then
	 raise Not_An_Stock;
      end if;
   end Remove_From_Stock;
   
   function In_Stocks (Stocks : in Stocks_Manager; Description : in Wstring_32) return Boolean is
   begin
      if Stocks.Stock_Last = 0 then
	 return False;
      end if;
      for Iter in 1..Stocks.Stock_Last loop
	 if Stocks.Stocks(Iter).Name = Description then
	    return True;
	 end if;
      end loop;
      return False;
   end In_Stocks;
   
   
   package Stock_Io is new Ada.Direct_Io(Stock_Record);
   use Stock_Io;
   
   procedure Stocks_Save is
      File : File_Type;
   begin
      
      
      if Hardware.Stock_Last /= 0 then
	 Create(File, Out_File, Hard_Filename, Form => "WCEM=8");
	 for Stock in 1..Hardware.Stock_Last loop
	    Write(File, Hardware.stocks(Stock));
	 end loop;
	 Close(File);
      end if;
      
      
      
      if Software.Stock_Last /= 0 then
	 Create(File, Out_File, Soft_Filename, Form => "WCEM=8");
	 for Stock in 1..Software.Stock_Last loop
	    Write(File, Software.stocks(Stock));
	 end loop;
	 Close(File);
      end if;
      
   end Stocks_Save;
   
   procedure Stocks_Restore is
      File : File_Type;
      Index : Natural := 0;
   begin
      if Is_Regular_File(Hard_Filename) then
	 Open(File, In_File, Hard_Filename, Form => "WCEM=8");
	 while not End_Of_File(File) loop
	    Read(File, hardware.Stocks(Index + 1));
	    Index := Index + 1;
	 end loop;
	 Hardware.Stock_Last := Index;
	 Close(File);
      end if;
      
      Index := 0;
      if Is_Regular_File(Soft_Filename) then
	 Open(File, In_File, Soft_Filename, Form => "WCEM=8");
	 while not End_Of_File(File) loop
	    Read(File, Software.Stocks(Index + 1));
	 Index := Index + 1;
	 end loop;
	 Software.Stock_Last := Index;
	 Close(File);
      end if;
   end Stocks_Restore;

   
end Sky.Stocks_manager ;