/*
 * Copyright (c) 2011-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
 *    Simon McDuff - bug 201266
 *    Simon McDuff - bug 230832
 */
package org.eclipse.emf.cdo.internal.common.revision;

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.id.CDOID;
import org.eclipse.emf.cdo.common.revision.CDORevision;
import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
import org.eclipse.emf.cdo.internal.common.bundle.OM;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionCache;

import org.eclipse.net4j.util.CheckUtil;
import org.eclipse.net4j.util.om.trace.ContextTracer;

import org.eclipse.emf.ecore.EClass;

import java.lang.ref.Reference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;

/**
 * @author Eike Stepper
 */
public class CDORevisionCacheAuditing extends AbstractCDORevisionCache
{
  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_REVISION, CDORevisionCacheAuditing.class);

  protected Map<Object, RevisionList> revisionLists = new HashMap<Object, RevisionList>();

  public CDORevisionCacheAuditing()
  {
  }

  public InternalCDORevisionCache instantiate(CDORevision revision)
  {
    return new CDORevisionCacheAuditing();
  }

  public EClass getObjectType(CDOID id)
  {
    synchronized (revisionLists)
    {
      RevisionList revisionList = revisionLists.get(id);
      if (revisionList != null && !revisionList.isEmpty())
      {
        Reference<InternalCDORevision> ref = revisionList.getFirst();
        InternalCDORevision revision = ref.get();
        if (revision != null)
        {
          return revision.getEClass();
        }
      }

      return null;
    }
  }

  public InternalCDORevision getRevision(CDOID id, CDOBranchPoint branchPoint)
  {
    checkBranch(branchPoint.getBranch());

    RevisionList revisionList = getRevisionList(id, branchPoint.getBranch());
    if (revisionList != null)
    {
      return revisionList.getRevision(branchPoint.getTimeStamp());
    }

    return null;
  }

  public InternalCDORevision getRevisionByVersion(CDOID id, CDOBranchVersion branchVersion)
  {
    CDOBranch branch = branchVersion.getBranch();
    checkBranch(branch);

    RevisionList revisionList = getRevisionList(id, branch);
    if (revisionList != null)
    {
      return revisionList.getRevisionByVersion(branchVersion.getVersion());
    }

    return null;
  }

  public List<CDORevision> getCurrentRevisions()
  {
    List<CDORevision> currentRevisions = new ArrayList<CDORevision>();
    synchronized (revisionLists)
    {
      for (RevisionList revisionList : revisionLists.values())
      {
        InternalCDORevision revision = revisionList.getRevision(CDORevision.UNSPECIFIED_DATE);
        if (revision != null)
        {
          currentRevisions.add(revision);
        }
      }
    }

    return currentRevisions;
  }

  public Map<CDOBranch, List<CDORevision>> getAllRevisions()
  {
    Map<CDOBranch, List<CDORevision>> result = new HashMap<CDOBranch, List<CDORevision>>();
    synchronized (revisionLists)
    {
      for (RevisionList list : revisionLists.values())
      {
        list.getAllRevisions(result);
      }
    }

    return result;
  }

  public void getAllRevisions(List<InternalCDORevision> result)
  {
    synchronized (revisionLists)
    {
      for (RevisionList list : revisionLists.values())
      {
        list.getAllRevisions(result);
      }
    }
  }

  public List<CDORevision> getRevisions(CDOBranchPoint branchPoint)
  {
    CDOBranch branch = branchPoint.getBranch();
    checkBranch(branch);

    List<CDORevision> result = new ArrayList<CDORevision>();
    synchronized (revisionLists)
    {
      for (Map.Entry<Object, RevisionList> entry : revisionLists.entrySet())
      {
        if (isKeyInBranch(entry.getKey(), branch))
        {
          RevisionList list = entry.getValue();
          InternalCDORevision revision = list.getRevision(branchPoint.getTimeStamp());
          if (revision != null)
          {
            result.add(revision);
          }
        }
      }
    }

    return result;
  }

  @Override
  protected void doAddRevision(CDORevision revision)
  {
    CheckUtil.checkArg(revision, "revision");

    CDOBranch branch = revision.getBranch();
    checkBranch(branch);

    CDOID id = revision.getID();
    Object key = createKey(id, branch);

    synchronized (revisionLists)
    {
      RevisionList list = revisionLists.get(key);
      if (list == null)
      {
        list = new RevisionList();
        revisionLists.put(key, list);
      }

      if (list.addRevision((InternalCDORevision)revision, createReference(revision)))
      {
        typeRefIncrease(id, revision.getEClass());
      }
    }
  }

  @Override
  protected InternalCDORevision doRemoveRevision(CDOID id, CDOBranchVersion branchVersion)
  {
    CDOBranch branch = branchVersion.getBranch();
    checkBranch(branch);

    Object key = createKey(id, branch);
    synchronized (revisionLists)
    {
      RevisionList list = revisionLists.get(key);
      if (list != null)
      {
        list.removeRevision(branchVersion.getVersion());
        if (list.isEmpty())
        {
          revisionLists.remove(key);
          typeRefDecrease(id);

          if (TRACER.isEnabled())
          {
            TRACER.format("Removed cache list of {0}", key); //$NON-NLS-1$
          }
        }
      }
    }

    return null;
  }

  public void clear()
  {
    synchronized (revisionLists)
    {
      revisionLists.clear();
      typeRefDispose();
    }
  }

  protected void typeRefIncrease(CDOID id, EClass type)
  {
    // Do nothing
  }

  protected void typeRefDecrease(CDOID id)
  {
    // Do nothing
  }

  protected void typeRefDispose()
  {
    // Do nothing
  }

  protected Object createKey(CDOID id, CDOBranch branch)
  {
    return id;
  }

  protected boolean isKeyInBranch(Object key, CDOBranch branch)
  {
    return true;
  }

  protected RevisionList getRevisionList(CDOID id, CDOBranch branch)
  {
    Object key = createKey(id, branch);
    synchronized (revisionLists)
    {
      return revisionLists.get(key);
    }
  }

  /**
   * @author Eike Stepper
   */
  protected static final class RevisionList extends LinkedList<Reference<InternalCDORevision>>
  {
    private static final long serialVersionUID = 1L;

    public RevisionList()
    {
    }

    public synchronized InternalCDORevision getRevision(long timeStamp)
    {
      if (timeStamp == CDORevision.UNSPECIFIED_DATE)
      {
        Reference<InternalCDORevision> ref = isEmpty() ? null : getFirst();
        if (ref != null)
        {
          InternalCDORevision revision = ref.get();
          if (revision != null)
          {
            if (!revision.isHistorical())
            {
              return revision;
            }
          }
          else
          {
            removeFirst();
          }
        }

        return null;
      }

      for (Iterator<Reference<InternalCDORevision>> it = iterator(); it.hasNext();)
      {
        Reference<InternalCDORevision> ref = it.next();
        InternalCDORevision revision = ref.get();
        if (revision != null)
        {
          long created = revision.getTimeStamp();
          if (created <= timeStamp)
          {
            long revised = revision.getRevised();
            if (timeStamp <= revised || revised == CDORevision.UNSPECIFIED_DATE)
            {
              return revision;
            }

            break;
          }
        }
        else
        {
          it.remove();
        }
      }

      return null;
    }

    public synchronized InternalCDORevision getRevisionByVersion(int version)
    {
      for (Iterator<Reference<InternalCDORevision>> it = iterator(); it.hasNext();)
      {
        Reference<InternalCDORevision> ref = it.next();
        InternalCDORevision revision = ref.get();
        if (revision != null)
        {
          int v = revision.getVersion();
          if (v == version)
          {
            return revision;
          }
          else if (v < version)
          {
            break;
          }
        }
        else
        {
          it.remove();
        }
      }

      return null;
    }

    public synchronized boolean addRevision(InternalCDORevision revision, Reference<InternalCDORevision> reference)
    {
      int version = revision.getVersion();
      for (ListIterator<Reference<InternalCDORevision>> it = listIterator(); it.hasNext();)
      {
        Reference<InternalCDORevision> ref = it.next();
        InternalCDORevision foundRevision = ref.get();
        if (foundRevision != null)
        {
          CDORevisionKey key = (CDORevisionKey)ref;
          int v = key.getVersion();
          if (v == version)
          {
            return false;
          }

          if (v < version)
          {
            it.previous();
            it.add(reference);
            return true;
          }
        }
        else
        {
          it.remove();
        }
      }

      addLast(reference);
      return true;
    }

    public synchronized void removeRevision(int version)
    {
      for (Iterator<Reference<InternalCDORevision>> it = iterator(); it.hasNext();)
      {
        Reference<InternalCDORevision> ref = it.next();
        CDORevisionKey key = (CDORevisionKey)ref;
        int v = key.getVersion();
        if (v == version)
        {
          it.remove();
          if (TRACER.isEnabled())
          {
            TRACER.format("Removed version {0} from cache list of {1}", version, key.getID()); //$NON-NLS-1$
          }

          break;
        }
        else if (v < version)
        {
          break;
        }
      }
    }

    @Override
    public String toString()
    {
      StringBuffer buffer = new StringBuffer();
      for (Iterator<Reference<InternalCDORevision>> it = iterator(); it.hasNext();)
      {
        Reference<InternalCDORevision> ref = it.next();
        InternalCDORevision revision = ref.get();
        if (buffer.length() == 0)
        {
          buffer.append("{");
        }
        else
        {
          buffer.append(", ");
        }

        buffer.append(revision);
      }

      buffer.append("}");
      return buffer.toString();
    }

    public void getAllRevisions(Map<CDOBranch, List<CDORevision>> result)
    {
      for (Iterator<Reference<InternalCDORevision>> it = iterator(); it.hasNext();)
      {
        Reference<InternalCDORevision> ref = it.next();
        InternalCDORevision revision = ref.get();
        if (revision != null)
        {
          CDOBranch branch = revision.getBranch();
          List<CDORevision> resultList = result.get(branch);
          if (resultList == null)
          {
            resultList = new ArrayList<CDORevision>(1);
            result.put(branch, resultList);
          }

          resultList.add(revision);
        }
      }
    }

    public void getAllRevisions(List<InternalCDORevision> result)
    {
      for (Iterator<Reference<InternalCDORevision>> it = iterator(); it.hasNext();)
      {
        Reference<InternalCDORevision> ref = it.next();
        InternalCDORevision revision = ref.get();
        if (revision != null)
        {
          result.add(revision);
        }
      }
    }
  }
}
