/*
 * Copyright (c) 2010-2012 Eike Stepper (Berlin, Germany) and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Ibrahim Sallam - initial API and implementation
 */
package org.eclipse.emf.cdo.server.internal.objectivity.db;

import org.eclipse.emf.cdo.server.internal.objectivity.bundle.OM;
import org.eclipse.emf.cdo.server.internal.objectivity.clustering.ObjyPlacementManager;
import org.eclipse.emf.cdo.server.internal.objectivity.clustering.ObjyPlacementManagerImpl;
import org.eclipse.emf.cdo.server.objectivity.IObjectivityStoreConfig;

import org.eclipse.net4j.util.om.trace.ContextTracer;

import com.objy.db.DatabaseNotFoundException;
import com.objy.db.DatabaseOpenException;
import com.objy.db.ObjyRuntimeException;
import com.objy.db.app.Connection;
import com.objy.db.app.Session;
import com.objy.db.app.oo;

import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;

public class ObjyConnection
{

  public static final ObjyConnection INSTANCE = new ObjyConnection();

  protected Connection connection = null;

  protected boolean isConnected = false;

  protected String fdName = "";

  // protected ObjectivityStore store = null;

  private static final ContextTracer TRACER_DEBUG = new ContextTracer(OM.DEBUG, ObjyConnection.class);

  // private static final ContextTracer TRACER_INFO = new ContextTracer(OM.INFO, ObjyConnection.class);

  // TODO - session pools could be a configuration candidate.
  private static final String SESSION_POOL_NAME_READ = "ReadSP";

  private static final String SESSION_POOL_NAME_WRITE = "WriteSP";

  // private static final String PoolInfo = "PoolInfo";

  protected ConcurrentHashMap<String, ObjySession> readPool;

  protected ConcurrentHashMap<String, ObjySession> writePool;

  private ObjyPlacementManager defaultPlacementManager = null;

  private Object syncObject = new Object();

  private ReentrantLock lock = new ReentrantLock();

  private int sessionMinCacheSize = 600;

  private int sessionMaxCacheSize = 1000;

  private final int minInactiveSessions = 5;

  private int sessionCount = 0;

  private String logDirPath = null;

  private int logOption = oo.LogNone;

  public ObjyConnection()
  {
    readPool = new ConcurrentHashMap<String, ObjySession>(5);
    writePool = new ConcurrentHashMap<String, ObjySession>(5);
  }

  /***
   * Connect to a store and an FD. TODO - We might need to allow switching of FD in the future.
   */
  synchronized public void connect(IObjectivityStoreConfig storeConfig)
  {
    /****
     * If
     */
    fdName = storeConfig.getFdName();
    logDirPath = storeConfig.getLogPath();
    logOption = storeConfig.getLogOption();
    connect();
    // this.store = store;
  }

  synchronized public void connect(String fdName, int logOption)
  {
    /****
     * If
     */
    this.fdName = fdName;
    this.logOption = logOption;
    connect();
    // this.store = store;
  }

  private void connect()
  {

    if (TRACER_DEBUG.isEnabled())
    {
      TRACER_DEBUG.trace(" SessionMinCacheSize: " + sessionMinCacheSize);
      TRACER_DEBUG.trace(" SessionMaxCacheSize: " + sessionMaxCacheSize);
    }

    if (!isConnected)
    {
      try
      {
        if (Connection.current() == null)
        {
          if (logOption != oo.LogNone)
          {
            Connection.setLoggingOptions(logOption, true, // boolean logToFiles
                true, // boolean appendLogFiles,
                logDirPath, // String logDirPath,
                "MainLog.txt"// String mainLogFileName
                );
          }
          if (TRACER_DEBUG.isEnabled())
          {
            TRACER_DEBUG.trace(" creating new Connection");
          }
          connection = Connection.open(fdName, oo.openReadWrite);
          connection.useContextClassLoader(true);
        }
        else
        {
          connection.addToMainLog("ObjyConnection.connect()", "...reopen connection to the FD.");
          connection.setOpenMode(oo.openReadWrite);
          connection.reopen();
          connection.loadSchemaClasses(true);
        }
        isConnected = true;
      }
      catch (DatabaseOpenException e)
      {
        e.printStackTrace();
      }
      catch (DatabaseNotFoundException e)
      {
        e.printStackTrace();
      }
    }
  }

  public String getSessionPoolNameRead()
  {
    return SESSION_POOL_NAME_READ;
  }

  public String getSessionPoolNameWrite()
  {
    return SESSION_POOL_NAME_WRITE;
  }

  public ObjySession getWriteSessionFromPool(String sessionName)
  {
    return getSessionFromPool(sessionName);
  }

  public ObjySession getReadSessionFromPool(String sessionName)
  {
    return getSessionFromPool(sessionName);
  }

  protected ObjySession getSessionFromPool(String sessionName)
  {
    synchronized (syncObject)
    {
      // return connection.getSessionFromPool(getSessionPoolNameWrite(), sessionName);
      ObjySession session = readPool.get(sessionName);
      if (session == null)
      {
        if (sessionCount >= minInactiveSessions)
        {
          // look for an inactive one, rename it and use it.
          for (ObjySession objySession : readPool.values())
          {
            if (objySession.isAvailable())
            {
              objySession.setName(sessionName);
              session = objySession;
              break;
            }
          }
        }

        // we are forced to create one.
        if (session == null)
        {
          session = new ObjySession(sessionName, readPool, this);
          ++sessionCount;
          // System.out.println(">>> IS: creating new session: " + sessionName + " - total: " + sessionCount);
          readPool.put(sessionName, session);
        }
      }
      session.join();
      session.setAvailable(false);
      return session;
    }
  }

  public void disconnect()
  {
    if (!isConnected)
    {
      return;
    }
    // synchronized(syncObject)
    {
      // it's important to do the lock() call, otherwise during the test-suite
      // run we can exit the test before cleaning up, and session might be
      // partly terminated.
      // We could change the code in cleanupSessionPool() to remove the session
      // from the pool before terminating it, but this could leave some sessions
      // in the connection (another issue here is the connection.reconnect()
      // doesn't work all the time).
      lock.lock();
      if (TRACER_DEBUG.isEnabled())
      {
        TRACER_DEBUG.trace("ObjyConnection.disconnect() -- Start. " + toString());
      }

      // terminate the session and cleanup the Pool.
      // TRACER_DEBUG.trace("ObjyConnection.disconnect() -- cleanup readPool. ");
      cleanupSessionPool(readPool);
      // TRACER_DEBUG.trace("ObjyConnection.disconnect() -- cleanup writePool. ");
      cleanupSessionPool(writePool);

      sessionCount = 0;

      // TRACER_DEBUG.trace("ObjyConnection.disconnect() -- cleanup any other sessions. ");
      // for testing we need to find out if there are any open sessions.

      @SuppressWarnings("unchecked")
      Vector<Session> sessions = connection.sessions();
      for (Session aSession : sessions)
      {
        if (TRACER_DEBUG.isEnabled())
        {
          TRACER_DEBUG.trace("Session: " + aSession + " - open state: " + aSession.isOpen());
        }
        // we need to make sure that any open session is aborted, otherwise we
        // can't reopen the fd.
        if (aSession.isOpen())
        {
          try
          {
            aSession.join();
            aSession.abort();
            // IS: sometime we get exception about no transaction, although we checked
            // aSession.isOpen() above.
          }
          catch (ObjyRuntimeException ex)
          {
            ex.printStackTrace();
          }
          finally
          {
            aSession.terminate();
          }
        }
      }

      // 100211:IS - Avoid closing the connection, we're seeing
      // sort of schema issues doing so with 9.4.1...
      /****
       * try { Session session = new Session(); session.begin(); //connection.dropAllUserClasses(true);
       * connection.dropAllUnregisterableClasses(); session.commit(); connection.close(); isConnected = false; } catch
       * (DatabaseClosedException e) { // TODO Auto-generated catch block e.printStackTrace(); }
       ****/
      if (TRACER_DEBUG.isEnabled())
      {
        TRACER_DEBUG.trace("ObjyConnection.disconnect() -- END. ");
      }
      lock.unlock();
    }

  }

  // public void resetFD()
  // {
  // //fdManager.resetFD();
  // if (Connection.current() != null)
  // {
  // if (!isConnected)
  // connect();
  //
  // // for testing we need to find out if there are any open sessions.
  // Vector<Session> sessions = Connection.current().sessions();
  // System.out.println("Sessions still available: " + sessions.size());
  // for (Session aSession : sessions)
  // {
  // System.out.println("Session: " + aSession + " - open state: " + aSession.isOpen());
  // // we need to make sure that any open session is aborted, otherwise we
  // // can't reopen the fd.
  // if (aSession.isOpen())
  // {
  // try {
  // aSession.join();
  // aSession.abort();
  // // IS: sometime we get exception about no transaction, although we checked
  // // aSession.isOpen() above.
  // } catch (ObjyRuntimeException ex) {
  // ex.printStackTrace();
  // } finally {
  // aSession.terminate();
  // }
  // }
  // }
  //
  // // Session session = new Session();
  // // session.begin();
  // // Iterator itr = session.getFD().containedDBs();
  // // ooDBObj dbObj = null;
  // // List<ooDBObj> dbList = new ArrayList<ooDBObj>();
  // // while (itr.hasNext())
  // // {
  // // dbObj = (ooDBObj) itr.next();
  // // dbList.add(dbObj);
  // // }
  // // itr.close();
  // // session.commit();
  //
  // // session.begin();
  // // for (ooDBObj db : dbList)
  // // {
  // // System.out.println("restFD() - deleting DB(" + db.getOid().getStoreString()+"):" + db.getName());
  // // db.delete();
  // // }
  // // session.commit();
  //
  // // we need to wipe the schema, some tests have similar class and package
  // // names which could cause tests to fail.
  // // for now we'll just wipe the wole FD.
  // //fdManager.resetFD_OLD();
  //
  // //
  // // System.out.println("resetFD() - dumping catalog BEGIN.........");
  // // session.begin();
  // // session.getFD().dumpCatalog();
  // // session.commit();
  // // System.out.println("resetFD() - dumping catalog END...........");
  // // session.terminate();
  //
  // disconnect();
  // }
  // }

  public void registerClass(String name)
  {
    connection.registerClass(name);
  }

  public ObjyPlacementManager getDefaultPlacementManager()
  {
    if (defaultPlacementManager == null)
    {
      defaultPlacementManager = new ObjyPlacementManagerImpl();
    }
    return defaultPlacementManager;
  }

  protected void cleanupSessionPool(ConcurrentHashMap<String, ObjySession> pool)
  {
    for (ObjySession objySession : pool.values())
    {
      try
      {
        if (objySession.isOpen())
        {
          objySession.join();
          objySession.abort();
          // IS: sometime we get exception about no transaction, although we checked
          // aSession.isOpen() above.
        }
      }
      catch (ObjyRuntimeException ex)
      {
        ex.printStackTrace();
      }
      finally
      {
        // TRACER_DEBUG.trace("ObjyConnection.cleanupSessionPool() -- start terminating session. " +
        // objySession.toString());
        try
        {
          objySession.terminate();
          // TRACER_DEBUG.trace("ObjyConnection.cleanupSessionPool() -- end terminating session. " +
          // objySession.toString());
        }
        catch (ObjyRuntimeException ex)
        {
          ex.printStackTrace();
        }
      }
    }
    pool.clear();
  }

  public void setSessionMinCacheSize(int sessionMinCacheSize)
  {
    if (sessionMinCacheSize > this.sessionMinCacheSize)
    {
      this.sessionMinCacheSize = sessionMinCacheSize;
    }
  }

  public void setSessionMaxCacheSize(int sessionMaxCacheSize)
  {
    if (sessionMaxCacheSize > this.sessionMaxCacheSize)
    {
      this.sessionMaxCacheSize = sessionMaxCacheSize;
    }
  }

  public int getMinSessionCacheSize()
  {
    return sessionMinCacheSize;
  }

  public int getMaxSessionCacheSize()
  {
    return sessionMaxCacheSize;
  }
}
