/*
 * Copyright (c) 2007-2012, 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:
 *    Simon McDuff - initial API and implementation
 *    Eike Stepper - maintenance
 */
package org.eclipse.emf.cdo.tests;

import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.revision.CDORevision;
import org.eclipse.emf.cdo.common.revision.CDORevisionUtil;
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.CDOListFeatureDelta;
import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
import org.eclipse.emf.cdo.common.revision.delta.CDOSetFeatureDelta;
import org.eclipse.emf.cdo.eresource.CDOResource;
import org.eclipse.emf.cdo.internal.common.revision.delta.CDOListFeatureDeltaImpl;
import org.eclipse.emf.cdo.internal.server.mem.MEMStore;
import org.eclipse.emf.cdo.server.IStore;
import org.eclipse.emf.cdo.session.CDOSession;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager;
import org.eclipse.emf.cdo.tests.model1.Category;
import org.eclipse.emf.cdo.tests.model1.Company;
import org.eclipse.emf.cdo.tests.model1.Customer;
import org.eclipse.emf.cdo.tests.model1.SalesOrder;
import org.eclipse.emf.cdo.tests.model3.NodeD;
import org.eclipse.emf.cdo.transaction.CDOTransaction;
import org.eclipse.emf.cdo.util.CDOUtil;
import org.eclipse.emf.cdo.util.CommitException;
import org.eclipse.emf.cdo.view.CDOView;

import org.eclipse.net4j.util.WrappedException;
import org.eclipse.net4j.util.io.IOUtil;

import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.spi.cdo.InternalCDOTransaction;

/**
 * See bug 201266
 *
 * @author Simon McDuff
 */
public class RevisionDeltaTest extends AbstractCDOTest
{
  public RevisionDeltaTest()
  {
  }

  public void testBasicRevisionDelta() throws Exception
  {
    CDOSession session = openSession();
    CDOTransaction transaction = session.openTransaction();
    CDOResource resource1 = transaction.createResource(getResourcePath("/test1"));

    Company company1 = getModel1Factory().createCompany();
    Category category1 = getModel1Factory().createCategory();

    resource1.getContents().add(company1);
    company1.getCategories().add(category1);

    company1.setName("TEST");
    InternalCDORevision rev1 = getCopyCDORevision(company1);

    // Test simple attributes
    company1.setName("TEST3");
    InternalCDORevision rev2 = getCopyCDORevision(company1);

    CDORevisionDelta revisionDelta = rev2.compare(rev1);
    assertEquals(1, revisionDelta.getFeatureDeltas().size());
    CDOSetFeatureDelta setDelta = (CDOSetFeatureDelta)revisionDelta.getFeatureDeltas().get(0);
    assertEquals("TEST3", setDelta.getValue());

    // Test List clear
    company1.getCategories().clear();
    InternalCDORevision rev3 = getCopyCDORevision(company1);

    CDORevisionDelta revisionDelta3 = rev3.compare(rev2);
    assertEquals(1, revisionDelta3.getFeatureDeltas().size());
    CDOListFeatureDeltaImpl delta3List = (CDOListFeatureDeltaImpl)revisionDelta3.getFeatureDeltas().get(0);

    assertEquals(1, delta3List.getListChanges().size());
    assertEquals(true, delta3List.getListChanges().get(0) instanceof CDOClearFeatureDelta);

    // Test List Add
    for (int i = 0; i < 5; i++)
    {
      Category category = getModel1Factory().createCategory();
      company1.getCategories().add(category);
    }

    InternalCDORevision rev4 = getCopyCDORevision(company1);

    CDORevisionDelta revisionDelta4 = rev4.compare(rev3);
    assertEquals(1, revisionDelta4.getFeatureDeltas().size());
    CDOListFeatureDeltaImpl delta4List = (CDOListFeatureDeltaImpl)revisionDelta4.getFeatureDeltas().get(0);

    assertEquals(5, delta4List.getListChanges().size());
    assertEquals(true, delta4List.getListChanges().get(0) instanceof CDOAddFeatureDelta);
    transaction.rollback();
    transaction.close();
    session.close();
  }

  /**
   * Sending deltas doesn't adjust CDOIDs
   * <p>
   * See bug 214374
   */
  public void testBugzilla214374() throws Exception
  {
    CDOSession session = openSession();
    CDOTransaction transaction = session.openTransaction();
    CDOResource resource = transaction.createResource(getResourcePath("/test1"));

    SalesOrder salesOrder = getModel1Factory().createSalesOrder();
    resource.getContents().add(salesOrder);
    transaction.commit();

    Customer customer = getModel1Factory().createCustomer();
    salesOrder.setCustomer(customer);

    resource.getContents().add(customer);
    transaction.commit();
    transaction.close();

    CDOTransaction transaction2 = session.openTransaction();
    SalesOrder salesOrder2 = (SalesOrder)CDOUtil
        .getEObject(transaction2.getObject(CDOUtil.getCDOObject(salesOrder).cdoID(), true));
    CDORevision salesRevision = CDOUtil.getCDOObject(salesOrder2).cdoRevision();
    EStructuralFeature customerFeature = getModel1Package().getSalesOrder_Customer();

    Object value = salesRevision.data().get(customerFeature, 0);
    assertEquals(true, value instanceof CDOID);
    transaction2.close();
    session.close();
  }

  /**
   * CDOView.getRevision() does not work for transactions/dirty objects (INVALID)
   * <p>
   * See bug 214431
   */
  public void testBugzilla214431() throws Exception
  {
    CDOSession session = openSession();
    CDOTransaction transaction = session.openTransaction();
    CDOResource resource = transaction.createResource(getResourcePath("/test1"));

    SalesOrder salesOrder = getModel1Factory().createSalesOrder();
    resource.getContents().add(salesOrder);
    transaction.commit();

    salesOrder.setId(4711);
    assertNotSame(CDOUtil.getCDOObject(salesOrder).cdoRevision(),
        ((InternalCDOTransaction)transaction).getRevision(CDOUtil.getCDOObject(salesOrder).cdoID(), true));
    assertEquals(CDOUtil.getCDOObject(salesOrder).cdoRevision(),
        transaction.getDirtyObjects().get(CDOUtil.getCDOObject(salesOrder).cdoID()).cdoRevision());
    transaction.close();
    session.close();
  }

  /**
   * CDOView.getRevision() does not work for transactions/dirty objects (INVALID)
   * <p>
   * See bug 214374
   */
  public void testBugzilla214374_HandleClear() throws Exception
  {
    CDOSession session = openSession();
    CDOTransaction transaction = session.openTransaction();
    CDOResource resource = transaction.createResource(getResourcePath("/test1"));

    Customer customer = getModel1Factory().createCustomer();
    resource.getContents().add(customer);

    SalesOrder salesOrder = getModel1Factory().createSalesOrder();
    resource.getContents().add(salesOrder);
    customer.getSalesOrders().add(salesOrder);
    customer.getSalesOrders().add(salesOrder);
    transaction.commit();

    salesOrder = getModel1Factory().createSalesOrder();
    customer = getModel1Factory().createCustomer();
    resource.getContents().add(salesOrder);
    resource.getContents().add(customer);
    salesOrder.setCustomer(customer);
    transaction.commit();
    transaction.close();
    session.close();
  }

  /**
   * java.lang.IllegalStateException with MEMStore
   * <p>
   * See bug 243282
   */
  public void testBugzilla243282_Exception() throws Exception
  {
    CDOSession session = openSession();
    CDOTransaction transaction = session.openTransaction();
    CDOResource resource = transaction.createResource(getResourcePath("/test1"));

    Customer customer = getModel1Factory().createCustomer();
    resource.getContents().add(customer);

    transaction.commit();

    InternalCDORevisionManager revisionManager = getRepository().getRevisionManager();
    CDORevision revision = CDOUtil.getCDOObject(customer).cdoRevision();
    revisionManager.getCache().removeRevision(revision.getID(), revision);

    SalesOrder salesOrder = getModel1Factory().createSalesOrder();
    resource.getContents().add(salesOrder);
    customer.getSalesOrders().add(salesOrder);

    IStore store = getRepository().getStore();
    if (store instanceof MEMStore)
    {
      MEMStore memStore = (MEMStore)store;
      CDORevisionUtil.dumpAllRevisions(memStore.getAllRevisions(), IOUtil.OUT());
    }

    transaction.commit();
    transaction.close();
    session.close();
  }

  @SuppressWarnings("unused")
  public void testDetachWithXRef() throws Exception
  {
    CDOSession session = openSession();
    CDOTransaction transaction = session.openTransaction();
    CDOResource resource = transaction.createResource(getResourcePath("/test1"));

    NodeD a = getModel3Factory().createNodeD();
    NodeD b = getModel3Factory().createNodeD();
    NodeD c = getModel3Factory().createNodeD();

    a.getChildren().add(b);
    c.getOtherNodes().add(b);

    resource.getContents().add(a);
    resource.getContents().add(c);

    if (true)
    {
      transaction.commit();
      transaction.close();
      transaction = session.openTransaction();
      resource = transaction.getResource(getResourcePath("/test1"));
    }

    // Start test logic

    a = (NodeD)resource.getContents().get(0);
    b = a.getChildren().get(0);
    c = (NodeD)resource.getContents().get(1);

    a.getChildren().remove(0);
    Object[] cB = c.getOtherNodes().toArray();

    CDORevisionDelta aDelta = transaction.getRevisionDeltas().get(CDOUtil.getCDOObject(a).cdoID());
    CDORevisionDelta cDelta = transaction.getRevisionDeltas().get(CDOUtil.getCDOObject(c).cdoID());

    session.close();
  }

  @SuppressWarnings("unused")
  public void testDetachWithXRef_Remove() throws Exception
  {
    CDOSession session = openSession();
    CDOTransaction transaction = session.openTransaction();
    CDOResource resource = transaction.createResource(getResourcePath("/test1"));

    NodeD a = getModel3Factory().createNodeD();
    NodeD b = getModel3Factory().createNodeD();
    NodeD c = getModel3Factory().createNodeD();

    a.getChildren().add(b);
    c.getOtherNodes().add(b);

    resource.getContents().add(a);
    resource.getContents().add(c);

    if (true)
    {
      transaction.commit();
      transaction.close();
      transaction = session.openTransaction();
      resource = transaction.getResource(getResourcePath("/test1"));
    }

    // Start test logic

    a = (NodeD)resource.getContents().get(0);
    b = a.getChildren().get(0);
    c = (NodeD)resource.getContents().get(1);

    a.getChildren().remove(0);
    c.getOtherNodes().remove(0);

    Object[] cB = c.getOtherNodes().toArray();

    CDORevisionDelta aDelta = transaction.getRevisionDeltas().get(CDOUtil.getCDOObject(a).cdoID());
    CDORevisionDelta cDelta = transaction.getRevisionDeltas().get(CDOUtil.getCDOObject(c).cdoID());

    CDOListFeatureDelta list = (CDOListFeatureDelta)cDelta.getFeatureDelta(getModel3Package().getNodeD_OtherNodes());
    assertEquals(1, list.getListChanges().size());

    session.close();
  }

  public void testListRemoveMiddle()
  {
    testStoreDelta(new ListManipulator()
    {
      public void doManipulations(EList<?> list)
      {
        list.remove(5);
      }
    });
  }

  public void testListRemoveLast()
  {
    testStoreDelta(new ListManipulator()
    {
      public void doManipulations(EList<?> list)
      {
        list.remove(list.size() - 1);
      }
    });
  }

  public void testListRemoveFirst()
  {
    testStoreDelta(new ListManipulator()
    {
      public void doManipulations(EList<?> list)
      {
        list.remove(0);
      }
    });
  }

  public void testListSimpleMove()
  {
    testStoreDelta(new ListManipulator()
    {
      public void doManipulations(EList<?> list)
      {
        list.move(2, 7);
      }
    });
  }

  public void testListMoveToLast()
  {
    testStoreDelta(new ListManipulator()
    {
      public void doManipulations(EList<?> list)
      {
        list.move(2, list.size() - 1);
      }
    });
  }

  public void testListMoveToFirst()
  {
    testStoreDelta(new ListManipulator()
    {
      public void doManipulations(EList<?> list)
      {
        list.move(2, 0);
      }
    });
  }

  public void testListTwoIndependentMoves()
  {
    testStoreDelta(new ListManipulator()
    {
      public void doManipulations(EList<?> list)
      {
        list.move(1, 3);
        list.move(7, 4);
      }
    });
  }

  public void testListTwoIntersectingMoves()
  {
    testStoreDelta(new ListManipulator()
    {
      public void doManipulations(EList<?> list)
      {
        list.move(1, 7);
        list.move(3, 4);
      }
    });
  }

  public void testListInsertFirst()
  {
    testStoreDelta(new ListManipulator()
    {
      @SuppressWarnings("unchecked")
      public void doManipulations(EList<?> list)
      {
        EList<Company> l = (EList<Company>)list;
        Company company = getModel1Factory().createCompany();
        company.setName("NewEntry");
        l.add(0, company);
      }
    });
  }

  public void testListInsertMiddle()
  {
    testStoreDelta(new ListManipulator()
    {
      @SuppressWarnings("unchecked")
      public void doManipulations(EList<?> list)
      {
        EList<Company> l = (EList<Company>)list;
        Company company = getModel1Factory().createCompany();
        company.setName("NewEntry");
        l.add(5, company);
      }
    });
  }

  public void testListInsertLast()
  {
    testStoreDelta(new ListManipulator()
    {
      @SuppressWarnings("unchecked")
      public void doManipulations(EList<?> list)
      {
        EList<Company> l = (EList<Company>)list;
        Company company = getModel1Factory().createCompany();
        company.setName("NewEntry");
        l.add(company);
      }
    });
  }

  public void testListMultipleOpsWithClear()
  {
    testStoreDelta(new ListManipulator()
    {
      @SuppressWarnings("unchecked")
      public void doManipulations(EList<?> list)
      {
        EList<Company> l = (EList<Company>)list;

        l.remove(4);
        l.remove(7);

        Company company = getModel1Factory().createCompany();
        company.setName("NewEntry 1");
        l.add(5, company);

        l.move(1, 2);
        l.move(7, 0);

        l.clear();

        company = getModel1Factory().createCompany();
        company.setName("NewEntry 2");
        l.add(company);

        company = getModel1Factory().createCompany();
        company.setName("NewEntry 3");
        l.add(company);

        company = getModel1Factory().createCompany();
        company.setName("NewEntry 4");
        l.add(0, company);

        l.move(1, 2);
      }
    });
  }

  public void testListMultipleOps()
  {
    testStoreDelta(new ListManipulator()
    {
      @SuppressWarnings("unchecked")
      public void doManipulations(EList<?> list)
      {
        EList<Company> l = (EList<Company>)list;

        l.remove(7);

        Company company = getModel1Factory().createCompany();
        company.setName("NewEntry 1");
        l.add(5, company);

        l.move(1, 2);

        company = getModel1Factory().createCompany();
        company.setName("NewEntry 2");
        l.add(company);

        l.move(7, 0);

        company = getModel1Factory().createCompany();
        company.setName("NewEntry 3");
        l.add(company);

        l.remove(4);

        company = getModel1Factory().createCompany();
        company.setName("NewEntry 4");
        l.add(0, company);

        l.move(1, 2);
      }
    });
  }

  public void testMultipleInserts()
  {
    testStoreDelta(new ListManipulator()
    {
      @SuppressWarnings("unchecked")
      public void doManipulations(EList<?> list)
      {
        EList<Company> l = (EList<Company>)list;
        Company company = getModel1Factory().createCompany();
        company.setName("NewEntry 1");
        l.add(7, company);
        company = getModel1Factory().createCompany();
        company.setName("NewEntry 2");
        l.add(12, company);
      }
    });
  }

  public void testInsertAndRemove()
  {
    testStoreDelta(new ListManipulator()
    {
      @SuppressWarnings("unchecked")
      public void doManipulations(EList<?> list)
      {
        EList<Company> l = (EList<Company>)list;
        Company company = getModel1Factory().createCompany();
        company.setName("NewEntry 1");
        l.add(7, company);
        l.remove(12);
      }
    });
  }

  public void testInsertAndMove()
  {
    testStoreDelta(new ListManipulator()
    {
      @SuppressWarnings("unchecked")
      public void doManipulations(EList<?> list)
      {
        EList<Company> l = (EList<Company>)list;
        Company company = getModel1Factory().createCompany();
        company.setName("NewEntry 1");
        l.add(7, company);
        l.move(12, 7);
      }
    });
  }

  public void testMoveAndDelete()
  {
    testStoreDelta(new ListManipulator()
    {
      @SuppressWarnings("unchecked")
      public void doManipulations(EList<?> list)
      {
        EList<Company> l = (EList<Company>)list;
        l.move(12, 7);
        l.remove(12);
      }
    });
  }

  public void testInsertAndMoveAndRemove()
  {
    testStoreDelta(new ListManipulator()
    {
      @SuppressWarnings("unchecked")
      public void doManipulations(EList<?> list)
      {
        EList<Company> l = (EList<Company>)list;
        Company company = getModel1Factory().createCompany();
        company.setName("NewEntry 1");
        l.add(7, company);
        l.move(12, 7);
        l.remove(12);
      }
    });
  }

  public void testInsertAndSet()
  {
    testStoreDelta(new ListManipulator()
    {
      @SuppressWarnings("unchecked")
      public void doManipulations(EList<?> list)
      {
        EList<Company> l = (EList<Company>)list;
        Company company = getModel1Factory().createCompany();
        company.setName("NewEntry 1");
        l.add(7, company);
        Company company2 = getModel1Factory().createCompany();
        company2.setName("NewEntry 2");
        l.set(7, company2);
        l.add(19, company); // <- needed because the set operation makes the company a dangling reference
      }
    });
  }

  public void testSetAndRemove()
  {
    testStoreDelta(new ListManipulator()
    {
      @SuppressWarnings("unchecked")
      public void doManipulations(EList<?> list)
      {
        EList<Company> l = (EList<Company>)list;
        Company company = getModel1Factory().createCompany();
        company.setName("NewEntry 1");
        Company oldCompany = l.get(7);
        l.set(7, company);
        l.add(19, oldCompany);
        l.remove(7); // <- needed because the set operation makes the company a dangling reference
      }
    });
  }

  public void testMultipleRemoves()
  {
    testStoreDelta(new ListManipulator()
    {
      @SuppressWarnings("unchecked")
      public void doManipulations(EList<?> list)
      {
        EList<Company> l = (EList<Company>)list;
        l.remove(7);
        l.remove(12);
      }
    });
  }

  private InternalCDORevision getCopyCDORevision(Object object)
  {
    return (InternalCDORevision)CDOUtil.getCDOObject((EObject)object).cdoRevision().copy();
  }

  protected void testStoreDelta(ListManipulator manipulator)
  {
    BasicEList<Company> reference = new BasicEList<Company>();

    {
      CDOSession session = openSession();
      CDOTransaction transaction = session.openTransaction();
      CDOResource resource = transaction.createResource(getResourcePath("/test1"));

      for (int i = 0; i < 20; i++)
      {
        String name = "company " + i;
        Company company = getModel1Factory().createCompany();
        company.setName(name);
        resource.getContents().add(company);

        company = getModel1Factory().createCompany();
        company.setName(name);
        reference.add(company);
      }

      try
      {
        transaction.commit();
      }
      catch (CommitException ex)
      {
        throw WrappedException.wrap(ex);
      }

      transaction.close();
      session.close();
    }

    clearCache(getRepository().getRevisionManager());

    {
      CDOSession session = openSession();
      CDOTransaction transaction = session.openTransaction();
      CDOResource resource = transaction.getResource(getResourcePath("/test1"));

      manipulator.doManipulations(resource.getContents());
      manipulator.doManipulations(reference);

      try
      {
        transaction.commit();
      }
      catch (CommitException ex)
      {
        throw WrappedException.wrap(ex);
      }

      transaction.close();
      session.close();
    }

    clearCache(getRepository().getRevisionManager());

    {
      CDOSession session = openSession();
      CDOView view = session.openView();
      CDOResource resource = view.getResource(getResourcePath("/test1"));

      assertEquals(reference.size(), resource.getContents().size());

      for (int i = 0; i < reference.size(); i++)
      {
        assertEquals(reference.get(i).getName(), ((Company)resource.getContents().get(i)).getName());
      }

      view.close();
      session.close();
    }
  }

  /**
   * @author Simon McDuff
   */
  protected static interface ListManipulator
  {
    public void doManipulations(EList<?> list);
  }
}
