with Ada.Command_Line; use Ada.Command_Line;
with Ada.Text_IO;      use Ada.Text_IO;
with GNAT.OS_Lib;      use GNAT.OS_Lib;

with Projects.Registry;    use Projects, Projects.Registry;
with Src_Info;             use Src_Info;
with Src_Info.Queries;     use Src_Info.Queries;

with Language_Handlers;    use Language_Handlers;
with Test_Utils;           use Test_Utils;

procedure Find_Dep is

   procedure Print (Dep : Dependency);

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

   procedure Print (Dep : Dependency) is
      B : constant Boolean :=
        Get_Depends_From_Body (Dependency_Information (Dep));
      S : constant Boolean :=
        Get_Depends_From_Spec (Dependency_Information (Dep));
   begin
      Put_Line
        ("Dep= "
         & Get_Source_Filename (File_Information (Dep))
         & " from_spec=" & S'Img & " from_body=" & B'Img);
   end Print;

   Prj_Filename     : String_Access;
   Source_Filename  : String_Access;
   Project          : Project_Type;
   Registry         : aliased Project_Registry;
   Source_Info_List : Src_Info.LI_File_List;
   LI_Unit          : LI_File_Ptr;
   Iter             : Dependency_Iterator;
   From_Dep         : Boolean;
   Dependencies, Dep : Dependency_List;
   Status           : Dependencies_Query_Status;
   Dep2             : Dependency;
   Handler          : Language_Handler;

begin
   Handler := Create_Lang_Handler (Registry'Unrestricted_Access);

   if Argument_Count /= 3 then
      Put_Line ("invalid number of arguments");
      Put_Line ("find_dep [""to""|""from""] project_name source_name");
      return;
   end if;

   From_Dep := Argument (1) = "from";

   Prj_Filename := new String'(Argument (2));
   if not Is_Regular_File (Prj_Filename.all) then
      Put_Line ("No such file: '" & Prj_Filename.all & "'");
      return;
   end if;

   Source_Filename := new String'(Argument (3));
   if not Is_Regular_File (Source_Filename.all) then
      Put_Line ("No such file: '" & Source_Filename.all & "'");
      return;
   end if;

   Reset (Source_Info_List);
   Load_Project (Prj_Filename.all, Handler, Registry, Project);
   Load_LI_File
     (Source_Info_List, Handler, Registry, Source_Filename.all, LI_Unit);

   if LI_Unit /= No_LI_File then
      if From_Dep then
         Find_Dependencies
           (LI_Unit, Source_Filename.all, Dependencies, Status);

         Dep := Dependencies;
         while Dep /= null loop
            Print (Dep.Value);
            Dep := Dep.Next;
         end loop;

         Destroy (Dependencies);

      else
         Find_Ancestor_Dependencies
           (Root_Project    => Project,
            Lang_Handler    => Handler,
            Source_Filename => Source_Filename.all,
            List            => Source_Info_List,
            Include_Self    => False,
            Iterator        => Iter);

         while Get (Iter) /= No_LI_File loop
            Dep2 := Get (Iter);
            Print (Dep2);
            Destroy (Dep2);
            Next (Handler, Iter, Source_Info_List);
         end loop;

         Destroy (Iter);
      end if;
   else
      Put_Line ("LI file not found");
   end if;
end Find_Dep;
