package commons.collections;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import commons.collections.interfaces.Sized;

public class ListOfIndexedSentences implements Sized
{

List<List<Integer>> lists = new ArrayList<List<Integer>>();

public ListOfIndexedSentences()
{
   lists.add(new ArrayList<Integer>());
}

public List<List<Integer>> getLists()
{
   return lists;
}

public int size()
{
   return lists.size();
}

public long signs()
{
   long s = 0;
   for(List<Integer> l : lists)
      s += l.size();
   return s;
}

public void setLists(List<List<Integer>> lists)
{
   this.lists = lists;
}

private List<Integer> lastList()
{
   int s = size();
   if(s == 0)
      nextList();
   return lists.get(s - 1);
}

public void addTerm(int term)
{
   lastList().add(term);
}

public void nextList()
{
   lists.add(new ArrayList<Integer>());
}

public void nextList(List<Integer> list)
{
   lists.add(list);
}

public int terms()
{
   int x = 0;
   for(List<Integer> l : lists)
      x += l.size();
   return x;
}

public Iterator<List<Integer>> iterator()
{
   return lists.iterator();
}

/**
 * slow (must iterate and copy), returns a set of all terms, not sorted.
 */
public List<Integer> getUniqueWordIndex()
{
   Set<Integer> done = new HashSet<Integer>();
   List<Integer> u = new ArrayList<Integer>();
   for(List<Integer> l : lists)
   {
      for(int t : l)
      {
         if(!done.contains(t))
         {
            u.add(t);
            done.add(t);
         }
      }
   }
   return u;
}

/**
 */
public synchronized Iterator<Integer> uniqueWordIterator()
{
   return new Iterator<Integer>()
   {

      Set<Integer>  done         = new HashSet<Integer>();
      List<Integer> currentList  = null;
      int           currentTerm  = -1;
      int           listNdx      = 0;
      int           termNdx      = 0;
      final int     listCount    = size();
      int           currListSize = 0;

      public boolean hasNext()
      {
         do
         {
            if(currentList == null)
            {
               termNdx = 0;
               currentList = lists.get(listNdx++);
               currListSize = currentList.size();
            }
            while(termNdx < currListSize)
            {
               currentTerm = currentList.get(termNdx++);
               if(!done.contains(currentTerm))
                  return true;
            }
            currentList = null;
         } while(listNdx < listCount);
         return false;
      }

      public Integer next()
      {
         done.add(currentTerm);
         return currentTerm;
      }

      public void remove()
      {
      }
   };
}

public List<Integer> getList(int ndx)
{
   try
   {
      return lists.get(ndx);
   }
   catch(Exception e)
   {
      return null;
   }
}

/**
 * remove term from all lists in list, and remove empty lists.
 */
public synchronized void remove(int term)
{
   for(int a = lists.size() - 1; a >= 0; a--)
   {
      List<Integer> l = lists.get(a);
      for(int i = l.size() - 1; i >= 0; i--)
         if(l.get(i).equals(term))
            l.remove(i);
      if(l.size() == 0)
         lists.remove(a);
   }
}

/**
 * remove term from all lists in list, and remove empty lists.
 */
public synchronized void removeEmptyLists()
{
   for(int a = lists.size() - 1; a >= 0; a--)
   {
      List<Integer> l = lists.get(a);
      if(l.size() == 0)
         lists.remove(a);
   }
}

/**
 * remove term from all lists in list, and remove empty lists.
 */
public synchronized void replace(int term, int termNew)
{
   for(int a = lists.size() - 1; a >= 0; a--)
   {
      List<Integer> l = lists.get(a);
      for(int i = l.size() - 1; i >= 0; i--)
         if(l.get(i).equals(term))
            l.set(i, termNew);
   }
}

public String toString()
{
   StringBuilder s = new StringBuilder();
   s.append(getClass().getSimpleName());
   s.append("{");
   s.append(size());
   s.append("}");
   return s.toString();
}

public String report()
{
   StringBuilder s = new StringBuilder();
   for(List<Integer> l : lists)
   {
      boolean ft = true;
      for(int t : l)
      {
         if(ft)
            ft = !ft;
         else
            s.append(", ");
         s.append(t);
      }
      s.append(".\n");
   }
   return s.toString();
}
}
