package shef.nlp.buchart.prolog;

import java.io.*;
import java.util.*;

import shef.nlp.buchart.prolog.cafe.*;

import jp.ac.kobe_u.cs.prolog.lang.*;
import jp.ac.kobe_u.cs.prolog.builtin.*;


public class PrologCafe extends Prolog
{
   private Hashtable database = null;

   public boolean init(File f)
   {
      try
      {
         database = new Hashtable();

         ObjectInputStream in = new ObjectInputStream(new FileInputStream(f));

         int numKeys = in.readInt();

         while (database.keySet().size() < numKeys)
         {
            Term key = (Term)in.readObject();

            database.put(key,readTerm(in));
         }

         in.close();

      }
      catch (Exception e)
      {
         database = null;
      }

      return database != null;

   }

   public boolean parse(File in, File out)
   {

      PrologControl p = new PrologControl();

      Term t = SymbolTerm.makeSymbol("[]");
      t = new ListTerm(SymbolTerm.makeSymbol(in.getAbsolutePath()),t);

      Predicate code = new PRED_parse_3();

      Predicate test = new PRED_best_parse_cats_2();

      Term hash = new JavaObjectTerm(database);

      try
      {
         PrintWriter pout = new PrintWriter(new FileWriter(out));

         Term writeOut = new JavaObjectTerm(pout);


         boolean success = p.execute(code,new Term[]{writeOut,hash,t});


         pout.flush();
         pout.close();

         return success;
      }
      catch(Exception e)
      {
         e.printStackTrace();
         return false;
      }
   }

   public static void main(String args[]) throws Exception
   {
      PrologControl p = new PrologControl();

      Predicate consult = new PRED_consult_1();
      Term f = SymbolTerm.makeSymbol(args[0]);

      p.setPredicate(consult,new Term[]{f});

      System.out.println("Consulting completed: " + p.call());

      Hashtable database = p.engine.getDynamicHash();

      Set keys = database.keySet();

      Iterator it = keys.iterator();

      ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(args[1]));

      out.writeInt(keys.size());

      while (it.hasNext())
      {
         Term k = (Term)it.next();

         out.writeObject(k.dereference());

         Term v = (Term)database.get(k);

         writeTerm(out,v);
      }

      out.flush();
      out.close();

      System.exit(0);
   }

   private static void writeTerm(ObjectOutputStream out, Term t) throws Exception
   {
      if (t instanceof ListTerm)
      {
         ListTerm lt = (ListTerm)t;

         out.writeInt(lt.length());

         boolean working = true;

         while (working)
         {
            Term ct = lt.car().dereference();
            writeTerm(out,ct);

            if (lt.cdr().dereference() instanceof ListTerm)
               lt = (ListTerm)lt.cdr().dereference();
            else
               working = false;
         }
      }
      else
      {
         out.writeInt(-1);
         out.writeObject(t.dereference());
      }
   }

   private static Term readTerm(ObjectInputStream in) throws Exception
   {
      int length = in.readInt();

      if (length != -1)
      {
         List terms = new ArrayList();

         for (int i = 0 ; i < length ; ++i)
         {
            terms.add(readTerm(in));
         }

         Term t = SymbolTerm.makeSymbol("[]");

         for (int i = terms.size() -1; i>=0 ; --i)
         {
            t = new ListTerm((Term)terms.get(i),t);
         }

         return t;
      }
      else
      {
         Term t = (Term)in.readObject();

         return t;
      }
   }
}