/*
 * Copyright (c) 2010-2014 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:
 *    Eike Stepper - initial API and implementation
 *    Stefan Winkler - bug 259402
 *    Stefan Winkler - redesign (prepared statements)
 *    Stefan Winkler - bug 276926
 */
package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;

import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.revision.CDORevision;
import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
import org.eclipse.emf.cdo.common.revision.CDORevisionUtil;
import org.eclipse.emf.cdo.server.IView;
import org.eclipse.emf.cdo.server.db.IDBStore;
import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
import org.eclipse.emf.cdo.server.db.IIDHandler;
import org.eclipse.emf.cdo.server.db.IMetaDataManager;
import org.eclipse.emf.cdo.server.db.mapping.IClassMappingUnitSupport;
import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
import org.eclipse.emf.cdo.server.internal.db.CDODBSchema;

import org.eclipse.net4j.db.BatchedStatement;
import org.eclipse.net4j.db.DBException;
import org.eclipse.net4j.db.DBType;
import org.eclipse.net4j.db.DBUtil;
import org.eclipse.net4j.db.IDBConnection;
import org.eclipse.net4j.db.IDBDatabase;
import org.eclipse.net4j.db.IDBDatabase.RunnableWithSchema;
import org.eclipse.net4j.db.IDBPreparedStatement;
import org.eclipse.net4j.db.IDBPreparedStatement.ReuseProbability;
import org.eclipse.net4j.db.ddl.IDBIndex;
import org.eclipse.net4j.db.ddl.IDBSchema;
import org.eclipse.net4j.db.ddl.IDBTable;
import org.eclipse.net4j.util.lifecycle.Lifecycle;

import org.eclipse.emf.ecore.EClass;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
 * @author Eike Stepper
 * @since 4.0
 */
public class UnitMappingTable extends Lifecycle implements IMappingConstants
{
  public static final String UNITS = "CDO_UNITS"; //$NON-NLS-1$

  public static final String UNITS_ELEM = "CDO_ELEM"; //$NON-NLS-1$

  public static final String UNITS_UNIT = "CDO_UNIT"; //$NON-NLS-1$

  // public static final String UNITS_CREATED = "CDO_CREATED"; //$NON-NLS-1$

  private static final String SQL_SELECT_ROOTS = "SELECT DISTINCT " + UNITS_UNIT + " FROM " + UNITS;

  private static final String SQL_INSERT_MAPPINGS = "INSERT INTO " + UNITS + " (" + UNITS_ELEM + ", " + UNITS_UNIT
      + ") VALUES (?, ?)";

  private static final String SQL_SELECT_CLASSES = "SELECT DISTINCT " + ATTRIBUTES_CLASS + " FROM " + UNITS + ", "
      + CDODBSchema.CDO_OBJECTS + " WHERE " + UNITS_ELEM + "=" + ATTRIBUTES_ID + " AND " + UNITS_UNIT + "=?";

  private static final int WRITE_UNIT_MAPPING_BATCH_SIZE = 100000;

  private final IMappingStrategy mappingStrategy;

  private IDBTable table;

  public UnitMappingTable(IMappingStrategy mappingStrategy)
  {
    this.mappingStrategy = mappingStrategy;
  }

  public List<CDOID> readUnitRoots(IDBStoreAccessor accessor)
  {
    List<CDOID> rootIDs = new ArrayList<CDOID>();
    IIDHandler idHandler = mappingStrategy.getStore().getIDHandler();
    Statement stmt = null;

    try
    {
      stmt = accessor.getDBConnection().createStatement();

      if (DBUtil.isTracerEnabled())
      {
        DBUtil.trace(stmt.toString());
      }

      ResultSet resultSet = stmt.executeQuery(SQL_SELECT_ROOTS);
      while (resultSet.next())
      {
        CDOID rootID = idHandler.getCDOID(resultSet, 1);
        rootIDs.add(rootID);
      }
    }
    catch (SQLException ex)
    {
      throw new DBException(ex);
    }
    finally
    {
      DBUtil.close(stmt);
    }

    return rootIDs;
  }

  public void readUnitRevisions(IDBStoreAccessor accessor, IView view, CDOID rootID, CDORevisionHandler revisionHandler)
  {
    IDBStore store = mappingStrategy.getStore();
    IIDHandler idHandler = store.getIDHandler();
    IMetaDataManager metaDataManager = store.getMetaDataManager();

    IDBConnection connection = accessor.getDBConnection();
    IDBPreparedStatement stmt = connection.prepareStatement(SQL_SELECT_CLASSES, ReuseProbability.HIGH);
    int oldFetchSize = -1;

    try
    {
      idHandler.setCDOID(stmt, 1, rootID);

      oldFetchSize = stmt.getFetchSize();
      stmt.setFetchSize(100000);
      ResultSet resultSet = stmt.executeQuery();

      while (resultSet.next())
      {
        CDOID classID = idHandler.getCDOID(resultSet, 1);
        EClass eClass = (EClass)metaDataManager.getMetaInstance(classID);

        IClassMappingUnitSupport classMapping = (IClassMappingUnitSupport)mappingStrategy.getClassMapping(eClass);
        classMapping.readUnitRevisions(accessor, view, rootID, revisionHandler);
      }
    }
    catch (SQLException ex)
    {
      throw new DBException(ex);
    }
    finally
    {
      if (oldFetchSize != -1)
      {
        try
        {
          stmt.setFetchSize(oldFetchSize);
        }
        catch (SQLException ex)
        {
          throw new DBException(ex);
        }
      }

      DBUtil.close(stmt);
    }
  }

  public BatchedStatement initUnit(IDBStoreAccessor accessor, long timeStamp, IView view, CDOID rootID,
      CDORevisionHandler revisionHandler, Set<CDOID> initializedIDs)
  {
    IIDHandler idHandler = mappingStrategy.getStore().getIDHandler();
    IDBConnection connection = accessor.getDBConnection();
    BatchedStatement stmt = DBUtil.batched(connection.prepareStatement(SQL_INSERT_MAPPINGS, ReuseProbability.HIGH),
        WRITE_UNIT_MAPPING_BATCH_SIZE);

    try
    {
      CDORevision revision = view.getRevision(rootID);

      initUnit(stmt, view, rootID, revisionHandler, initializedIDs, timeStamp, idHandler, revision);
      return stmt;
    }
    catch (SQLException ex)
    {
      throw new DBException(ex);
    }
    finally
    {
      // Don't close the statement; that's done later in finishUnit().
    }
  }

  private void initUnit(BatchedStatement stmt, IView view, CDOID rootID, CDORevisionHandler revisionHandler,
      Set<CDOID> initializedIDs, long timeStamp, IIDHandler idHandler, CDORevision revision) throws SQLException
  {
    revisionHandler.handleRevision(revision);

    CDOID id = revision.getID();
    initializedIDs.add(id);

    writeUnitMapping(stmt, rootID, timeStamp, idHandler, id);

    List<CDORevision> children = CDORevisionUtil.getChildRevisions(revision, view, true);
    for (CDORevision child : children)
    {
      initUnit(stmt, view, rootID, revisionHandler, initializedIDs, timeStamp, idHandler, child);
    }
  }

  public void finishUnit(BatchedStatement stmt, CDOID rootID, List<CDOID> ids, long timeStamp)
  {
    IDBStore store = mappingStrategy.getStore();
    IIDHandler idHandler = store.getIDHandler();
    Connection connection = null;

    try
    {
      connection = stmt.getConnection();

      for (CDOID id : ids)
      {
        writeUnitMapping(stmt, rootID, timeStamp, idHandler, id);
      }
    }
    catch (SQLException ex)
    {
      DBUtil.rollbackSilently(connection);
      throw new DBException(ex);
    }
    finally
    {
      DBUtil.close(stmt);
    }

    try
    {
      connection.commit();
    }
    catch (SQLException ex)
    {
      throw new DBException(ex);
    }
  }

  public void writeUnitMappings(IDBStoreAccessor accessor, Map<CDOID, CDOID> unitMappings, long timeStamp)
  {
    IIDHandler idHandler = mappingStrategy.getStore().getIDHandler();
    IDBConnection connection = accessor.getDBConnection();
    BatchedStatement stmt = DBUtil.batched(connection.prepareStatement(SQL_INSERT_MAPPINGS, ReuseProbability.HIGH),
        WRITE_UNIT_MAPPING_BATCH_SIZE);

    try
    {
      for (Entry<CDOID, CDOID> entry : unitMappings.entrySet())
      {
        CDOID id = entry.getKey();
        CDOID rootID = entry.getValue();
        writeUnitMapping(stmt, rootID, timeStamp, idHandler, id);
      }
    }
    catch (SQLException ex)
    {
      throw new DBException(ex);
    }
    finally
    {
      DBUtil.close(stmt);
    }
  }

  private void writeUnitMapping(BatchedStatement stmt, CDOID rootID, long timeStamp, IIDHandler idHandler, CDOID id)
      throws SQLException
  {
    idHandler.setCDOID(stmt, 1, id);
    idHandler.setCDOID(stmt, 2, rootID);
    // stmt.setLong(3, timeStamp);
    stmt.executeUpdate();
  }

  @Override
  protected void doActivate() throws Exception
  {
    super.doActivate();

    IDBStore store = mappingStrategy.getStore();
    final DBType idType = store.getIDHandler().getDBType();
    final int idLength = store.getIDColumnLength();

    IDBDatabase database = store.getDatabase();
    table = database.getSchema().getTable(UNITS);
    if (table == null)
    {
      database.updateSchema(new RunnableWithSchema()
      {
        public void run(IDBSchema schema)
        {
          table = schema.addTable(UNITS);
          table.addField(UNITS_ELEM, idType, idLength, true);
          table.addField(UNITS_UNIT, idType, idLength);
          // table.addField(UNITS_CREATED, DBType.BIGINT);
          table.addIndex(IDBIndex.Type.PRIMARY_KEY, UNITS_ELEM);
          table.addIndex(IDBIndex.Type.NON_UNIQUE, UNITS_UNIT);
        }
      });
    }
  }

  @Override
  protected void doDeactivate() throws Exception
  {
    table = null;
    super.doDeactivate();
  }
}
