/*
 * 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:
 *    Caspar De Groot - initial API and implementation
 */
package org.eclipse.emf.internal.cdo.util;

import org.eclipse.emf.cdo.CDOObject;
import org.eclipse.emf.cdo.CDOState;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.id.CDOIDUtil;
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.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.CDORevisionDelta;
import org.eclipse.emf.cdo.common.revision.delta.CDOSetFeatureDelta;
import org.eclipse.emf.cdo.common.revision.delta.CDOUnsetFeatureDelta;
import org.eclipse.emf.cdo.eresource.CDOResource;
import org.eclipse.emf.cdo.spi.common.model.InternalCDOClassInfo;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
import org.eclipse.emf.cdo.util.CDOUtil;
import org.eclipse.emf.cdo.util.CommitIntegrityException;

import org.eclipse.net4j.util.CheckUtil;

import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.spi.cdo.InternalCDOObject;
import org.eclipse.emf.spi.cdo.InternalCDOTransaction;
import org.eclipse.emf.spi.cdo.InternalCDOTransaction.InternalCDOCommitContext;

import java.util.HashSet;
import java.util.Set;

/**
 * @author Caspar De Groot
 * @since 4.0
 */
public class CommitIntegrityCheck
{
  private InternalCDOTransaction transaction;

  private Style style;

  private Set<CDOID> newIDs, dirtyIDs, detachedIDs;

  private Set<CDOObject> missingObjects = new HashSet<CDOObject>();

  private StringBuilder exceptionMessage = new StringBuilder();

  public CommitIntegrityCheck(InternalCDOCommitContext commitContext)
  {
    this(commitContext, Style.EXCEPTION_FAST);
  }

  public CommitIntegrityCheck(InternalCDOCommitContext commitContext, Style style)
  {
    transaction = commitContext.getTransaction();

    CheckUtil.checkArg(style, "style");
    this.style = style;

    newIDs = commitContext.getNewObjects().keySet();
    dirtyIDs = commitContext.getDirtyObjects().keySet();
    detachedIDs = commitContext.getDetachedObjects().keySet();
  }

  public void check() throws CommitIntegrityException
  {
    // For new objects: ensure that their container is included,
    // as well as the targets of the new object's bidi references
    for (CDOID newID : newIDs)
    {
      CDOObject newObject = transaction.getObject(newID);
      checkContainerIncluded(newObject, "new");
      checkCurrentRefTargetsIncluded(newObject, "new");
    }

    // For detached objects: ensure that their former container is included,
    // as well as the targets of the detached object's bidi references
    for (CDOID detachedID : detachedIDs)
    {
      CDOObject detachedObject = transaction.getObject(detachedID);
      checkFormerContainerIncluded(detachedObject);
      checkFormerBidiRefTargetsIncluded(detachedObject, "detached");
    }

    // For dirty objects: if any of the deltas for the object, affect containment (i.e. object was moved)
    // or a bi-di reference, ensure that for containment, both the old and new containers are included,
    // (or that the child is included if we are considering the dirty parent),
    // and that for a bi-di reference, the object holding the other end of the bi-di is included,
    // as well as possibly the *former* object holding the other end.
    for (CDOID dirtyID : dirtyIDs)
    {
      CDOObject dirtyObject = transaction.getObject(dirtyID);
      analyzeRevisionDelta((InternalCDOObject)dirtyObject);
    }

    if (!missingObjects.isEmpty() && style == Style.EXCEPTION)
    {
      throw createException();
    }
  }

  public Set<? extends EObject> getMissingObjects()
  {
    return missingObjects;
  }

  private CDOID getContainerOrResourceID(InternalCDORevision revision)
  {
    CDOID containerOrResourceID = null;
    Object idOrObject = revision.getContainerID();
    if (idOrObject != null)
    {
      containerOrResourceID = (CDOID)transaction.convertObjectToID(idOrObject);
    }

    if (CDOIDUtil.isNull(containerOrResourceID))
    {
      containerOrResourceID = revision.getResourceID();
    }

    return containerOrResourceID;
  }

  private void analyzeRevisionDelta(InternalCDOObject dirtyObject) throws CommitIntegrityException
  {
    // Getting the deltas from the TX is not a good idea...
    // We better recompute a fresh delta:
    InternalCDORevision cleanRev = transaction.getCleanRevisions().get(dirtyObject);
    CheckUtil.checkNull(cleanRev, "Could not obtain clean revision for dirty object " + dirtyObject);

    InternalCDOClassInfo classInfo = dirtyObject.cdoClassInfo();
    InternalCDORevision dirtyRev = dirtyObject.cdoRevision();
    CDORevisionDelta revisionDelta = dirtyRev.compare(cleanRev);

    for (CDOFeatureDelta featureDelta : revisionDelta.getFeatureDeltas())
    {
      EStructuralFeature feature = featureDelta.getFeature();
      if (feature == CDOContainerFeatureDelta.CONTAINER_FEATURE)
      {
        // Three possibilities here:
        // 1. Object's container has changed
        // 2. Object's containment feature has changed
        // 3. Object's resource has changed
        // (or several of the above)

        // @1
        CDOID currentContainerID = (CDOID)transaction.convertObjectToID(dirtyRev.getContainerID());
        CDOID cleanContainerID = (CDOID)transaction.convertObjectToID(cleanRev.getContainerID());
        if (!CDOIDUtil.equals(currentContainerID, cleanContainerID))
        {
          if (currentContainerID != CDOID.NULL)
          {
            checkIncluded(currentContainerID, "container of moved", dirtyObject);
          }

          if (cleanContainerID != CDOID.NULL)
          {
            checkIncluded(cleanContainerID, "former container of moved", dirtyObject);
          }
        }

        // @2
        // Nothing to be done. (I think...)

        // @3
        CDOID currentResourceID = dirtyRev.getResourceID();
        CDOID cleanResourceID = cleanRev.getResourceID();
        if (!CDOIDUtil.equals(currentResourceID, cleanResourceID))
        {
          if (currentResourceID != CDOID.NULL)
          {
            checkIncluded(currentResourceID, "resource of moved", dirtyObject);
          }

          if (cleanResourceID != CDOID.NULL)
          {
            checkIncluded(cleanResourceID, "former resource of moved", dirtyObject);
          }
        }
      }
      else if (feature instanceof EReference)
      {
        if (featureDelta instanceof CDOListFeatureDelta)
        {
          boolean hasPersistentOpposite = classInfo.hasPersistentOpposite(feature);
          for (CDOFeatureDelta innerFeatDelta : ((CDOListFeatureDelta)featureDelta).getListChanges())
          {
            checkFeatureDelta(innerFeatDelta, hasPersistentOpposite, dirtyObject);
          }
        }
        else
        {
          boolean hasPersistentOpposite = classInfo.hasPersistentOpposite(feature);
          checkFeatureDelta(featureDelta, hasPersistentOpposite, dirtyObject);
        }
      }
    }
  }

  private void checkIncluded(Object idOrObject, String msg, CDOObject o) throws CommitIntegrityException
  {
    idOrObject = transaction.convertObjectToID(idOrObject);
    if (idOrObject instanceof CDOID)
    {
      CDOID id = (CDOID)idOrObject;
      if (!id.isNull())
      {
        checkIncluded(id, msg, o);
      }
    }

    // else: Transient object -- ignore
  }

  private void checkFeatureDelta(CDOFeatureDelta featureDelta, boolean hasPersistentOpposite, CDOObject dirtyObject)
      throws CommitIntegrityException
  {
    EReference ref = (EReference)featureDelta.getFeature();
    boolean containmentOrWithOpposite = ref.isContainment() || hasPersistentOpposite;

    if (featureDelta instanceof CDOAddFeatureDelta)
    {
      Object idOrObject = ((CDOAddFeatureDelta)featureDelta).getValue();
      if (containmentOrWithOpposite || isNew(idOrObject))
      {
        checkIncluded(idOrObject, "added child / refTarget of", dirtyObject);
      }
    }
    else if (featureDelta instanceof CDOSetFeatureDelta)
    {
      Object oldIDOrObject = ((CDOSetFeatureDelta)featureDelta).getOldValue();
      CDOID oldID = (CDOID)transaction.convertObjectToID(oldIDOrObject);
      if (!CDOIDUtil.isNull(oldID))
      {
        // Old child must be included if it's the container or has an eOpposite
        if (containmentOrWithOpposite)
        {
          checkIncluded(oldID, "removed / former child / refTarget of", dirtyObject);
        }
      }

      Object newIDOrObject = ((CDOSetFeatureDelta)featureDelta).getValue();
      if (newIDOrObject != null)
      {
        // New child must be included
        newIDOrObject = transaction.convertObjectToID(newIDOrObject);
        if (containmentOrWithOpposite || isNew(newIDOrObject))
        {
          checkIncluded(newIDOrObject, "new child / refTarget of", dirtyObject);
        }
      }
    }
    else if (containmentOrWithOpposite)
    {
      if (featureDelta instanceof CDORemoveFeatureDelta)
      {
        Object idOrObject = ((CDORemoveFeatureDelta)featureDelta).getValue();
        CDOID id = (CDOID)transaction.convertObjectToID(idOrObject);
        checkIncluded(id, "removed child / refTarget of", dirtyObject);
      }
      else if (featureDelta instanceof CDOClearFeatureDelta)
      {
        EStructuralFeature feat = ((CDOClearFeatureDelta)featureDelta).getFeature();
        InternalCDORevision cleanRev = transaction.getCleanRevisions().get(dirtyObject);
        int n = cleanRev.size(feat);
        for (int i = 0; i < n; i++)
        {
          Object idOrObject = cleanRev.get(feat, i);
          CDOID id = (CDOID)transaction.convertObjectToID(idOrObject);
          checkIncluded(id, "removed child / refTarget of", dirtyObject);
        }
      }
      else if (featureDelta instanceof CDOUnsetFeatureDelta)
      {
        EStructuralFeature feat = ((CDOUnsetFeatureDelta)featureDelta).getFeature();
        InternalCDORevision cleanRev = transaction.getCleanRevisions().get(dirtyObject);
        Object idOrObject = cleanRev.getValue(feat);
        CDOID id = (CDOID)transaction.convertObjectToID(idOrObject);
        checkIncluded(id, "removed child / refTarget of", dirtyObject);
      }
      else if (featureDelta instanceof CDOMoveFeatureDelta)
      {
        // Nothing to do: a move doesn't affect the child being moved
        // so that child does not need to be included
      }
      else
      {
        throw new IllegalArgumentException("Unexpected delta type: " + featureDelta.getClass().getSimpleName());
      }
    }
  }

  private boolean isNew(Object idOrObject)
  {
    CDOObject object = null;
    if (idOrObject instanceof CDOObject)
    {
      object = (CDOObject)idOrObject;
    }
    else if (idOrObject instanceof EObject)
    {
      object = CDOUtil.getCDOObject((EObject)idOrObject);
    }
    else if (idOrObject instanceof CDOID)
    {
      object = transaction.getObject((CDOID)idOrObject);
    }

    if (object != null)
    {
      return object.cdoState() == CDOState.NEW;
    }

    return false;
  }

  private void checkIncluded(CDOID id, String msg, CDOObject o) throws CommitIntegrityException
  {
    if (id.isNull())
    {
      throw new IllegalArgumentException("CDOID must not be NULL");
    }

    if (!dirtyIDs.contains(id) && !detachedIDs.contains(id) && !newIDs.contains(id))
    {
      CDOObject missingObject = transaction.getObject(id);
      if (missingObject == null)
      {
        throw new IllegalStateException("Could not find object for CDOID " + id);
      }

      missingObjects.add(missingObject);

      if (exceptionMessage.length() > 0)
      {
        exceptionMessage.append('\n');
      }

      String m = String.format("The %s object %s needs to be included in the commit but isn't", msg, o);
      exceptionMessage.append(m);

      if (style == Style.EXCEPTION_FAST)
      {
        throw createException();
      }
    }
  }

  private CommitIntegrityException createException()
  {
    return new CommitIntegrityException(exceptionMessage.toString(), missingObjects);
  }

  /**
   * Checks whether the container of a given object is included in the commit
   */
  private void checkContainerIncluded(CDOObject object, String msgFrag) throws CommitIntegrityException
  {
    EObject eContainer = object.eContainer();
    if (eContainer == null)
    {
      // It's a top-level object
      CDOResource resource = object.cdoDirectResource();
      checkIncluded(resource.cdoID(), "resource of " + msgFrag, object);
    }
    else
    {
      CDOObject container = CDOUtil.getCDOObject(eContainer);
      checkIncluded(container.cdoID(), "container of " + msgFrag, object);
    }
  }

  private void checkCurrentRefTargetsIncluded(CDOObject referencer, String msgFrag) throws CommitIntegrityException
  {
    InternalCDOClassInfo classInfo = ((InternalCDOObject)referencer).cdoClassInfo();

    for (EReference reference : classInfo.getAllPersistentReferences())
    {
      if (reference.isMany())
      {
        EList<?> list = (EList<?>)referencer.eGet(reference);
        if (!list.isEmpty())
        {
          boolean hasPersistentOpposite = classInfo.hasPersistentOpposite(reference);
          for (Object refTarget : list)
          {
            checkBidiRefTargetOrNewNonBidiTargetIncluded(referencer, reference, refTarget, hasPersistentOpposite,
                msgFrag);
          }
        }
      }
      else
      {
        Object refTarget = referencer.eGet(reference);
        if (refTarget != null)
        {
          boolean hasPersistentOpposite = classInfo.hasPersistentOpposite(reference);
          checkBidiRefTargetOrNewNonBidiTargetIncluded(referencer, reference, refTarget, hasPersistentOpposite,
              msgFrag);
        }
      }
    }
  }

  private void checkBidiRefTargetOrNewNonBidiTargetIncluded(CDOObject referencer, EReference eRef, Object refTarget,
      boolean hasPersistentOpposite, String msgFrag) throws CommitIntegrityException
  {
    if (hasPersistentOpposite)
    {
      // It's a bi-di ref; the target must definitely be included
      checkBidiRefTargetIncluded(refTarget, referencer, eRef.getName(), msgFrag);
    }
    else if (isNew(refTarget))
    {
      // It's a non-bidi ref; the target doesn't have to be included unless it's NEW
      checkIncluded(refTarget, "target of reference '" + eRef.getName() + "' of " + msgFrag, referencer);
    }
  }

  private void checkFormerBidiRefTargetsIncluded(CDOObject referencer, String msgFrag) throws CommitIntegrityException
  {
    // The referencer argument should really be a detached object, and so we know
    // that we can find the pre-detach revision in tx.getFormerRevisions(). However,
    // the object may have already been dirty prior to detachment, so we check the
    // clean revisions first.
    InternalCDORevision cleanRev = transaction.getCleanRevisions().get(referencer);
    CheckUtil.checkState(cleanRev, "cleanRev");

    InternalCDOClassInfo referencerClassInfo = ((InternalCDOObject)referencer).cdoClassInfo();
    for (EReference reference : referencerClassInfo.getAllPersistentReferences())
    {
      if (referencerClassInfo.hasPersistentOpposite(reference))
      {
        if (reference.isMany())
        {
          EList<?> list = cleanRev.getList(reference);
          if (list != null)
          {
            for (Object element : list)
            {
              checkBidiRefTargetIncluded(element, referencer, reference.getName(), msgFrag);
            }
          }
        }
        else
        {
          Object value = cleanRev.getValue(reference);
          if (value != null)
          {
            checkBidiRefTargetIncluded(value, referencer, reference.getName(), msgFrag);
          }
        }
      }
    }
  }

  private void checkBidiRefTargetIncluded(Object refTarget, CDOObject referencer, String refName, String msgFrag)
      throws CommitIntegrityException
  {
    CheckUtil.checkArg(refTarget, "refTarget");
    CDOID refTargetID = null;
    if (refTarget instanceof EObject)
    {
      refTargetID = CDOUtil.getCDOObject((EObject)refTarget).cdoID();
      if (refTargetID == null)
      {
        // No ID, means object is TRANSIENT; ignore.
        return;
      }
    }
    else if (refTarget instanceof CDOID)
    {
      refTargetID = (CDOID)refTarget;
    }

    checkIncluded(refTargetID, "target of reference '" + refName + "' of " + msgFrag, referencer);
  }

  private void checkFormerContainerIncluded(CDOObject detachedObject) throws CommitIntegrityException
  {
    InternalCDORevision rev = transaction.getCleanRevisions().get(detachedObject);
    CheckUtil.checkNull(rev, "Could not obtain clean revision for detached object " + detachedObject);

    CDOID id = getContainerOrResourceID(rev);
    checkIncluded(id, "former container (or resource) of detached", detachedObject);
  }

  /**
   * Designates an exception style for a {@link CommitIntegrityCheck}
   *
   * @author Caspar De Groot
   */
  public static enum Style
  {
    /**
     * Throw an exception as soon as this {@link CommitIntegrityCheck} encounters the first problem
     */
    EXCEPTION_FAST,

    /**
     * Throw an exception when this {@link CommitIntegrityCheck} finishes performing all possible checks, in case any
     * problems were found
     */
    EXCEPTION,

    /**
     * Do not throw an exception. Caller must invoke {@link CommitIntegrityCheck#getMissingObjects()} to find out if the
     * check discovered any problems.
     */
    NO_EXCEPTION
  }
}
