package basics.dictionaries;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import basics.filesystem.file.LineReader;
import basics.filesystem.file.LineWriter;
import basics.testing.Test;
import basics.unexpected.Problem;
import basics.utl.SUtl;
import basics.utl.SysUtl;

/**
 * Simple map. Can read an dictionary file that contains <word><space><stem-form> entries.
 * Designed to translates words into stem-forms of words.
 * @author ks
 */
public class Transducer
{
public static String SEPARATOR = " ";
Map<String, String>  table     = new HashMap<String, String>();

public Iterator<String> sortedKeysIterator()
{
   List<String> keys = new ArrayList<String>();
   for(Iterator<String> i = table.keySet().iterator(); i.hasNext();)
      keys.add(i.next());
   Collections.sort(keys);
   return keys.iterator();
}

public Iterator<String> filteredIterator(String _v)
{
   String v = new String(_v.toLowerCase().trim());
   List<String> keys = new ArrayList<String>();
   for(Iterator<String> i = table.keySet().iterator(); i.hasNext();)
   {
      String k = i.next();
      if(k.toLowerCase().contains(v)) keys.add(k);
      else
      {
         String e = table.get(k);
         if(e.toLowerCase().contains(v)) keys.add(k);
      }
   }
   Collections.sort(keys);
   return keys.iterator();
}

/**
 * Returns null if the input is unknown in the dict.
 */
public String transduceOrNull(String lexem)
{
   return table.get(lexem);
}

/**
 * Returns the input if the input is unknown in the dict.
 */
public String transduceOrReturn(String lexem)
{
   String t = table.get(lexem);
   return t == null ? lexem : t;
}

/**
 * @param lexFile - name must have format transducer_<lang>.txt
 */
public Transducer(File lexFile)
{
   try
   {
      LineReader lr = new LineReader(lexFile);
      if(!lr.open())
      {
         SysUtl.trace("No such transducer found: " + lexFile);
         return;
      }
      while(lr.hasLine())
      {
         String [] v = SUtl.split(lr.nextLine(), SEPARATOR);
         table.put(v[0], SUtl.join(1, v, " "));
      }
      lr.close();
   }
   catch(Exception e)
   {
   }
   SysUtl.trace(table.size() + " entries from " + lexFile);
}

public void put(String t1, String t2)
{
   table.put(t1, t2);
}

public void remove(String t1)
{
   table.remove(t1);
}

public int size()
{
   return table.size();
}

public void saveToFile(File file)
{
   try
   {
      LineWriter w = new LineWriter(file);
      if(!w.open(false)) throw new Problem("Can't open stop file for writing: " + file);
      Iterator<String> iter = table.keySet().iterator();
      StringBuilder sb = new StringBuilder();
      while(iter.hasNext())
      {
         String k = iter.next();
         sb.append(k);
         sb.append(SEPARATOR);
         sb.append(table.get(k));
         w.write(sb.toString());
         sb.delete(0, sb.length());
         sb.trimToSize();
      }
      w.close();
   }
   catch(Exception e)
   {
   }
}

public static void unittest()
{
   Transducer t = new Transducer(null);
   t.put("a", "A");
   t.put("c", "C");
   t.put("b", "B");
   Test.assertTrue(t.size() == 3, "size not 3");
   Test.assertEqualsTrue(t.transduceOrReturn("a"), "A", "a --/--> A");
   Test.assertEqualsTrue(t.transduceOrReturn("b"), "B", "b --/--> B");
   Test.assertEqualsTrue(t.transduceOrReturn("c"), "C", "c --/--> C");
   Test.assertEqualsFalse(t.transduceOrReturn("d"), "D", "d ----> D??");
   Test.assertNull(t.transduceOrNull("d"), "d --/--> Null");
   t.remove("a");
   t.remove("b");
   Test.assertTrue(t.size() == 1, "size not 1");
}
}
