with Ada.Strings;              use Ada.Strings;
with Ada.Strings.Fixed;        use Ada.Strings.Fixed;
with Ada.Text_IO;              use Ada.Text_IO;
with GNAT.OS_Lib;              use GNAT.OS_Lib;
with Language;                 use Language;
with Language.Ada;             use Language.Ada;
with Language.C;               use Language.C;
with Language.Cpp;             use Language.Cpp;

package body Test is

   ----------------
   -- Initialize --
   ----------------

   procedure Initialize is
   begin
      Add_File_Extensions (Ada_Lang, ".ads;.adb;.ada");
      Add_File_Extensions (C_Lang, ".h;.c");
      Add_File_Extensions (Cpp_Lang, ".hh;.cc;.cpp");
   end Initialize;

   ----------
   -- Read --
   ----------

   function Read (Source : String) return String
   is
      FD : File_Descriptor;
      Length : Integer;
   begin
      FD := Open_Read (Name => Source, Fmode => Text);
      if FD = Invalid_FD then
         Put_Line ("Error: Can not open file: " & Source);
         OS_Exit (1);
      end if;

      Length := Integer (File_Length (FD));

      declare
         Buffer : String (1 .. Length + 1);
         Chars_Read : Integer;
      begin
         Chars_Read := Read (FD, Buffer'Address, Buffer'Length);
         if Chars_Read /= Length then
            Put
              ("Error: Incorrect number of chars read =" &
               Chars_Read'Img & " (expected " & Length'Img & ")");
         end if;
         close (FD);

         return Buffer (1 .. Length);
      end;
   end Read;

   -----------
   -- Print --
   -----------

   procedure Print (Text : String) is
      First_Non_Space_Index : constant Integer := Index_Non_Blank (Text);
      Last_Non_Space_Index  : constant Integer :=
        Index_Non_Blank (Text, Backward);
   begin

      --  Treat the case where Text is only made of spaces first.
      --  Prevents constraint error later.

      if First_Non_Space_Index = 0 then
         for Index in Text'Range loop
            Put ("<space>");
         end loop;
         return;
      end if;

      --  General case: The Text contains other characters than space

      for Index in Text'First .. First_Non_Space_Index - 1 loop
         Put ("<space>");
      end loop;

      for Index in First_Non_Space_Index .. Last_Non_Space_Index loop
         case Text (Index) is
            when ASCII.HT =>
               Put ("<tab>");
            when ASCII.LF =>
               Put ("<lf>");
            when ASCII.CR =>
               Put ("<cr>");
            when others =>
               Put (Text (Index));
         end case;
      end loop;

      for Index in Last_Non_Space_Index + 1 .. Text'Last loop
         Put ("<space>");
      end loop;
   end Print;

   --------------
   -- Run_Test --
   --------------

   procedure Run_Test (Source : String)
   is
      Buffer : constant String := Read (Source);
      Index : Integer := Buffer'First;
      Next_Char : Integer;
      Lang : Language_Access;
      Entity : Language_Entity;
   begin
      Initialize;

      Lang := Get_Language_From_File (Source);
      if Lang = null then
         Put_Line ("Error: Unknown file type for " & Source );
         OS_Exit (1);
      end if;

      Split_Loop:
      loop
         Looking_At (Lang, Buffer (Index .. Buffer'Last), Entity, Next_Char);
         Put (Entity'Img & ": ");
         Print (Buffer (Index .. Next_Char - 1));
         New_Line;

         exit Split_Loop when Next_Char > Buffer'Last;
         Index := Next_Char;
      end loop Split_Loop;

   end Run_Test;

end Test;
