with Ada.Numerics.Discrete_Random;
with Integer_Vectors; use Integer_Vectors;
with Ada.Containers;  use Ada.Containers;
with Ada.Text_IO;  use Ada.Text_IO;
with Ada.Integer_Text_IO;  use Ada.Integer_Text_IO;
with Ada.Command_Line;  use Ada.Command_Line;

procedure Test_Integer_Vectors is

   package Random_Numbers is
      new Ada.Numerics.Discrete_Random (Natural);
   use Random_Numbers;

   G : Generator;

   V : Vector;

   function Random_Insertion_Index return Natural is
      L : constant Count_Type := Length (V);
      R : constant Natural := Random (G);
      I : constant Natural := R rem (Count_Type'Pos (L) + 1);
   begin
      return I;
   end;

   function Random_Deletion_Index return Natural is
      L : constant Count_Type := Length (V);
      R : constant Natural := Random (G);
      I : constant Natural := R rem (Count_Type'Pos (L));
   begin
      return I;
   end;

   function Random_Element return Positive is
      R : constant Natural := Random (G);
      E : constant Natural := R rem 9000;
   begin
      return 1000 + E;
   end;

   function Random_Unique_Element return Positive is
   begin
      loop
         declare
            E : constant Positive := Random_Element;
         begin
            if not Contains (V, E) then
               return E;
            end if;
         end;
      end loop;
   end Random_Unique_Element;

   package Count_IO is
      new Ada.Text_IO.Integer_IO (Count_Type);
   use Count_IO;

begin

   if Argument_Count = 0 then
      Reset (G);
   else
      declare
         Image : constant String := Argument (1);
         Value : constant Integer := Integer'Value (Image);
      begin
         Reset (G, Value);
      end;
   end if;

   while Length (V) < 99 loop

      declare
         L : constant Count_Type := Length (V);
         I : constant Natural := Random_Insertion_Index;
         E : constant Positive := Random_Unique_Element;
         C : Cursor;
      begin
         Put ("len="); Put (L, Width => 2);
         Put (" idx="); Put (I, Width => 2);
         Put (" elm="); Put (E, Width => 4);
         New_Line;

         Insert (V, Before => I, New_Item => E);
         pragma Assert (Element (V, I) = E);
         pragma Assert (Find_Index (V, E) = I);
         C := Find (V, E);
         pragma Assert (C /= No_Element);
         pragma Assert (Has_Element (C));
         pragma Assert (Element (C) = E);
      end;

   end loop;

   New_Line;

   while not Is_Empty (V) loop

      declare
         L : constant Count_Type := Length (V);
         I : constant Natural := Random_Deletion_Index;
         E : constant Positive := Element (V, I);
      begin
         Put ("len="); Put (L, Width => 2);
         Put (" idx="); Put (I, Width => 2);
         Put (" elm="); Put (E, Width => 4);
         New_Line;

         Delete (V, Index => I);
         pragma Assert (not Contains (V, E));
         pragma Assert (Find (V, E) = No_Element);
      end;

   end loop;

end Test_Integer_Vectors;
