/*
 * Copyright (c) 2011-2013 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
 *    Simon McDuff - bug 201266
 *    Simon McDuff - bug 213402
 */
package org.eclipse.emf.cdo.spi.server;

import org.eclipse.emf.cdo.common.branch.CDOBranch;
import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
import org.eclipse.emf.cdo.common.branch.CDOBranchVersion;
import org.eclipse.emf.cdo.common.commit.CDOCommitData;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.id.CDOIDTemp;
import org.eclipse.emf.cdo.common.id.CDOIDUtil;
import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion;
import org.eclipse.emf.cdo.common.revision.CDOList;
import org.eclipse.emf.cdo.common.revision.CDORevision;
import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
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.CDORemoveFeatureDelta;
import org.eclipse.emf.cdo.common.revision.delta.CDOSetFeatureDelta;
import org.eclipse.emf.cdo.common.revision.delta.CDOUnsetFeatureDelta;
import org.eclipse.emf.cdo.common.util.CDOCommonUtil;
import org.eclipse.emf.cdo.internal.server.bundle.OM;
import org.eclipse.emf.cdo.server.ISession;
import org.eclipse.emf.cdo.server.IStoreAccessor;
import org.eclipse.emf.cdo.server.ITransaction;
import org.eclipse.emf.cdo.spi.common.commit.CDOCommitInfoUtil;
import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry;
import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;
import org.eclipse.emf.cdo.spi.common.revision.CDOFeatureDeltaVisitorImpl;
import org.eclipse.emf.cdo.spi.common.revision.DetachedCDORevision;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager;

import org.eclipse.net4j.util.lifecycle.Lifecycle;
import org.eclipse.net4j.util.om.monitor.OMMonitor;
import org.eclipse.net4j.util.om.trace.ContextTracer;

import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * If the meaning of this type isn't clear, there really should be more of a description here...
 *
 * @author Eike Stepper
 * @since 4.0
 */
public abstract class StoreAccessorBase extends Lifecycle implements IStoreAccessor
{
  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, StoreAccessorBase.class);

  // private static int COUNT;

  private Store store;

  private Object context;

  private boolean reader;

  private List<CommitContext> commitContexts = new ArrayList<CommitContext>();

  private StoreAccessorBase(Store store, Object context, boolean reader)
  {
    this.store = store;
    this.context = context;
    this.reader = reader;
  }

  protected StoreAccessorBase(Store store, ISession session)
  {
    this(store, session, true);
  }

  protected StoreAccessorBase(Store store, ITransaction transaction)
  {
    this(store, transaction, false);
  }

  void setContext(Object context)
  {
    this.context = context;
  }

  public Store getStore()
  {
    return store;
  }

  public boolean isReader()
  {
    return reader;
  }

  /**
   * @since 3.0
   */
  public InternalSession getSession()
  {
    if (context instanceof ITransaction)
    {
      return (InternalSession)((ITransaction)context).getSession();
    }

    return (InternalSession)context;
  }

  public ITransaction getTransaction()
  {
    if (context instanceof ITransaction)
    {
      return (ITransaction)context;
    }

    return null;
  }

  public void release()
  {
    store.releaseAccessor(this);
    commitContexts.clear();
  }

  /**
   * @since 3.0
   */
  public final void write(InternalCommitContext context, OMMonitor monitor)
  {
    if (TRACER.isEnabled())
    {
      TRACER.format("Writing transaction: {0}", getTransaction()); //$NON-NLS-1$
    }

    commitContexts.add(context);
    doWrite(context, monitor);
  }

  protected abstract void doWrite(InternalCommitContext context, OMMonitor monitor);

  /**
   * @since 3.0
   */
  public final void commit(OMMonitor monitor)
  {
    doCommit(monitor);

    long latest = CDORevision.UNSPECIFIED_DATE;
    long latestNonLocal = CDORevision.UNSPECIFIED_DATE;
    for (CommitContext commitContext : commitContexts)
    {
      CDOBranchPoint branchPoint = commitContext.getBranchPoint();
      long timeStamp = branchPoint.getTimeStamp();
      if (timeStamp > latest)
      {
        latest = timeStamp;
      }

      CDOBranch branch = branchPoint.getBranch();
      if (!branch.isLocal())
      {
        if (timeStamp > latestNonLocal)
        {
          latestNonLocal = timeStamp;
        }
      }
    }

    store.setLastCommitTime(latest);
    store.setLastNonLocalCommitTime(latestNonLocal);
  }

  /**
   * @since 3.0
   */
  protected abstract void doCommit(OMMonitor monitor);

  public final void rollback()
  {
    if (TRACER.isEnabled())
    {
      TRACER.format("Rolling back transaction: {0}", getTransaction()); //$NON-NLS-1$
    }

    for (CommitContext commitContext : commitContexts)
    {
      doRollback(commitContext);
    }
  }

  protected abstract void doRollback(CommitContext commitContext);

  /**
   * @since 3.0
   */
  public CDOID readResourceID(CDOID folderID, String name, CDOBranchPoint branchPoint)
  {
    QueryResourcesContext.ExactMatch context = Store.createExactMatchContext(folderID, name, branchPoint);
    queryResources(context);
    return context.getResourceID();
  }

  /**
   * @since 3.0
   */
  public CDOCommitData loadCommitData(long timeStamp)
  {
    CommitDataRevisionHandler handler = new CommitDataRevisionHandler(this, timeStamp);
    return handler.getCommitData();
  }

  /**
   * Add ID mappings for all new objects of a transaction to the commit context. The implementor must, for each new
   * object of the commit context, determine a permanent CDOID and make it known to the context by calling
   * {@link InternalCommitContext#addIDMapping(CDOID, CDOID)}.
   *
   * @since 3.0
   */
  public void addIDMappings(InternalCommitContext commitContext, OMMonitor monitor)
  {
    try
    {
      CDORevision[] newObjects = commitContext.getNewObjects();
      monitor.begin(newObjects.length);
      for (CDORevision revision : newObjects)
      {
        CDOID id = revision.getID();
        if (id instanceof CDOIDTemp)
        {
          CDOIDTemp oldID = (CDOIDTemp)id;
          CDOID newID = getNextCDOID(revision);
          if (CDOIDUtil.isNull(newID) || newID.isTemporary())
          {
            throw new IllegalStateException("newID=" + newID); //$NON-NLS-1$
          }

          commitContext.addIDMapping(oldID, newID);
        }

        monitor.worked();
      }
    }
    finally
    {
      monitor.done();
    }
  }

  protected abstract CDOID getNextCDOID(CDORevision revision);

  // @Override
  // protected void doActivate() throws Exception
  // {
  // System.out.println("Active accessors: " + ++COUNT);
  // }
  //
  // @Override
  // protected void doDeactivate() throws Exception
  // {
  // System.out.println("Active accessors: " + --COUNT);
  // }

  protected void doPassivate() throws Exception
  {
  }

  protected void doUnpassivate() throws Exception
  {
  }

  /**
   * If the meaning of this type isn't clear, there really should be more of a description here...
   *
   * @author Eike Stepper
   * @since 3.0
   */
  public static class CommitDataRevisionHandler implements CDORevisionHandler
  {
    private IStoreAccessor storeAccessor;

    private long timeStamp;

    private InternalCDORevisionManager revisionManager;

    private List<CDOPackageUnit> newPackageUnits = new ArrayList<CDOPackageUnit>();

    private List<CDOIDAndVersion> newObjects = new ArrayList<CDOIDAndVersion>();

    private List<CDORevisionKey> changedObjects = new ArrayList<CDORevisionKey>();

    private DetachCounter detachCounter = new DetachCounter();

    public CommitDataRevisionHandler(IStoreAccessor storeAccessor, long timeStamp)
    {
      this.storeAccessor = storeAccessor;
      this.timeStamp = timeStamp;

      InternalStore store = (InternalStore)storeAccessor.getStore();
      InternalRepository repository = store.getRepository();
      revisionManager = repository.getRevisionManager();

      InternalCDOPackageRegistry packageRegistry = repository.getPackageRegistry(false);
      InternalCDOPackageUnit[] packageUnits = packageRegistry.getPackageUnits(timeStamp, timeStamp);
      for (InternalCDOPackageUnit packageUnit : packageUnits)
      {
        if (!packageUnit.isSystem())
        {
          newPackageUnits.add(packageUnit);
        }
      }
    }

    public CDOCommitData getCommitData()
    {
      storeAccessor.handleRevisions(null, null, timeStamp, true, new CDORevisionHandler.Filtered.Undetached(this));

      List<CDOIDAndVersion> detachedObjects = detachCounter.getDetachedObjects();
      return CDOCommitInfoUtil.createCommitData(newPackageUnits, newObjects, changedObjects, detachedObjects);
    }

    /**
     * @since 4.0
     */
    public boolean handleRevision(CDORevision rev)
    {
      if (rev.getTimeStamp() != timeStamp)
      {
        throw new IllegalArgumentException(
            "Invalid revision time stamp: " + CDOCommonUtil.formatTimeStamp(rev.getTimeStamp()));
      }

      if (rev instanceof DetachedCDORevision)
      {
        // Do nothing. Detached objects are handled by detachCounter.
      }
      else
      {
        InternalCDORevision revision = (InternalCDORevision)rev;
        CDOID id = revision.getID();
        CDOBranch branch = revision.getBranch();
        int version = revision.getVersion();
        if (version > CDOBranchVersion.FIRST_VERSION)
        {
          CDOBranchVersion oldVersion = branch.getVersion(version - 1);
          InternalCDORevision oldRevision = revisionManager.getRevisionByVersion(id, oldVersion, CDORevision.UNCHUNKED,
              true);
          InternalCDORevisionDelta delta = revision.compare(oldRevision);
          changedObjects.add(delta);

          detachCounter.update(oldRevision, delta);
        }
        else
        {
          InternalCDORevision oldRevision = getRevisionFromBase(id, branch);
          if (oldRevision != null)
          {
            InternalCDORevisionDelta delta = revision.compare(oldRevision);
            changedObjects.add(delta);
          }
          else
          {
            InternalCDORevision newRevision = revision.copy();
            newRevision.setRevised(CDOBranchPoint.UNSPECIFIED_DATE);
            newObjects.add(newRevision);
          }
        }
      }

      return true;
    }

    private InternalCDORevision getRevisionFromBase(CDOID id, CDOBranch branch)
    {
      if (branch.isMainBranch())
      {
        return null;
      }

      CDOBranchPoint base = branch.getBase();
      InternalCDORevision revision = revisionManager.getRevision(id, base, CDORevision.UNCHUNKED,
          CDORevision.DEPTH_NONE, true);
      if (revision == null)
      {
        revision = getRevisionFromBase(id, base.getBranch());
      }

      return revision;
    }

    /**
     * @author Eike Stepper
     */
    private static final class DetachCounter extends CDOFeatureDeltaVisitorImpl
    {
      private Map<CDOID, AtomicInteger> counters = CDOIDUtil.createMap();

      private InternalCDORevision oldRevision;

      public DetachCounter()
      {
      }

      public void update(InternalCDORevision oldRevision, InternalCDORevisionDelta delta)
      {
        try
        {
          this.oldRevision = oldRevision;
          delta.accept(this);
        }
        finally
        {
          this.oldRevision = null;
        }
      }

      public List<CDOIDAndVersion> getDetachedObjects()
      {
        List<CDOIDAndVersion> result = new ArrayList<CDOIDAndVersion>();
        for (Entry<CDOID, AtomicInteger> entry : counters.entrySet())
        {
          int value = entry.getValue().get();
          if (value == -1)
          {
            CDOID id = entry.getKey();
            result.add(CDOIDUtil.createIDAndVersion(id, CDOBranchVersion.UNSPECIFIED_VERSION));
          }
        }

        return result;
      }

      @Override
      public void visit(CDOAddFeatureDelta delta)
      {
        if (isContainment(delta.getFeature()))
        {
          handleContainment(delta.getValue(), 1);
        }
      }

      @Override
      public void visit(CDORemoveFeatureDelta delta)
      {
        if (isContainment(delta.getFeature()))
        {
          handleContainment(delta.getValue(), -1);
        }
      }

      @Override
      public void visit(CDOSetFeatureDelta delta)
      {
        if (isContainment(delta.getFeature()))
        {
          handleContainment(delta.getValue(), 1);
        }
      }

      @Override
      public void visit(CDOUnsetFeatureDelta delta)
      {
        EStructuralFeature feature = delta.getFeature();
        if (isContainment(feature))
        {
          Object value = oldRevision.getValue(feature);
          handleContainment(value, -1);
        }
      }

      @Override
      public void visit(CDOClearFeatureDelta delta)
      {
        EStructuralFeature feature = delta.getFeature();
        if (isContainment(feature))
        {
          CDOList list = oldRevision.getList(feature);
          for (Object value : list)
          {
            handleContainment(value, -1);
          }
        }
      }

      private void handleContainment(Object value, int delta)
      {
        CDOID id = (CDOID)value;
        AtomicInteger counter = counters.get(id);
        if (counter == null)
        {
          counter = new AtomicInteger();
          counters.put(id, counter);
        }

        counter.addAndGet(delta);
      }

      private static boolean isContainment(EStructuralFeature feature)
      {
        if (feature instanceof EReference)
        {
          EReference reference = (EReference)feature;
          return reference.isContainment();
        }

        return false;
      }
    }
  }
}
