with
  Ada.Calendar,
  Ada.Strings,
  Ada.Strings.Fixed,
  Ada.Strings.Unbounded.Text_Io,
  Ada.Unchecked_Deallocation,
  Gnat.Directory_Operations,
  Ada.Strings.Maps,
  Utils.Strings;

use
  Ada.Calendar,
  Ada.Strings,
  Ada.Strings.Fixed,
  Ada.Strings.Unbounded.Text_Io,
  Gnat.Directory_Operations,
  Ada.Strings.Maps,
  Utils.Strings;

package body Libraries is

   procedure Deallocate is new Ada.Unchecked_Deallocation(Library_Record,
                                                          Library);

   procedure Init_Library
     (Name    : in     String;
      Comment : in     String;
      Path    : in     String;
      Lib     :    out Library;
      Included: in     String_Array := Empty_String_Array) is

      File_Name: Unbounded_String;

   begin
      Lib       := new Library_Record;
      Lib.N     := To_Unbounded_String(Name);
      File_Name := Path & Dir_Separator & Lib.N;

      --===
      --  header file
      --    include the all_libs library
      --===
      Create(Lib.H, Out_File, To_String(File_Name & "." & Header_Extension));
      Put_Line(Lib.H, "/*  generated by helena  */");
      Put_Line(Lib.H, "");
      Put_Line(Lib.H, "#if !defined(LIB_" & To_Upper(Lib.N) & ")");
      Put_Line(Lib.H, "#define LIB_" & To_Upper(Lib.N));
      for I in Included'Range loop
         Put_Line(Lib.H, "#include """ &
                  To_String(Included(I)) & "." & Header_Extension & """");
      end loop;
      New_Line(Lib.H, 2);

      --===
      --  code file
      --===
      Create(Lib.C, Out_File, To_String(File_Name & "." & Code_Extension));
      Put_Line(Lib.C, "/*  generated by helena  */");
      Put_Line(Lib.C, "");
      Put_Line(Lib.C, "#include """ & Name & "." & Header_Extension & """");
   end;

   procedure End_Library
     (L: in out Library) is
   begin
      New_Line(L.H);
      Put_Line(L.H, "#endif /*  defined(LIB_" & To_Upper(L.N) & ")  */");
      Close(L.H);
      Close(L.C);
      Deallocate(L);
      L := null;
   end;

   function Get_Header_File
     (L: in Library) return access File_Type is
   begin
      return L.H'Access;
   end;

   function Get_Code_File
     (L: in Library) return access File_Type is
   begin
      return L.C'Access;
   end;

   procedure Nlh
     (L: in Library;
      N: in Natural := 1) is
   begin
      New_Line(L.H, Ada.Text_Io.Count(N));
   end;

   procedure Ph
     (L: in Library;
      S: in String;
      T: in Natural := 0) is
   begin
      Ada.Text_Io.Put(L.H, T*Tab & S);
   end;

   procedure Ph
     (L: in Library;
      S: in Unbounded_String;
      T: in Natural := 0) is
   begin
      Ph(L, T, To_String(S));
   end;

   procedure Ph
     (L: in Library;
      T: in Natural;
      S: in String) is
   begin
      Ph(L, S, T);
   end;

   procedure Ph
     (L: in Library;
      T: in Natural;
      S: in Unbounded_String) is
   begin
      Ph(L, S, T);
   end;

   procedure Plh
     (L: in Library;
      S: in String;
      T: in Natural := 0) is
   begin
      Ada.Text_Io.Put_Line(L.H, T*Tab & S);
   end;

   procedure Plh
     (L: in Library;
      S: in Unbounded_String;
      T: in Natural := 0) is
   begin
      Plh(L, T, To_String(S));
   end;

   procedure Plh
     (L: in Library;
      T: in Natural;
      S: in String) is
   begin
      Plh(L, S, T);
   end;

   procedure Plh
     (L: in Library;
      T: in Natural;
      S: in Unbounded_String) is
   begin
      Plh(L, S, T);
   end;

   procedure Nlc
     (L: in Library;
      N: in Natural := 1) is
   begin
      New_Line(L.C, Ada.Text_Io.Count(N));
   end;

   procedure Pc
     (L: in Library;
      S: in String;
      T: in Natural := 0) is
   begin
      Ada.Text_Io.Put(L.C, T*Tab & S);
   end;

   procedure Pc
     (L: in Library;
      S: in Unbounded_String;
      T: in Natural := 0) is
   begin
      Pc(L, To_String(S), T);
   end;

   procedure Pc
     (L: in Library;
      T: in Natural;
      S: in String) is
   begin
      Pc(L, S, T);
   end;

   procedure Pc
     (L: in Library;
      T: in Natural;
      S: in Unbounded_String) is
   begin
      Pc(L, S, T);
   end;

   procedure Plc
     (L: in Library;
      S: in String;
      T: in Natural := 0) is
   begin
      Ada.Text_Io.Put_Line(L.C, T*Tab & S);
   end;

   procedure Plc
     (L: in Library;
      S: in Unbounded_String;
      T: in Natural := 0) is
   begin
      Plc(L, To_String(S), T);
   end;

   procedure Plc
     (L: in Library;
      T: in Natural;
      S: in String) is
   begin
      Plc(L, S, T);
   end;

   procedure Plc
     (L: in Library;
      T: in Natural;
      S: in Unbounded_String) is
   begin
      Plc(L, To_String(S), T);
   end;

   procedure Section_Start_Comment
     (L      : in Library;
      Comment: in Unbounded_String) is
   begin
      L.S := Comment;
      Nlh(L, 2);
      Plh(L, "/****** begin " & Comment & " *****/");
      Nlc(L, 2);
      Plc(L, "/****** begin " & Comment & " *****/");
   end;

   procedure Section_Start_Comment
     (L      : in Library;
      Comment: in String) is
   begin
      Section_Start_Comment(L,To_Unbounded_String(Comment));
   end;

   procedure Section_End_Comment
     (L: in Library) is
   begin
      Plh(L, "/****** end   " & L.S & " *****/");
      Nlh(L, 2);
      Plc(L, "/****** end   " & L.S & " *****/");
      Nlc(L, 2);
      L.S := Null_Unbounded_String;
   end;

   procedure Pcl
     (L    : in Library;
      Lines: in String_Array) is
   begin
      for I in Lines'Range loop
	Plc (L, Lines (I));
      end loop;
   end;

end Libraries;
