with Integer_Unbounded_Double_Lists;  use Integer_Unbounded_Double_Lists;
with Ada.Numerics.Discrete_Random;
with Ada.Text_IO;  use Ada.Text_IO;
--with Ada.Integer_Text_IO;  use Ada.Integer_Text_IO;

procedure Test_Sort_Unbounded_Double_List is

--     procedure Print (C : Container_Type) is
--        procedure Process (I : Iterator_Type) is
--        begin
--           Put (Element (I), Width => 0);
--           Put (' ');
--        end;

--        procedure Iterate is
--           new Generic_Reverse_Iteration;
--     begin
--        Iterate (C);
--        New_Line;
--     end;


   function Is_Sorted (C : Container_Type) return Boolean is

      I : Iterator_Type := First (C);
      J : constant Iterator_Type := Back (C);

      E : Integer := -1;

   begin

      while I /= J loop

         if Element (I) < E then
            return False;
         end if;

         E := Element (I);

         Increment (I);

      end loop;

      return True;

   end Is_Sorted;

   package Random_Integers is
      new Ada.Numerics.Discrete_Random (Integer);

   use Random_Integers;

   G : Generator;
   C, C2 : Container_Type;
   I, J : Iterator_Type;
   E : Integer;

   procedure Sort is
      new Generic_Sort;

begin

   Reset (G);

   Put_Line ("inserting and sorting");

   C2 := C;
   pragma Assert (C2 = C);

   Assign (Target => C2, Source => C);
   pragma Assert (C2 = C);

   Sort (C2);
   pragma Assert (Is_Sorted (C2));

--     Print (C);
--     Print (C2);
--     New_Line;

   E := Random (G) mod 1000;
   Append (C, New_Item => E);
   pragma Assert (Is_In (E, C));
   pragma Assert (Find (C, E) = First (C));
   pragma Assert (Reverse_Find (C, E) = First (C));

   loop

      C2 := C;
      pragma Assert (C2 = C);

      Assign (Target => C2, Source => C);
      pragma Assert (C2 = C);

      Sort (C2);
      pragma Assert (Is_Sorted (C2));

--        Print (C);
--        Print (C2);
--        New_Line;

      exit when Length (C) >= 1000;

      I := First (C);

      for Index in 1 .. Random (G) mod Length (C) loop
         Increment (I);
      end loop;

      E := Random (G) mod 1000;

      Insert
        (Container => C,
         Before    => I,
         New_Item  => E,
         Iterator  => J);

      pragma Assert (Element (J) = E);

      I := Find (C, E);

      while I /= J loop
         I := Find (C, E, Position => Succ (I));
      end loop;

      I := Reverse_Find (C, E);

      while I /= J loop
         I := Reverse_Find (C, E, Position => Pred (I));
      end loop;

   end loop;

   Put_Line ("deleting");

   while not Is_Empty (C) loop

--        Put (Length (C), Width => 0);
--        New_Line;

      I := First (C);

      for Index in 1 .. Random (G) mod Length (C) loop
         Increment (I);
      end loop;

      E := Element (I);

      Delete (C, Item => E);

      pragma Assert (not Is_In (E, C));
      pragma Assert (Find (C, E) = Back (C));
      pragma Assert (Reverse_Find (C, E) = Back (C));

   end loop;

end Test_Sort_Unbounded_Double_List;
