with Ada.Strings.Hash;
with Ada.Containers.Generic_Array_Sort;

package body Wordfreq_Types is

   function Hash (Data : Data_Type) return Hash_Type is
   begin
      return Ada.Strings.Hash (Data.Word);
   end;

   function Equivalent (L, R : Data_Type) return Boolean is
   begin
      return L.Word = R.Word;
   end;

   function Word (Data : Data_Type) return String is
   begin
      return Data.Word;
   end;

   function Equivalent (Word : String; Data : Data_Type) return Boolean is
   begin
      return Word = Data.Word;
   end;

   package Word_Keys is new Data_Sets.Generic_Keys
     (String,
      Word,
      Ada.Strings.Hash,
      Equivalent);

   function To_Data (Word : String) return Data_Type is
   begin
      return Data_Type'(Word'Length, Word, 0);
   end;

   procedure Insert (Data_Set : in out Data_Sets.Set; Word : in String) is
      procedure Inc_Count (Data : in out Data_Type) is
      begin
         Data.Count := Data.Count + 1;
      end;

      C : Data_Sets.Cursor;
      B : Boolean;
   begin
      Data_Set.Insert (To_Data (Word), C, B);
      Word_Keys.Update_Element_Preserving_Key (Data_Set, C, Inc_Count'Access);
   end Insert;

   function "<" (L, R : Data_Sets.Cursor) return Boolean is
      --  NOTE:
      --  We could also do this using nested calls to
      --  Query_Element. For now just copy the data.
      --  END NOTE.

      LE : constant Data_Type := Data_Sets.Element (L);
      RE : constant Data_Type := Data_Sets.Element (R);
   begin
      if LE.Count < RE.Count then
         return False;
      elsif LE.Count > RE.Count then
         return True;
      else
         return LE.Word > RE.Word;
      end if;
   end "<";

   procedure Cursor_Array_Sort is new Ada.Containers.Generic_Array_Sort
     (Count_Type,
      Data_Sets.Cursor,
      Cursor_Array);

   procedure Sort (Cursors : in out Cursor_Array) renames Cursor_Array_Sort;

end Wordfreq_Types;
