/*
 * Copyright (c) 2009-2013, 2015 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 - 271444: [DB] Multiple refactorings bug 271444
 *    Christopher Albert - 254455: [DB] Support FeatureMaps bug 254455
 *    Stefan Winkler - Bug 329025: [DB] Support branching for range-based mapping strategy
 */
package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;

import org.eclipse.emf.cdo.common.branch.CDOBranch;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.revision.CDORevision;
import org.eclipse.emf.cdo.common.revision.delta.CDOAddFeatureDelta;
import org.eclipse.emf.cdo.common.revision.delta.CDOClearFeatureDelta;
import org.eclipse.emf.cdo.common.revision.delta.CDOContainerFeatureDelta;
import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta;
import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDeltaVisitor;
import org.eclipse.emf.cdo.common.revision.delta.CDOListFeatureDelta;
import org.eclipse.emf.cdo.common.revision.delta.CDOMoveFeatureDelta;
import org.eclipse.emf.cdo.common.revision.delta.CDORemoveFeatureDelta;
import org.eclipse.emf.cdo.common.revision.delta.CDOSetFeatureDelta;
import org.eclipse.emf.cdo.common.revision.delta.CDOUnsetFeatureDelta;
import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
import org.eclipse.emf.cdo.server.db.IIDHandler;
import org.eclipse.emf.cdo.server.db.mapping.IListMappingDeltaSupport;
import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
import org.eclipse.emf.cdo.server.db.mapping.ITypeMapping;

import org.eclipse.net4j.db.DBException;
import org.eclipse.net4j.db.DBUtil;
import org.eclipse.net4j.db.IDBPreparedStatement;
import org.eclipse.net4j.db.IDBPreparedStatement.ReuseProbability;
import org.eclipse.net4j.util.ImplementationError;

import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.util.FeatureMap;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.List;

/**
 * This is a featuremap-to-table mapping optimized for non-audit-mode. It doesn't care about version and has delta
 * support.
 *
 * @author Eike Stepper
 * @since 3.0
 */
public class NonAuditFeatureMapTableMapping extends AbstractFeatureMapTableMapping implements IListMappingDeltaSupport
{
  private static final int TEMP_INDEX = -1;

  private static final int UNBOUNDED_MOVE = -1;

  private String sqlClear;

  private String sqlUpdateIndex;

  private String sqlUpdateValue;

  private String sqlDeleteItem;

  private String sqlMoveDownWithLimit;

  private String sqlMoveDown;

  private String sqlMoveUpWithLimit;

  private String sqlMoveUp;

  public NonAuditFeatureMapTableMapping(IMappingStrategy mappingStrategy, EClass eClass, EStructuralFeature feature)
  {
    super(mappingStrategy, eClass, feature);
    initSQLStrings();
  }

  private void initSQLStrings()
  {
    // TODO: add key fields length support

    StringBuilder builder = new StringBuilder();

    // ----------- clear list -------------------------

    builder.append("DELETE FROM "); //$NON-NLS-1$
    builder.append(getTable());
    builder.append(" WHERE "); //$NON-NLS-1$
    builder.append(FEATUREMAP_REVISION_ID);
    builder.append("=? "); //$NON-NLS-1$

    sqlClear = builder.toString();

    builder.append(" AND "); //$NON-NLS-1$
    builder.append(FEATUREMAP_IDX);
    builder.append("=? "); //$NON-NLS-1$

    sqlDeleteItem = builder.toString();

    // ----------- update one item index --------------
    builder = new StringBuilder();
    builder.append("UPDATE "); //$NON-NLS-1$
    builder.append(getTable());
    builder.append(" SET "); //$NON-NLS-1$
    builder.append(FEATUREMAP_IDX);
    builder.append("=? "); //$NON-NLS-1$
    builder.append(" WHERE "); //$NON-NLS-1$
    builder.append(FEATUREMAP_REVISION_ID);
    builder.append("=? AND "); //$NON-NLS-1$
    builder.append(FEATUREMAP_IDX);
    builder.append("=? "); //$NON-NLS-1$
    sqlUpdateIndex = builder.toString();

    // ----------- update one item value --------------
    builder = new StringBuilder();
    builder.append("UPDATE "); //$NON-NLS-1$
    builder.append(getTable());
    builder.append(" SET "); //$NON-NLS-1$

    builder.append(FEATUREMAP_TAG);
    builder.append("=?,"); //$NON-NLS-1$

    Iterator<String> iter = getColumnNames().iterator();
    while (iter.hasNext())
    {
      String column = iter.next();
      builder.append(column);
      builder.append("=?"); //$NON-NLS-1$

      if (iter.hasNext())
      {
        builder.append(", "); //$NON-NLS-1$
      }
    }

    builder.append(" WHERE "); //$NON-NLS-1$
    builder.append(FEATUREMAP_REVISION_ID);
    builder.append("=? AND "); //$NON-NLS-1$
    builder.append(FEATUREMAP_IDX);
    builder.append("=? "); //$NON-NLS-1$
    sqlUpdateValue = builder.toString();

    // ----------- move down --------------
    builder = new StringBuilder();
    builder.append("UPDATE "); //$NON-NLS-1$
    builder.append(getTable());
    builder.append(" SET "); //$NON-NLS-1$
    builder.append(FEATUREMAP_IDX);
    builder.append("="); //$NON-NLS-1$
    builder.append(FEATUREMAP_IDX);
    builder.append("-1 WHERE "); //$NON-NLS-1$
    builder.append(FEATUREMAP_REVISION_ID);
    builder.append("=? AND "); //$NON-NLS-1$
    builder.append(FEATUREMAP_IDX);
    builder.append(">? "); //$NON-NLS-1$
    sqlMoveDown = builder.toString();

    builder.append(" AND "); //$NON-NLS-1$
    builder.append(FEATUREMAP_IDX);
    builder.append("<=?"); //$NON-NLS-1$
    sqlMoveDownWithLimit = builder.toString();

    // ----------- move up --------------
    builder = new StringBuilder();
    builder.append("UPDATE "); //$NON-NLS-1$
    builder.append(getTable());
    builder.append(" SET "); //$NON-NLS-1$
    builder.append(FEATUREMAP_IDX);
    builder.append("="); //$NON-NLS-1$
    builder.append(FEATUREMAP_IDX);
    builder.append("+1 WHERE "); //$NON-NLS-1$
    builder.append(FEATUREMAP_REVISION_ID);
    builder.append("=? AND "); //$NON-NLS-1$
    builder.append(FEATUREMAP_IDX);
    builder.append(">=? "); //$NON-NLS-1$
    sqlMoveUp = builder.toString();

    builder.append(" AND "); //$NON-NLS-1$
    builder.append(FEATUREMAP_IDX);
    builder.append("<?"); //$NON-NLS-1$
    sqlMoveUpWithLimit = builder.toString();
  }

  @Override
  protected void addKeyFields(List<FieldInfo> list)
  {
    // Do nothing
  }

  @Override
  protected void setKeyFields(PreparedStatement stmt, CDORevision revision) throws SQLException
  {
    getMappingStrategy().getStore().getIDHandler().setCDOID(stmt, 1, revision.getID());
  }

  public void objectDetached(IDBStoreAccessor accessor, CDOID id, long revised)
  {
    clearList(accessor, id);
  }

  /**
   * Clear a list of a given revision.
   *
   * @param accessor
   *          the accessor to use
   * @param id
   *          the id of the revision from which to remove all items
   */
  public void clearList(IDBStoreAccessor accessor, CDOID id)
  {
    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
    IDBPreparedStatement stmt = accessor.getDBConnection().prepareStatement(sqlClear, ReuseProbability.HIGH);

    try
    {
      idHandler.setCDOID(stmt, 1, id);
      DBUtil.update(stmt, false);
    }
    catch (SQLException e)
    {
      throw new DBException(e);
    }
    finally
    {
      DBUtil.close(stmt);
    }
  }

  @Override
  public void rawDeleted(IDBStoreAccessor accessor, CDOID id, CDOBranch branch, int version)
  {
    clearList(accessor, id);
  }

  /**
   * Insert a list item at a specified position.
   *
   * @param accessor
   *          the accessor to use
   * @param id
   *          the id of the revision to insert the value
   * @param index
   *          the index where to insert the element
   * @param value
   *          the value to insert.
   */
  public void insertListItem(IDBStoreAccessor accessor, CDOID id, int index, Object value, long timestamp)
  {
    move1up(accessor, id, index, UNBOUNDED_MOVE);
    insertValue(accessor, id, index, value, timestamp);
  }

  private void insertValue(IDBStoreAccessor accessor, CDOID id, int index, Object value, long timestamp)
  {
    FeatureMap.Entry entry = (FeatureMap.Entry)value;
    EStructuralFeature entryFeature = entry.getEStructuralFeature();
    CDOID tag = getTagByFeature(entryFeature, timestamp);
    ITypeMapping typeMapping = getTypeMapping(tag);
    String columnName = getColumnName(tag);

    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
    IDBPreparedStatement stmt = accessor.getDBConnection().prepareStatement(sqlInsert, ReuseProbability.HIGH);

    try
    {
      idHandler.setCDOID(stmt, 1, id);
      int column = getKeyFields().length + 1;

      for (int i = 0; i < getColumnNames().size(); i++)
      {
        if (getColumnNames().get(i).equals(columnName))
        {
          typeMapping.setValue(stmt, column++, entry.getValue());
        }
        else
        {
          stmt.setNull(column++, getDBTypes().get(i).getCode());
        }
      }

      stmt.setInt(column++, index);
      idHandler.setCDOID(stmt, column++, tag);
      DBUtil.update(stmt, true);
    }
    catch (SQLException e)
    {
      throw new DBException(e);
    }
    finally
    {
      DBUtil.close(stmt);
    }
  }

  /**
   * Move a list item from one position to another. Indices between both positions are updated so that the list remains
   * consistent.
   *
   * @param accessor
   *          the accessor to use
   * @param id
   *          the id of the revision in which to move the item
   * @param oldPosition
   *          the old position of the item.
   * @param newPosition
   *          the new position of the item.
   */
  public void moveListItem(IDBStoreAccessor accessor, CDOID id, int oldPosition, int newPosition)
  {
    if (oldPosition == newPosition)
    {
      return;
    }

    // move element away temporarily
    updateOneIndex(accessor, id, oldPosition, TEMP_INDEX);

    // move elements in between
    if (oldPosition < newPosition)
    {
      move1down(accessor, id, oldPosition, newPosition);
    }
    else
    {
      // oldPosition > newPosition -- equal case is handled above
      move1up(accessor, id, newPosition, oldPosition);
    }

    // move temporary element to new position
    updateOneIndex(accessor, id, TEMP_INDEX, newPosition);
  }

  private void updateOneIndex(IDBStoreAccessor accessor, CDOID id, int oldIndex, int newIndex)
  {
    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
    IDBPreparedStatement stmt = accessor.getDBConnection().prepareStatement(sqlUpdateIndex, ReuseProbability.HIGH);

    try
    {
      stmt.setInt(1, newIndex);
      idHandler.setCDOID(stmt, 2, id);
      stmt.setInt(3, oldIndex);
      DBUtil.update(stmt, true);
    }
    catch (SQLException e)
    {
      throw new DBException(e);
    }
    finally
    {
      DBUtil.close(stmt);
    }
  }

  /**
   * Remove a list item from a specified a position.
   *
   * @param accessor
   *          the accessor to use
   * @param id
   *          the id of the revision from which to remove the item
   * @param index
   *          the index of the item to remove
   */
  public void removeListItem(IDBStoreAccessor accessor, CDOID id, int index)
  {
    deleteItem(accessor, id, index);
    move1down(accessor, id, index, UNBOUNDED_MOVE);
  }

  /**
   * Move references downwards to close a gap at position <code>index</code>. Only indexes starting with
   * <code>index + 1</code> and ending with <code>upperIndex</code> are moved down.
   */
  private void move1down(IDBStoreAccessor accessor, CDOID id, int index, int upperIndex)
  {
    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
    IDBPreparedStatement stmt = accessor.getDBConnection()
        .prepareStatement(upperIndex == UNBOUNDED_MOVE ? sqlMoveDown : sqlMoveDownWithLimit, ReuseProbability.HIGH);

    try
    {
      idHandler.setCDOID(stmt, 1, id);
      stmt.setInt(2, index);
      if (upperIndex != UNBOUNDED_MOVE)
      {
        stmt.setInt(3, upperIndex);
      }

      DBUtil.update(stmt, false);
    }
    catch (SQLException e)
    {
      throw new DBException(e);
    }
    finally
    {
      DBUtil.close(stmt);
    }
  }

  /**
   * Move references downwards to close a gap at position <code>index</code>. Only indexes starting with
   * <code>index + 1</code> and ending with <code>upperIndex</code> are moved down.
   */
  private void move1up(IDBStoreAccessor accessor, CDOID id, int index, int upperIndex)
  {
    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
    IDBPreparedStatement stmt = accessor.getDBConnection()
        .prepareStatement(upperIndex == UNBOUNDED_MOVE ? sqlMoveUp : sqlMoveUpWithLimit, ReuseProbability.HIGH);

    try
    {
      idHandler.setCDOID(stmt, 1, id);
      stmt.setInt(2, index);
      if (upperIndex != UNBOUNDED_MOVE)
      {
        stmt.setInt(3, upperIndex);
      }

      DBUtil.update(stmt, false);
    }
    catch (SQLException e)
    {
      throw new DBException(e);
    }
    finally
    {
      DBUtil.close(stmt);
    }
  }

  private void deleteItem(IDBStoreAccessor accessor, CDOID id, int index)
  {
    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
    IDBPreparedStatement stmt = accessor.getDBConnection().prepareStatement(sqlDeleteItem, ReuseProbability.HIGH);

    try
    {
      idHandler.setCDOID(stmt, 1, id);
      stmt.setInt(2, index);
      DBUtil.update(stmt, true);
    }
    catch (SQLException e)
    {
      throw new DBException(e);
    }
    finally
    {
      DBUtil.close(stmt);
    }
  }

  /**
   * Set a value at a specified position to the given value.
   *
   * @param accessor
   *          the accessor to use
   * @param id
   *          the id of the revision to set the value
   * @param index
   *          the index of the item to set
   * @param value
   *          the value to be set.
   */
  public void setListItem(IDBStoreAccessor accessor, CDOID id, int index, Object value, long timestamp)
  {
    FeatureMap.Entry entry = (FeatureMap.Entry)value;
    EStructuralFeature entryFeature = entry.getEStructuralFeature();
    CDOID tag = getTagByFeature(entryFeature, timestamp);
    ITypeMapping mapping = getTypeMapping(tag);
    String columnName = getColumnName(tag);

    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
    IDBPreparedStatement stmt = accessor.getDBConnection().prepareStatement(sqlUpdateValue, ReuseProbability.HIGH);

    try
    {
      idHandler.setCDOID(stmt, 1, tag);
      int column = 2;

      for (int i = 0; i < getColumnNames().size(); i++)
      {
        if (getColumnNames().get(i).equals(columnName))
        {
          mapping.setValue(stmt, column++, entry.getValue());
        }
        else
        {
          stmt.setNull(column++, getDBTypes().get(i).getCode());
        }
      }

      idHandler.setCDOID(stmt, column++, id);
      stmt.setInt(column++, index);
      DBUtil.update(stmt, true);
    }
    catch (SQLException e)
    {
      throw new DBException(e);
    }
    finally
    {
      DBUtil.close(stmt);
    }
  }

  public void processDelta(final IDBStoreAccessor accessor, final CDOID id, final int branchId, int oldVersion,
      final int newVersion, final long created, CDOListFeatureDelta listDelta)
  {
    CDOFeatureDeltaVisitor visitor = new CDOFeatureDeltaVisitor()
    {
      public void visit(CDOMoveFeatureDelta delta)
      {
        moveListItem(accessor, id, delta.getOldPosition(), delta.getNewPosition());
      }

      public void visit(CDOAddFeatureDelta delta)
      {
        insertListItem(accessor, id, delta.getIndex(), delta.getValue(), created);
      }

      public void visit(CDORemoveFeatureDelta delta)
      {
        removeListItem(accessor, id, delta.getIndex());
      }

      public void visit(CDOSetFeatureDelta delta)
      {
        setListItem(accessor, id, delta.getIndex(), delta.getValue(), created);
      }

      public void visit(CDOUnsetFeatureDelta delta)
      {
        if (delta.getFeature().isUnsettable())
        {
          throw new ImplementationError("Should not be called"); //$NON-NLS-1$
        }

        clearList(accessor, id);
      }

      public void visit(CDOListFeatureDelta delta)
      {
        throw new ImplementationError("Should not be called"); //$NON-NLS-1$
      }

      public void visit(CDOClearFeatureDelta delta)
      {
        clearList(accessor, id);
      }

      public void visit(CDOContainerFeatureDelta delta)
      {
        throw new ImplementationError("Should not be called"); //$NON-NLS-1$
      }
    };

    for (CDOFeatureDelta delta : listDelta.getListChanges())
    {
      delta.accept(visitor);
    }
  }
}
