/*
 * Copyright (c) 2010-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
 */
package org.eclipse.emf.cdo.internal.common.commit;

import org.eclipse.emf.cdo.common.commit.CDOChangeKind;
import org.eclipse.emf.cdo.common.commit.CDOChangeSetData;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.id.CDOIDUtil;
import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion;
import org.eclipse.emf.cdo.common.revision.CDORevision;
import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta;
import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
import org.eclipse.emf.cdo.spi.common.commit.CDOChangeKindCache;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta;

import org.eclipse.net4j.util.StringUtil;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * @author Eike Stepper
 */
public class CDOChangeSetDataImpl implements CDOChangeSetData
{
  private List<CDOIDAndVersion> newObjects;

  private List<CDORevisionKey> changedObjects;

  private List<CDOIDAndVersion> detachedObjects;

  private CDOChangeKindCache changeKindCache;

  public CDOChangeSetDataImpl(List<CDOIDAndVersion> newObjects, List<CDORevisionKey> changedObjects,
      List<CDOIDAndVersion> detachedObjects)
  {
    this.newObjects = newObjects;
    this.changedObjects = changedObjects;
    this.detachedObjects = detachedObjects;
  }

  public CDOChangeSetDataImpl()
  {
    this(new ArrayList<CDOIDAndVersion>(), new ArrayList<CDORevisionKey>(), new ArrayList<CDOIDAndVersion>());
  }

  public boolean isEmpty()
  {
    if (newObjects != null && !newObjects.isEmpty())
    {
      return false;
    }

    if (changedObjects != null && !changedObjects.isEmpty())
    {
      return false;
    }

    if (detachedObjects != null && !detachedObjects.isEmpty())
    {
      return false;
    }

    return true;
  }

  public CDOChangeSetData copy()
  {
    List<CDOIDAndVersion> newObjectsCopy = new ArrayList<CDOIDAndVersion>(newObjects.size());
    for (CDOIDAndVersion key : newObjects)
    {
      if (key instanceof CDORevision)
      {
        CDORevision revision = (CDORevision)key;
        newObjectsCopy.add(revision.copy());
      }
      else
      {
        newObjectsCopy.add(key);
      }
    }

    List<CDORevisionKey> changedObjectsCopy = new ArrayList<CDORevisionKey>(changedObjects.size());
    for (CDORevisionKey key : changedObjects)
    {
      if (key instanceof CDORevisionDelta)
      {
        CDORevisionDelta delta = (CDORevisionDelta)key;
        changedObjectsCopy.add(delta.copy());
      }
      else
      {
        changedObjectsCopy.add(key);
      }
    }

    List<CDOIDAndVersion> detachedObjectsCopy = new ArrayList<CDOIDAndVersion>(detachedObjects.size());
    for (CDOIDAndVersion key : detachedObjects)
    {
      detachedObjectsCopy.add(key);
    }

    return new CDOChangeSetDataImpl(newObjectsCopy, changedObjectsCopy, detachedObjectsCopy);
  }

  public void merge(CDOChangeSetData changeSetData)
  {
    Map<CDOID, CDOIDAndVersion> newMap = CDOIDUtil.createMap();
    fillMap(newMap, newObjects);
    fillMap(newMap, changeSetData.getNewObjects());

    Map<CDOID, CDORevisionKey> changedMap = CDOIDUtil.createMap();
    fillMap(changedMap, changedObjects);
    for (CDORevisionKey key : changeSetData.getChangedObjects())
    {
      mergeChangedObject(key, newMap, changedMap);
    }

    Map<CDOID, CDOIDAndVersion> detachedMap = CDOIDUtil.createMap();
    fillMap(detachedMap, detachedObjects);
    for (CDOIDAndVersion key : changeSetData.getDetachedObjects())
    {
      CDOID id = key.getID();
      if (newMap.remove(id) == null)
      {
        detachedMap.put(id, key);
      }
    }

    newObjects = new ArrayList<CDOIDAndVersion>(newMap.values());
    changedObjects = new ArrayList<CDORevisionKey>(changedMap.values());
    detachedObjects = new ArrayList<CDOIDAndVersion>(detachedMap.values());
  }

  private void mergeChangedObject(CDORevisionKey key, Map<CDOID, CDOIDAndVersion> newMap,
      Map<CDOID, CDORevisionKey> changedMap)
  {
    CDOID id = key.getID();
    if (key instanceof CDORevisionDelta)
    {
      CDORevisionDelta delta = (CDORevisionDelta)key;

      // Try to add the delta to existing new revision
      CDOIDAndVersion oldRevision = newMap.get(id);
      if (oldRevision instanceof CDORevision)
      {
        CDORevision newRevision = (CDORevision)oldRevision;
        delta.applyTo(newRevision);
        return;
      }

      // Try to add the delta to existing delta
      CDORevisionKey oldDelta = changedMap.get(id);
      if (oldDelta instanceof CDORevisionDelta)
      {
        InternalCDORevisionDelta newDelta = (InternalCDORevisionDelta)oldDelta;
        for (CDOFeatureDelta featureDelta : delta.getFeatureDeltas())
        {
          newDelta.addFeatureDelta(featureDelta, null);
        }

        return;
      }
    }

    // Fall back
    changedMap.put(id, key);
  }

  public List<CDOIDAndVersion> getNewObjects()
  {
    return newObjects;
  }

  public List<CDORevisionKey> getChangedObjects()
  {
    return changedObjects;
  }

  public List<CDOIDAndVersion> getDetachedObjects()
  {
    return detachedObjects;
  }

  public synchronized Map<CDOID, CDOChangeKind> getChangeKinds()
  {
    if (changeKindCache == null)
    {
      changeKindCache = new CDOChangeKindCache(this);
    }

    return changeKindCache;
  }

  public CDOChangeKind getChangeKind(CDOID id)
  {
    return getChangeKinds().get(id);
  }

  @Override
  public String toString()
  {
    return MessageFormat.format("ChangeSetData[newObjects={0}, changedObjects={1}, detachedObjects={2}]", //$NON-NLS-1$
        newObjects.size(), changedObjects.size(), detachedObjects.size());
  }

  public static String format(CDOChangeSetData changeSetData)
  {
    StringBuilder builder = new StringBuilder();
    builder.append(changeSetData);
    builder.append(StringUtil.NL);

    format(builder, "  New Objects:", changeSetData.getNewObjects());
    format(builder, "  Changed Objects:", changeSetData.getChangedObjects());
    format(builder, "  Detached Objects:", changeSetData.getDetachedObjects());
    return builder.toString();
  }

  private static void format(StringBuilder builder, String label, List<?> objects)
  {
    builder.append(label);
    builder.append(StringUtil.NL);

    for (Object object : objects)
    {
      builder.append("    ");
      builder.append(object);
      builder.append(StringUtil.NL);
    }
  }

  private static <T extends CDOIDAndVersion> void fillMap(Map<CDOID, T> map, Collection<T> c)
  {
    for (T key : c)
    {
      map.put(key.getID(), key);
    }
  }
}
