/***************************************************************************
 * Copyright (c) 2004 - 2008 Eike Stepper, Germany.
 * 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:
 *    Eike Stepper - initial API and implementation
 **************************************************************************/
package org.eclipse.emf.cdo.server.internal.db.jdbc;

import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.id.CDOIDUtil;
import org.eclipse.emf.cdo.common.revision.CDORevision;
import org.eclipse.emf.cdo.server.db.IAttributeMapping;
import org.eclipse.emf.cdo.server.internal.db.CDODBSchema;
import org.eclipse.emf.cdo.server.internal.db.ServerInfo;
import org.eclipse.emf.cdo.server.internal.db.bundle.OM;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;

import org.eclipse.net4j.db.DBException;
import org.eclipse.net4j.db.DBUtil;
import org.eclipse.net4j.util.collection.Pair;
import org.eclipse.net4j.util.om.monitor.OMMonitor;
import org.eclipse.net4j.util.om.monitor.OMMonitor.Async;
import org.eclipse.net4j.util.om.trace.ContextTracer;
import org.eclipse.net4j.util.ref.ReferenceValueMap;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * @author Stefan Winkler
 * @since 2.0
 */
public class PreparedStatementJDBCDelegate extends AbstractJDBCDelegate
{
  /**
   * Value for {@link #cachingFlag}: Guess if caching is needed
   */
  public static final String CACHE_STMTS_GUESS = "guess";

  /**
   * Value for {@link #cachingFlag}: Turn caching on
   */
  public static final String CACHE_STMTS_TRUE = "true";

  /**
   * Value for {@link #cachingFlag}: Turn caching off
   */
  public static final String CACHE_STMTS_FALSE = "false";

  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, PreparedStatementJDBCDelegate.class);

  private static final String SQL_UPDATE_REVISE_VERSION = " SET " + CDODBSchema.ATTRIBUTES_REVISED + " = ? WHERE "
      + CDODBSchema.ATTRIBUTES_ID + " = ? AND " + CDODBSchema.ATTRIBUTES_VERSION + " = ?";

  private static final String SQL_UPDATE_REVISE_UNREVISED = " SET " + CDODBSchema.ATTRIBUTES_REVISED + " = ? WHERE "
      + CDODBSchema.ATTRIBUTES_ID + " = ? AND " + CDODBSchema.ATTRIBUTES_REVISED + " = 0";

  private static final String SQL_INSERT_REFERENCE_WITH_DBID = " VALUES (?, ?, ?, ?, ?)";

  private static final String SQL_INSERT_REFERENCE = " VALUES (?, ?, ?, ?)";

  /**
   * Cache for preparedStatements used in diverse methods
   */
  private Map<CacheKey, WrappedPreparedStatement> statementCache = null;

  /**
   * Container for dirty statements. A statement is considered 'dirty', if addBatch was called, but not executeBatch.
   */
  private Map<CacheKey, PreparedStatement> dirtyStatements = null;

  /**
   * This flag determines, if prepared statements should be cached within this delegate. Its value is guessed in
   * {@link #postInitConnection()} based on the fact if the JDBC driver supports pooled statements. If it does, caching
   * in the delegate is unnecessary.
   */
  private boolean cacheStatements;

  private CachingEnablement cachingEnablement;

  public PreparedStatementJDBCDelegate()
  {
  }

  public CachingEnablement getCachingEnablement()
  {
    return cachingEnablement;
  }

  public void setCachingEnablement(CachingEnablement cachingEnablement)
  {
    checkInactive();
    this.cachingEnablement = cachingEnablement;
  }

  public void flush(OMMonitor monitor)
  {
    try
    {
      monitor.begin(dirtyStatements.size());
      for (Entry<CacheKey, PreparedStatement> entry : dirtyStatements.entrySet())
      {
        try
        {
          int[] results;
          Async async = monitor.forkAsync();

          try
          {
            results = entry.getValue().executeBatch();
          }
          finally
          {
            async.stop();
          }

          if (TRACER.isEnabled())
          {
            TRACER.format("Executing batch for {0} [{1}]", entry.getKey().toString(), entry.getValue());
          }

          for (int result : results)
          {
            checkState(result == 1, "Batch execution did not return '1' for " + entry.getKey().toString());
          }
        }
        catch (SQLException ex)
        {
          throw new DBException("Batch execution failed for " + entry.getKey().toString() + " [" + entry.getValue()
              + "]", ex);
        }
      }
    }
    finally
    {
      if (!cacheStatements)
      {
        if (TRACER.isEnabled())
        {
          TRACER.format("Closing prepared statements.");
        }

        for (PreparedStatement ps : dirtyStatements.values())
        {
          DBUtil.close(ps);
        }
      }
      else
      {
        if (TRACER.isEnabled())
        {
          TRACER.format("Re-caching prepared statements.");
        }

        for (Entry<CacheKey, PreparedStatement> entry : dirtyStatements.entrySet())
        {
          cacheStatement(entry.getKey(), entry.getValue());
        }
      }

      dirtyStatements.clear();
      monitor.done();
    }
  }

  @Override
  protected void doActivate() throws Exception
  {
    super.doActivate();
    dirtyStatements = new ReferenceValueMap.Strong<CacheKey, PreparedStatement>();

    switch (cachingEnablement)
    {
    case ENABLED:
      cacheStatements = true;
      break;

    case DISABLED:
      cacheStatements = false;
      break;

    case GUESS:
      try
      {
        cacheStatements = !getConnection().getMetaData().supportsStatementPooling();
      }
      catch (SQLException ex)
      {
        OM.LOG.warn("Failed to guess JDBC statement pooling. Activating cache, just to be sure ...", ex);
        cacheStatements = true;
      }
    }

    if (TRACER.isEnabled())
    {
      TRACER.trace("JDBC PreparedStatement caching is " + (cacheStatements ? "enabled." : "NOT enabled."));
    }

    if (cacheStatements)
    {
      // initialize cache ...
      statementCache = new ReferenceValueMap.Soft<CacheKey, WrappedPreparedStatement>();
    }
  }

  @Override
  protected void doBeforeDeactivate() throws Exception
  {
    for (PreparedStatement ps : dirtyStatements.values())
    {
      DBUtil.close(ps);
    }

    dirtyStatements.clear();
    if (cacheStatements)
    {
      for (WrappedPreparedStatement ps : statementCache.values())
      {
        DBUtil.close(ps.getWrappedStatement());
      }

      statementCache.clear();
    }

    super.doBeforeDeactivate();
  }

  /**
   * Implementation of the hook which is called after selects.
   */
  @Override
  protected void releaseStatement(Statement stmt)
  {
    // leave open cached statements
    if (!cacheStatements || !(stmt instanceof PreparedStatement))
    {
      super.releaseStatement(stmt);
    }

    // /* This code would guarantee that releaseStatement is only called
    // for cached statements. However this looks through the whole hashmap
    // and is thus too expensive to do in non-debugging mode. */
    //
    // else {
    // if(!selectStatementsCache.containsValue(stmt)) {
    // super.releaseStatement(stmt);
    // }
    // }
  }

  @Override
  protected void doInsertAttributes(String tableName, CDORevision rev, List<IAttributeMapping> attributeMappings,
      boolean withFullRevisionInfo)
  {
    boolean firstBatch = false;

    InternalCDORevision revision = (InternalCDORevision)rev;
    if (attributeMappings == null)
    {
      attributeMappings = Collections.emptyList();
    }

    PreparedStatement stmt = getDirtyStatement(StmtType.INSERT_ATTRIBUTES, tableName);
    if (stmt == null && cacheStatements)
    {
      firstBatch = true;
      stmt = getAndRemoveCachedStatement(StmtType.INSERT_ATTRIBUTES, tableName);
    }

    try
    {
      firstBatch = true;
      if (stmt == null)
      {
        StringBuilder sql = new StringBuilder();

        sql.append("INSERT INTO ");
        sql.append(tableName);
        sql.append(" VALUES (?, ?, ");
        if (withFullRevisionInfo)
        {
          sql.append("?, ?, ?, ?, ?, ?");
        }

        for (int i = 0; i < attributeMappings.size(); i++)
        {
          sql.append(", ?");
        }

        sql.append(")");
        stmt = getConnection().prepareStatement(sql.toString());
      }

      int col = 1;
      if (TRACER.isEnabled())
      {
        TRACER.trace(stmt.toString());
      }

      stmt.setLong(col++, CDOIDUtil.getLong(revision.getID()));
      stmt.setInt(col++, revision.getVersion());
      if (withFullRevisionInfo)
      {
        stmt.setInt(col++, ServerInfo.getDBID(revision.getCDOClass()));
        stmt.setLong(col++, revision.getCreated());
        stmt.setLong(col++, revision.getRevised());
        stmt.setLong(col++, CDOIDUtil.getLong(revision.getResourceID()));
        stmt.setLong(col++, CDOIDUtil.getLong((CDOID)revision.getContainerID()));
        stmt.setInt(col++, revision.getContainingFeatureID());
      }

      for (IAttributeMapping attributeMapping : attributeMappings)
      {
        Object value = attributeMapping.getRevisionValue(revision);

        if (value == null)
        {
          stmt.setNull(col++, attributeMapping.getField().getType().getCode());
        }
        else
        {
          stmt.setObject(col++, value);
        }
      }

      if (firstBatch)
      {
        addDirtyStatement(StmtType.INSERT_ATTRIBUTES, tableName, stmt);
      }

      stmt.addBatch();
    }
    catch (SQLException e)
    {
      throw new DBException(e);
    }
  }

  @Override
  protected void doInsertReference(String tableName, int dbID, long source, int version, int index, long target)
  {
    boolean firstBatch = false;

    PreparedStatement stmt = getDirtyStatement(StmtType.INSERT_REFERENCES, tableName);
    if (stmt == null && cacheStatements)
    {
      firstBatch = true;
      stmt = getAndRemoveCachedStatement(StmtType.INSERT_REFERENCES, tableName);
    }

    try
    {
      if (stmt == null)
      {
        firstBatch = true;
        StringBuilder sql = new StringBuilder("INSERT INTO ");
        sql.append(tableName);
        sql.append(dbID != 0 ? SQL_INSERT_REFERENCE_WITH_DBID : SQL_INSERT_REFERENCE);
        stmt = getConnection().prepareStatement(sql.toString());
      }

      int idx = 1;
      if (dbID != 0)
      {
        stmt.setInt(idx++, dbID);
      }

      stmt.setLong(idx++, source);
      stmt.setInt(idx++, version);
      stmt.setInt(idx++, index);
      stmt.setLong(idx++, target);
      if (TRACER.isEnabled())
      {
        TRACER.trace(stmt.toString());
      }

      if (firstBatch)
      {
        addDirtyStatement(StmtType.INSERT_REFERENCES, tableName, stmt);
      }

      stmt.addBatch();
    }
    catch (SQLException e)
    {
      throw new DBException(e);
    }
  }

  @Override
  protected void doUpdateRevised(String tableName, long revisedStamp, long cdoid, int version)
  {
    PreparedStatement stmt = null;
    if (cacheStatements)
    {
      stmt = getCachedStatement(StmtType.REVISE_VERSION, tableName);
    }

    try
    {
      if (stmt == null)
      {
        StringBuilder sql = new StringBuilder("UPDATE ");
        sql.append(tableName);
        sql.append(SQL_UPDATE_REVISE_VERSION);
        stmt = getConnection().prepareStatement(sql.toString());

        if (cacheStatements)
        {
          cacheStatement(StmtType.REVISE_VERSION, tableName, stmt);
        }
      }

      stmt.setLong(1, revisedStamp);
      stmt.setLong(2, cdoid);
      stmt.setInt(3, version);
      if (TRACER.isEnabled())
      {
        TRACER.trace(stmt.toString());
      }

      stmt.execute();
    }
    catch (SQLException e)
    {
      throw new DBException(e);
    }
    finally
    {
      if (!cacheStatements)
      {
        DBUtil.close(stmt);
      }
    }
  }

  @Override
  protected void doUpdateRevised(String tableName, long revisedStamp, long cdoid)
  {
    PreparedStatement stmt = null;
    if (cacheStatements)
    {
      stmt = getCachedStatement(StmtType.REVISE_UNREVISED, tableName);
    }

    try
    {
      if (stmt == null)
      {
        StringBuilder sql = new StringBuilder("UPDATE ");
        sql.append(tableName);
        sql.append(SQL_UPDATE_REVISE_UNREVISED);
        stmt = getConnection().prepareStatement(sql.toString());

        if (cacheStatements)
        {
          cacheStatement(StmtType.REVISE_UNREVISED, tableName, stmt);
        }
      }

      stmt.setLong(1, revisedStamp);
      stmt.setLong(2, cdoid);
      if (TRACER.isEnabled())
      {
        TRACER.trace(stmt.toString());
      }

      stmt.execute();
    }
    catch (SQLException e)
    {
      throw new DBException(e);
    }
    finally
    {
      if (!cacheStatements)
      {
        DBUtil.close(stmt);
      }
    }
  }

  @Override
  protected ResultSet doSelectRevisionAttributes(String tableName, long revisionId,
      List<IAttributeMapping> attributeMappings, boolean hasFullRevisionInfo, String where) throws SQLException
  {
    // Because of the variable where clause, statement caching can not be
    // based on table names. Instead, we build the sql in any case and
    // use this as key (similar to what JDBC3 does ...).

    StringBuilder builder = new StringBuilder();
    builder.append("SELECT ");
    builder.append(CDODBSchema.ATTRIBUTES_VERSION);
    builder.append(", ");
    builder.append(CDODBSchema.ATTRIBUTES_CREATED);

    if (hasFullRevisionInfo)
    {
      builder.append(", ");
      builder.append(CDODBSchema.ATTRIBUTES_REVISED);
      builder.append(", ");
      builder.append(CDODBSchema.ATTRIBUTES_RESOURCE);
      builder.append(", ");
      builder.append(CDODBSchema.ATTRIBUTES_CONTAINER);
      builder.append(", ");
      builder.append(CDODBSchema.ATTRIBUTES_FEATURE);
    }

    for (IAttributeMapping attributeMapping : attributeMappings)
    {
      builder.append(", ");
      builder.append(attributeMapping.getField());
    }

    builder.append(" FROM ");
    builder.append(tableName);
    builder.append(" WHERE ");
    builder.append(CDODBSchema.ATTRIBUTES_ID);
    builder.append("= ? AND (");
    builder.append(where);
    builder.append(")");
    String sql = builder.toString();
    if (TRACER.isEnabled())
    {
      TRACER.format("{0} ({1})", sql, revisionId);
    }

    PreparedStatement pstmt = null;
    if (cacheStatements)
    {
      pstmt = getCachedStatement(StmtType.GENERAL, sql);
      if (pstmt == null)
      {
        pstmt = getConnection().prepareStatement(sql);
        cacheStatement(StmtType.GENERAL, sql, pstmt);
      }
    }
    else
    {
      /* no caching */
      pstmt = getConnection().prepareStatement(sql);
    }

    pstmt.setLong(1, revisionId);
    return pstmt.executeQuery();
  }

  @Override
  protected ResultSet doSelectRevisionReferences(String tableName, long sourceId, int version, int dbFeatureID,
      String where) throws SQLException
  {
    StringBuilder builder = new StringBuilder();
    builder.append("SELECT ");
    builder.append(CDODBSchema.REFERENCES_TARGET);
    builder.append(" FROM ");
    builder.append(tableName);
    builder.append(" WHERE ");
    if (dbFeatureID != 0)
    {
      builder.append(CDODBSchema.REFERENCES_FEATURE);
      builder.append("= ? AND ");
    }

    builder.append(CDODBSchema.REFERENCES_SOURCE);
    builder.append("= ? AND ");
    builder.append(CDODBSchema.REFERENCES_VERSION);
    builder.append("= ? ");
    if (where != null)
    {
      builder.append(where);
    }

    builder.append(" ORDER BY ");
    builder.append(CDODBSchema.REFERENCES_IDX);

    String sql = builder.toString();
    if (TRACER.isEnabled())
    {
      TRACER.trace(sql);
    }

    PreparedStatement pstmt = null;
    if (cacheStatements)
    {
      pstmt = getCachedStatement(StmtType.GENERAL, sql);
      if (pstmt == null)
      {
        pstmt = getConnection().prepareStatement(sql);
        cacheStatement(StmtType.GENERAL, sql, pstmt);
      }
    }
    else
    {
      /* no caching */
      pstmt = getConnection().prepareStatement(sql);
    }

    int idx = 1;
    if (dbFeatureID != 0)
    {
      pstmt.setInt(idx++, dbFeatureID);
    }

    pstmt.setLong(idx++, sourceId);
    pstmt.setInt(idx++, version);
    return pstmt.executeQuery();
  }

  /**
   * Add a dirty statement to the dirty statements container.
   */
  private void addDirtyStatement(StmtType type, String subKey, PreparedStatement stmt)
  {
    if (TRACER.isEnabled())
    {
      TRACER.format("Adding dirty statement: ({0},{1}) -> {2}", type, subKey, stmt);
    }

    dirtyStatements.put(new CacheKey(type, subKey), stmt);
  }

  /**
   * Query the dirty statements container.
   * 
   * @return
   */
  private PreparedStatement getDirtyStatement(StmtType type, String subKey)
  {
    return dirtyStatements.get(CacheKey.useOnce(type, subKey));
  }

  /**
   * Cache a prepared statement.
   */
  private void cacheStatement(StmtType type, String subKey, PreparedStatement stmt)
  {
    cacheStatement(new CacheKey(type, subKey), stmt);
  }

  /**
   * Cache a prepared statement with given key.
   */
  private void cacheStatement(CacheKey key, PreparedStatement stmt)
  {
    if (TRACER.isEnabled())
    {
      TRACER.format("Adding cached statement: {0} -> {1}", key, stmt);
    }

    statementCache.put(key, new WrappedPreparedStatement(stmt));
  }

  /**
   * Query the cache of prepared statements.
   */
  private PreparedStatement getCachedStatement(StmtType type, String subKey)
  {
    WrappedPreparedStatement wrapped = statementCache.get(CacheKey.useOnce(type, subKey));
    if (wrapped == null)
    {
      return null;
    }

    PreparedStatement stmt = wrapped.getWrappedStatement();
    if (TRACER.isEnabled())
    {
      TRACER.format("Using cached statement: ({0},{1}) -> {2}", type, subKey, stmt);
    }

    return stmt;
  }

  private PreparedStatement getAndRemoveCachedStatement(StmtType type, String subKey)
  {
    WrappedPreparedStatement wrapped = statementCache.remove(CacheKey.useOnce(type, subKey));
    if (wrapped == null)
    {
      return null;
    }

    PreparedStatement stmt = wrapped.unwrapStatement();
    if (TRACER.isEnabled())
    {
      TRACER.format("Removing cached statement: ({0},{1}) -> {2}", type, subKey, stmt);
    }

    return stmt;
  }

  /**
   * @author Stefan Winkler
   */
  public static enum CachingEnablement
  {
    ENABLED, DISABLED, GUESS
  }

  /**
   * Statement type as first part of the statement cache key.
   * 
   * @author Stefan Winkler
   */
  private static enum StmtType
  {
    INSERT_ATTRIBUTES, INSERT_REFERENCES, REVISE_VERSION, REVISE_UNREVISED, GENERAL
  }

  /**
   * Convenience definition for Pair<StmtType, String>
   * 
   * @author Stefan Winkler
   */
  private static class CacheKey extends Pair<StmtType, String>
  {
    public CacheKey(StmtType type, String subKey)
    {
      super(type, subKey);
    }

    private static CacheKey useOnceKey = new CacheKey(StmtType.GENERAL, "");

    /**
     * Memory-resource-friendly method which uses a single static field, modifies it and returns it to be used at once,
     * e.g., to use it in a cache lookup. Do not store a reference to the result!!!
     */
    public static CacheKey useOnce(StmtType type, String subKey)
    {
      useOnceKey.setElement1(type);
      useOnceKey.setElement2(subKey);
      return useOnceKey;
    }
  }
}
