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

import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.id.CDOIDUtil;
import org.eclipse.emf.cdo.common.model.CDOClassInfo;
import org.eclipse.emf.cdo.common.protocol.CDODataInput;
import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants;
import org.eclipse.emf.cdo.common.revision.CDORevision;
import org.eclipse.emf.cdo.common.util.CDOFetchRule;
import org.eclipse.emf.cdo.server.internal.net4j.bundle.OM;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager;
import org.eclipse.emf.cdo.spi.common.revision.RevisionInfo;
import org.eclipse.emf.cdo.spi.common.revision.RevisionInfo.Type;

import org.eclipse.net4j.util.collection.MoveableList;
import org.eclipse.net4j.util.om.trace.ContextTracer;

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

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author Eike Stepper
 */
public class LoadRevisionsIndication extends CDOServerReadIndication
{
  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_PROTOCOL, LoadRevisionsIndication.class);

  private RevisionInfo[] infos;

  private CDOBranchPoint branchPoint;

  private int referenceChunk;

  private int prefetchDepth;

  private Map<EClass, CDOFetchRule> fetchRules = new HashMap<EClass, CDOFetchRule>();

  private CDOID contextID = CDOID.NULL;

  private int loadRevisionCollectionChunkSize;

  public LoadRevisionsIndication(CDOServerProtocol protocol)
  {
    super(protocol, CDOProtocolConstants.SIGNAL_LOAD_REVISIONS);
  }

  @Override
  protected void indicating(CDODataInput in) throws IOException
  {
    branchPoint = in.readCDOBranchPoint();
    if (TRACER.isEnabled())
    {
      TRACER.format("Read branchPoint: {0}", branchPoint); //$NON-NLS-1$
    }

    referenceChunk = in.readInt();
    if (TRACER.isEnabled())
    {
      TRACER.format("Read referenceChunk: {0}", referenceChunk); //$NON-NLS-1$
    }

    int size = in.readInt();
    if (size < 0)
    {
      size = -size;
      prefetchDepth = in.readInt();
      if (TRACER.isEnabled())
      {
        TRACER.format("Read prefetchDepth: {0}", prefetchDepth); //$NON-NLS-1$
      }
    }

    if (TRACER.isEnabled())
    {
      TRACER.format("Reading {0} infos", size); //$NON-NLS-1$
    }

    infos = new RevisionInfo[size];
    for (int i = 0; i < size; i++)
    {
      RevisionInfo info = RevisionInfo.read(in, branchPoint);
      if (TRACER.isEnabled())
      {
        TRACER.format("Read info: {0}", info); //$NON-NLS-1$
      }

      infos[i] = info;
    }

    int fetchSize = in.readInt();
    if (fetchSize > 0)
    {
      loadRevisionCollectionChunkSize = in.readInt();
      if (loadRevisionCollectionChunkSize < 1)
      {
        loadRevisionCollectionChunkSize = 1;
      }

      contextID = in.readCDOID();
      if (TRACER.isEnabled())
      {
        TRACER.format("Reading fetch rules for context {0}", contextID); //$NON-NLS-1$
      }

      for (int i = 0; i < fetchSize; i++)
      {
        CDOFetchRule fetchRule = new CDOFetchRule(in, getRepository().getPackageRegistry());
        fetchRules.put(fetchRule.getEClass(), fetchRule);
      }
    }
  }

  @Override
  protected void responding(CDODataOutput out) throws IOException
  {
    List<CDORevision> additionalRevisions = new ArrayList<CDORevision>();
    List<RevisionInfo> additionalRevisionInfos = new ArrayList<RevisionInfo>();
    Set<CDOID> revisionIDs = new HashSet<CDOID>();
    int size = infos.length;
    if (TRACER.isEnabled())
    {
      TRACER.format("Writing {0} results", size); //$NON-NLS-1$
    }

    for (RevisionInfo info : infos)
    {
      revisionIDs.add(info.getID());
    }

    // Need to fetch the rule first.
    Set<CDOFetchRule> visitedFetchRules = new HashSet<CDOFetchRule>();
    if (!CDOIDUtil.isNull(contextID) && fetchRules.size() > 0)
    {
      if (TRACER.isEnabled())
      {
        TRACER.format("Collecting more revisions based on rules"); //$NON-NLS-1$
      }

      RevisionInfo info = getRevisionInfo(contextID);
      InternalCDORevision revisionContext = info.getResult();
      collectRevisions(revisionContext, revisionIDs, additionalRevisionInfos, additionalRevisions, visitedFetchRules);
    }

    InternalCDORevisionManager revisionManager = getRepository().getRevisionManager();
    InternalCDORevision[] revisions = new InternalCDORevision[size];
    for (int i = 0; i < size; i++)
    {
      RevisionInfo info = infos[i];
      info.execute(revisionManager, referenceChunk);
      revisions[i] = info.getResult();
      if (loadRevisionCollectionChunkSize > 0)
      {
        collectRevisions(revisions[i], revisionIDs, additionalRevisionInfos, additionalRevisions, visitedFetchRules);
      }
    }

    if (prefetchDepth != 0)
    {
      prefetchRevisions(prefetchDepth > 0 ? prefetchDepth : Integer.MAX_VALUE, revisions, additionalRevisionInfos,
          additionalRevisions);
    }

    getRepository().notifyReadAccessHandlers(getSession(), revisions, additionalRevisions);

    for (int i = 0; i < size; i++)
    {
      RevisionInfo info = infos[i];
      info.setResult(revisions[i]);
      info.writeResult(out, referenceChunk, branchPoint); // Exposes revision to client side
    }

    int additionalSize = additionalRevisionInfos.size();
    if (TRACER.isEnabled())
    {
      TRACER.format("Writing {0} additional revision infos", additionalSize); //$NON-NLS-1$
    }

    out.writeInt(additionalSize);
    for (int i = 0; i < additionalSize; i++)
    {
      InternalCDORevision revision = (InternalCDORevision)additionalRevisions.get(i);
      RevisionInfo info = additionalRevisionInfos.get(i);
      info.setResult(revision);
      out.write(Type.MISSING.ordinal());
      out.writeCDOID(info.getID());
      info.writeResult(out, referenceChunk, branchPoint);
    }
  }

  private RevisionInfo getRevisionInfo(CDOID id)
  {
    RevisionInfo info = new RevisionInfo.Missing(id, branchPoint);
    info.execute(getRepository().getRevisionManager(), referenceChunk);
    return info;
  }

  private void collectRevisions(InternalCDORevision revision, Set<CDOID> revisions,
      List<RevisionInfo> additionalRevisionInfos, List<CDORevision> additionalRevisions,
      Set<CDOFetchRule> visitedFetchRules)
  {
    if (revision == null)
    {
      return;
    }

    getSession().collectContainedRevisions(revision, branchPoint, referenceChunk, revisions, additionalRevisions);

    CDOFetchRule fetchRule = fetchRules.get(revision.getEClass());
    if (fetchRule == null || visitedFetchRules.contains(fetchRule))
    {
      return;
    }

    visitedFetchRules.add(fetchRule);

    for (EStructuralFeature feature : fetchRule.getFeatures())
    {
      if (feature.isMany())
      {
        MoveableList<Object> list = revision.getList(feature);
        int toIndex = Math.min(loadRevisionCollectionChunkSize, list.size()) - 1;
        for (int i = 0; i <= toIndex; i++)
        {
          Object value = list.get(i);
          if (value instanceof CDOID)
          {
            CDOID id = (CDOID)value;
            if (!CDOIDUtil.isNull(id) && !revisions.contains(id))
            {
              RevisionInfo info = getRevisionInfo(id);
              InternalCDORevision containedRevision = info.getResult();
              if (containedRevision != null)
              {
                additionalRevisionInfos.add(info);
                revisions.add(containedRevision.getID());
                additionalRevisions.add(containedRevision);
                collectRevisions(containedRevision, revisions, additionalRevisionInfos, additionalRevisions,
                    visitedFetchRules);
              }
            }
          }
        }
      }
      else
      {
        Object value = revision.getValue(feature);
        if (value instanceof CDOID)
        {
          CDOID id = (CDOID)value;
          if (!id.isNull() && !revisions.contains(id))
          {
            RevisionInfo info = getRevisionInfo(id);
            InternalCDORevision containedRevision = info.getResult();
            if (containedRevision != null)
            {
              revisions.add(containedRevision.getID());
              additionalRevisions.add(containedRevision);
              collectRevisions(containedRevision, revisions, additionalRevisionInfos, additionalRevisions,
                  visitedFetchRules);
            }
          }
        }
      }
    }

    visitedFetchRules.remove(fetchRule);
  }

  private void prefetchRevisions(int depth, CDORevision[] revisions, List<RevisionInfo> additionalRevisionInfos,
      List<CDORevision> additionalRevisions)
  {
    Map<CDOID, CDORevision> map = CDOIDUtil.createMap();
    for (CDORevision revision : revisions)
    {
      map.put(revision.getID(), revision);
    }

    for (CDORevision revision : additionalRevisions)
    {
      map.put(revision.getID(), revision);
    }

    for (CDORevision revision : revisions)
    {
      prefetchRevision(depth, (InternalCDORevision)revision, additionalRevisionInfos, additionalRevisions, map);
    }
  }

  private void prefetchRevision(int depth, InternalCDORevision revision, List<RevisionInfo> additionalRevisionInfos,
      List<CDORevision> additionalRevisions, Map<CDOID, CDORevision> map)
  {
    CDOClassInfo classInfo = revision.getClassInfo();
    for (EStructuralFeature feature : classInfo.getAllPersistentFeatures())
    {
      if (feature instanceof EReference)
      {
        EReference reference = (EReference)feature;
        if (reference.isContainment())
        {
          Object value = revision.getValue(reference);
          if (value instanceof CDOID)
          {
            CDOID id = (CDOID)value;
            prefetchRevisionChild(depth, id, additionalRevisionInfos, additionalRevisions, map);
          }
          else if (value instanceof Collection<?>)
          {
            Collection<?> c = (Collection<?>)value;
            for (Object e : c)
            {
              // If this revision was loaded with referenceChunk != UNCHUNKED, then
              // some elements might be uninitialized, i.e. not instanceof CDOID.
              // (See bug 339313.)
              if (e instanceof CDOID)
              {
                CDOID id = (CDOID)e;
                prefetchRevisionChild(depth, id, additionalRevisionInfos, additionalRevisions, map);
              }
            }
          }
        }
      }
    }
  }

  private void prefetchRevisionChild(int depth, CDOID id, List<RevisionInfo> additionalRevisionInfos,
      List<CDORevision> additionalRevisions, Map<CDOID, CDORevision> map)
  {
    if (CDOIDUtil.isNull(id))
    {
      return;
    }

    CDORevision child = map.get(id);
    if (child == null)
    {
      RevisionInfo info = getRevisionInfo(id);
      child = info.getResult();
      if (child != null)
      {
        map.put(id, child);
        additionalRevisions.add(child);
        additionalRevisionInfos.add(info);
      }
    }

    if (child != null && depth > 0)
    {
      prefetchRevision(depth - 1, (InternalCDORevision)child, additionalRevisionInfos, additionalRevisions, map);
    }
  }

}
