with Integer_Bounded_Single_Lists;  use Integer_Bounded_Single_Lists;
with Ada.Numerics.Discrete_Random;
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_Single_Bounded_Sort is

   procedure Print (C : Container_Type) is

      procedure Process (I : Iterator_Type) is
         E : constant Integer := Element (C, I);
      begin
         Put (E, Width => 0);
         Put (' ');
      end;

      procedure Iterate is
        new Integer_Bounded_Single_Lists.Generic_Iteration;

   begin

      Put (Length (C), Width => 0);
      Put (": ");

      if Is_Empty (C) then
         Put ("<empty>");
      else
         Iterate (C);
      end if;

      New_Line;

   end Print;


   function Is_Sorted (C : Container_Type) return Boolean is

      I, J : Iterator_Type;
   begin
      if Length (C) <= 1 then
         return True;
      end if;

      I := First (C);

      loop

         J := Succ (C, I);

         if J = Back (C) then
            return True;
         end if;

         if Element (C, J) < Element (C, I) then
            return False;
         end if;

         I := J;

      end loop;
   end Is_Sorted;


   function Count (C : Container_Type) return Natural is
      I : Iterator_Type := First (C);
      N : Integer'Base := 0;
   begin
      while I /= Back (C) loop
         N := N + 1;
         Increment (C, I);
      end loop;

      return N;
   end;


   procedure Sort is
      new Integer_Bounded_Single_Lists.Generic_Sort;

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

   use Random_Integers;

   G : Generator;

   C1 : Container_Type (25);

   N : Natural;

   I, J : Iterator_Type;

   Seed : Integer := 0;

begin

   if Argument_Count >= 1 then
      Seed := Integer'Value (Argument (1));
   end if;

   Reset (G, Seed);

   for Index in 1 .. 100 loop

      Put (Index, Width => 0);
      New_Line;

      N := Random (G) mod (C1.Size + 1);

      for I in 1 .. N loop
         Append (C1, New_Item => Random (G) mod 26);
      end loop;

      N := Random (G) mod 21;

      Print (C1);
      --New_Line;

      I := First (C1);

      if I /= Back (C1) then
         N := Random (G) mod Length (C1);

         for X in 1 .. N loop
            Increment (C1, I);
         end loop;
      end if;

      J := First (C1);

      if J /= Back (C1) then
         N := Random (G) mod Length (C1);

         for X in 1 .. N loop
            Increment (C1, J);
         end loop;
      end if;

      Put ("splice #1: I=");

      if I = Back (C1) then
         Put ("<back>");
      else
         Put (Element (C1, I), Width => 0);
      end if;

      Put (" J=");

      if J = Back (C1) then
         Put ("<back>");
      else
         Put (Element (C1, J), Width => 0);
      end if;

      New_Line;

      Splice_After (C1, Position => I, Pred => J);

      Print (C1);
      --New_Line;

      pragma Assert (Count (C1) = Length (C1));

      Put_Line ("sorting");

      Sort (C1);
      pragma Assert (Is_Sorted (C1));

      Print (C1);
      New_Line;

      Clear (C1);

   end loop;


end Test_Single_Bounded_Sort;



