--  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 GNAT.Directory_Operations;

with Nomo.Interpreter_Parameters;

package body Nomo.Reader is

   use Ada.Streams.Stream_IO;

   Data_Index : Data_Counts;
   Rule_Size  : Positive;

   function Get_Binary_Stream (Data : in Data_Type) return not null Ada.Streams.Stream_IO.Stream_Access is
   begin
      pragma Assert (Is_Open (Binary_File));
      Set_Index (Binary_File, Data_Index (Data));
      return Stream (Binary_File);
   end Get_Binary_Stream;

   function Get_Rule_Stream (I : in Positive) return not null Ada.Streams.Stream_IO.Stream_Access is
      Rule_Index : constant Positive_Count := Positive_Count (Positive (Data_Index (Rules)) + Rule_Size * (I - 1));
   begin
      pragma Assert (Is_Open (Binary_File));
      Set_Index (Binary_File, Rule_Index);
      return Stream (Binary_File);
   end Get_Rule_Stream;

begin
   declare
      Title           : String_Header;
      Dir_Name        : constant GNAT.Directory_Operations.Dir_Name_Str := GNAT.Directory_Operations.Get_Current_Dir;
      Dir             : GNAT.Directory_Operations.Dir_Type;
      Str             : String (1 .. Path_Size_Max);
      Last            : Natural;
      Engine_Data     : Interpreter_Parameters.Engine_Parameters;
      Number_Of_Rules : Positive;
      Is_Find         : Boolean := False;
   begin
      GNAT.Directory_Operations.Open (Dir, Dir_Name);
      loop
         GNAT.Directory_Operations.Read (Dir, Str, Last);
         if Last > Extension_Size and then Str (Last - Extension_Size + 1 .. Last) = Extension then
            if Is_Find then
               raise Too_Many_Files;
            else
               Is_Find := True;
            end if;
            Binary_Path := Str;
            Binary_Path_Size := Last;
            Open (Binary_File, In_File, Binary_Path (1 .. Binary_Path_Size));
            String_Header'Read (Stream (Binary_File), Title);
            if Title = Header then
               declare
               begin
                  Data_Counts'Read (Stream (Binary_File), Data_Index);
                  Interpreter_Parameters.Engine_Parameters'Read (Stream (Binary_File), Engine_Data);
                  Number_Of_Rules := Engine_Data.Number_Of_Rules;
                  Rule_Size := Positive (Data_Index (Data_Type'Succ (Rules)) - Data_Index (Rules)) / Number_Of_Rules;
               exception
                  when others =>
                     raise Corrupt_File;
               end;
            else
               raise Corrupt_File;
            end if;
         elsif Last = 0 then
            exit when Is_Find;
            raise Missing_File;
         end if;
      end loop;
   end;
end Nomo.Reader;
