package basic;
import java.util.Iterator;
import uk.ac.ic.doc.automed.util.persist.PersistentDB;
import uk.ac.ic.doc.automed.util.persist.PersistentDBController;
import uk.ac.ic.doc.automed.util.persist.PersistentDBException;
import uk.ac.ic.doc.automed.util.persist.PersistentKey;
import uk.ac.ic.doc.automed.qproc.cache.CacheObjectBinding;
import uk.ac.ic.doc.automed.util.DateUtil;
import uk.ac.ic.doc.automed.util.Debugger;
import uk.ac.ic.doc.automed.util.LogOutputHandler;
import uk.ac.ic.doc.automed.util.Logger;
import uk.ac.ic.doc.automed.util.cache.CacheItem;
import uk.ac.ic.doc.automed.util.persist.DuplicatePersistentHandler;
import uk.ac.ic.doc.automed.util.persist.PersistentHandler;
import utils.AutoMedUtils;


/**
 * PersistentDBExample.java<br><br>
 *
 * @author Duc M Le  <a href="mailto:dmle@doc.ic.ac.uk"><i>dmle@doc.ic.ac.uk</i></a>
 * <br>Created on August 3, 2006
 * <br>Department of Computing, Imperial College
 */

public class PersistentDBExample {
  private PersistentHandler _pdb;
  
  /**
   * Creates a new instance of PersistentDBExample
   */
  public PersistentDBExample(PersistentHandler pdb) {
    _pdb = pdb;
  }
  
  public void viewSingleEntry(PersistentKey pkey) {
    CacheItem ci = (CacheItem) _pdb.get(pkey);
    if (ci != null)
      System.out.println(ci.toString());
    else 
      System.out.println("Not found!");
  }
  
  public void viewDuplicateEntries(PersistentKey pkey) throws Exception {
    if (_pdb instanceof DuplicatePersistentHandler) {
      DuplicatePersistentHandler dph = (DuplicatePersistentHandler) _pdb;
      Object[] objs = dph.getDuplicates(pkey);
      if (objs != null) {
      for (int i = 0; i < objs.length; i++) {
        CacheItem cix = (CacheItem) objs[i];
        System.out.println(cix.toString());
      }
      } else {
        System.out.println("Not found!");
      }
    } else
      throw new Exception("Persistent handler must be of type DuplicatePersistentHandler");
  }
  
  public void addTestEntries(CacheObjectBinding cob,
    int numItems, PersistentKey[] createdKeys) {
    for (int i = 0; i < numItems; i++) {
      CacheItem ci = new CacheItem(i+"", DateUtil.getClockRepresentation(DateUtil.getDateAsMillisecs()));
      ci.addContentItem("id", i+"");
      ci.addContentItem("query", "<<test,x"+i+">>");
      ci.addContentItem("fquery", "f:<<test,x"+i+">>");
      ci.addContentItem("squery", "s:<<test,x"+i+">>");
      ci.addContentItem("iquery", "i:<<test,x"+i+">>");
      ci.addContentItem("result", "[{"+i+","+(i+5)+"},{"+(i+System.currentTimeMillis())+","+(i+10)+"}]");
      PersistentKey pkey = cob.getKey(ci);
      createdKeys[i] = pkey;
      System.out.println("Putting entry "+pkey);
      _pdb.put(pkey, ci);
    }
  }
  
  public void viewDB() {
    Iterator eit = _pdb.iterator();
    int i = 1;
    while (eit.hasNext()) {
      System.out.println("Entry "+(i++));
      System.out.println("----------");
      CacheItem ciy = (CacheItem) eit.next();
      System.out.println(ciy.toString());
    }
  }
  
  public static void main(String[] args) throws Exception {
    
    Debugger.setSectionDebugLevel(Debugger.DEBUG_GENERAL, Debugger.DEBUG_LEVEL_ERROR);
    Logger.setOutputHandler(
      new LogOutputHandler(LogOutputHandler.CONSOLE +
      LogOutputHandler.FILE));
    
    boolean readOnly = false;
    PersistentDBController pdbc = null;
    try {
      pdbc = PersistentDBController.getInstance(PersistentDBController.DB_ENV_FILE_PATH, readOnly);
    } catch (PersistentDBException ex) {
      Logger.error(ex);
      throw ex;
    }
    
    // display list of dbnames to choose from
    System.out.println("Select the cacheDB from the list below:");
    String[] dbNames = pdbc.getDatabaseNames();    
    int dbInd = AutoMedUtils.displayItemList(dbNames);
    
    String dbname = dbNames[dbInd];
    
    CacheObjectBinding cob = new CacheObjectBinding();
    boolean duplicateAllowed = true;
    boolean removed = false;
    if (AutoMedUtils.dialogYesNo("Remove DB?", 0) == 1) {    
      pdbc.removeDB(dbname);
      removed = true;
    }
    
    if (removed) {
      System.out.println("Creating a new db for " + dbname);
    } else {
      System.out.println("Opening existing db " + dbname);
    }
    
    PersistentDB pdb = pdbc.createDB(dbname, duplicateAllowed, cob);
    
    PersistentDBExample pex = new PersistentDBExample(pdb);
    do {
      // test writing a number of cache items
      int numItems = 5;
      PersistentKey[] keys = new PersistentKey[numItems];
      
      
      if (AutoMedUtils.dialogYesNo("Test writing items to db?", 0) == 1) {
        System.out.println("-----------------------------------------------------------");
        System.out.println("Writing "+numItems+" test entries to " + dbname);
        System.out.println("-----------------------------------------------------------");
        pex.addTestEntries(cob, numItems, keys);
      }
      
      if (AutoMedUtils.dialogYesNo("Test reading a SINGLE item from db?", 1) == 1) {
        // read entries from the database
        PersistentKey sk = keys[1];
        if (sk == null) sk = new PersistentKey("<<test,x0>>");
        System.out.println("-----------------------------------------------------------");
        System.out.println("Reading a SINGLE entry " + sk + " from " + dbname);
        System.out.println("-----------------------------------------------------------");
        pex.viewSingleEntry(sk);
      }
      
      // read entries from the database
      if (AutoMedUtils.dialogYesNo("Test reading DUPLICATE items from db?", 1) == 1) {
        PersistentKey skx = keys[3];
        if (skx == null) skx = new PersistentKey("<<test,x0>>");
        
        System.out.println("------------------------------------------------------------------------");
        System.out.println("Reading the SET of entries for key " + skx + " from " + dbname);
        System.out.println("------------------------------------------------------------------------");
        pex.viewDuplicateEntries(skx);
      }
      
      // read entries from the database
      if (AutoMedUtils.dialogYesNo("Test reading ALL items from db?", 0) == 1) {
        System.out.println("-----------------------------------------------------------");
        System.out.println("Reading ALL test entries from " + dbname);
        System.out.println("-----------------------------------------------------------");
        pex.viewDB();
      }
    } while (AutoMedUtils.dialogYesNo("Run again?", 0) == 1);
    
    AutoMedUtils.banner("~END~");
    
    System.exit(0);
  }
}