/*
 * Copyright (c) 2012 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.tests.hibernate;

import org.eclipse.emf.cdo.CDOObject;
import org.eclipse.emf.cdo.CDOObjectHistory;
import org.eclipse.emf.cdo.common.commit.CDOCommitHistory;
import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
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.common.revision.delta.CDOSetFeatureDelta;
import org.eclipse.emf.cdo.eresource.CDOResource;
import org.eclipse.emf.cdo.eresource.EresourcePackage;
import org.eclipse.emf.cdo.session.CDOSession;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
import org.eclipse.emf.cdo.tests.AbstractCDOTest;
import org.eclipse.emf.cdo.tests.config.IRepositoryConfig;
import org.eclipse.emf.cdo.tests.config.impl.ConfigTest.Requires;
import org.eclipse.emf.cdo.tests.model1.Company;
import org.eclipse.emf.cdo.tests.model1.Model1Package;
import org.eclipse.emf.cdo.tests.model1.Product1;
import org.eclipse.emf.cdo.tests.model1.VAT;
import org.eclipse.emf.cdo.transaction.CDOTransaction;
import org.eclipse.emf.cdo.util.CDOUtil;
import org.eclipse.emf.cdo.view.CDOView;

import org.eclipse.net4j.util.concurrent.ConcurrencyUtil;
import org.eclipse.net4j.util.lifecycle.LifecycleUtil;

import org.eclipse.emf.ecore.EAnnotation;
import org.eclipse.emf.ecore.EcoreFactory;
import org.eclipse.emf.teneo.Constants;

import java.util.List;

/**
 * @author Martin Taal
 * @author Eike Stepper
 */
@Requires(IRepositoryConfig.CAPABILITY_AUDITING)
public class CDOObjectHistoryTest extends AbstractCDOTest
{
  protected CDOSession session1;

  @Override
  public void setUp() throws Exception
  {
    if (Model1Package.eINSTANCE.getProduct1_Vat().getEAnnotation(Constants.ANNOTATION_SOURCE_TENEO_JPA) == null)
    {
      final EAnnotation eAnnotation = EcoreFactory.eINSTANCE.createEAnnotation();
      eAnnotation.setSource(Constants.ANNOTATION_SOURCE_TENEO_JPA);
      eAnnotation.getDetails().put(Constants.ANNOTATION_KEY_VALUE, "@Enumerated(value=EnumType.ORDINAL)");
      Model1Package.eINSTANCE.getProduct1_Vat().getEAnnotations().add(eAnnotation);
    }

    super.setUp();
  }

  @Override
  protected void doTearDown() throws Exception
  {
    LifecycleUtil.deactivate(session1);
    session1 = null;
    super.doTearDown();
  }

  protected CDOSession openSession1()
  {
    session1 = openSession();
    return session1;
  }

  protected void closeSession1()
  {
    session1.close();
  }

  protected CDOSession openSession2()
  {
    return openSession();
  }

  public void testChangedAudit() throws Exception
  {
    CDOSession session = openSession1();
    CDOTransaction transaction = session.openTransaction();
    CDOResource resource = transaction.createResource(getResourcePath("/res1"));

    Company company = getModel1Factory().createCompany();
    company.setName("ESC");
    resource.getContents().add(company);

    // add a product
    Product1 product = getModel1Factory().createProduct1();
    product.setVat(VAT.VAT15);
    product.setDescription("description");
    resource.getContents().add(product);

    long commitTime1 = transaction.commit().getTimeStamp();
    assertEquals(true, session.getRepositoryInfo().getCreationTime() < commitTime1);
    assertEquals("ESC", company.getName());
    final CDOObject cdoObjectCompany = CDOUtil.getCDOObject(company);
    assertEquals(1, cdoObjectCompany.cdoRevision().getVersion());

    company.setName("Sympedia");
    long commitTime2 = transaction.commit().getTimeStamp();
    assertEquals(true, commitTime1 < commitTime2);
    assertEquals(true, session.getRepositoryInfo().getCreationTime() < commitTime2);
    assertEquals("Sympedia", company.getName());
    assertEquals(2, cdoObjectCompany.cdoRevision().getVersion());

    company.setName("Eclipse");
    long commitTime3 = transaction.commit().getTimeStamp();
    assertEquals(true, commitTime2 < commitTime3);
    assertEquals(true, session.getRepositoryInfo().getCreationTime() < commitTime2);
    assertEquals("Eclipse", company.getName());
    assertEquals(3, cdoObjectCompany.cdoRevision().getVersion());

    resource.getContents().remove(company);
    long commitTime4 = transaction.commit().getTimeStamp();

    closeSession1();
    session = openSession2();

    CDOView audit = session.openView(commitTime1);
    {
      CDOResource auditResource = audit.getResource(getResourcePath("/res1"));
      Company auditCompany = (Company)auditResource.getContents().get(0);
      assertEquals("ESC", auditCompany.getName());

      final CDOObjectHistory cdoObjectHistory = getCDOObjectHistory(audit, auditCompany);
      assertEquals(1, cdoObjectHistory.getElements().length);
      for (CDOCommitInfo cdoCommitInfo : cdoObjectHistory.getElements())
      {
        if (cdoCommitInfo.getTimeStamp() == commitTime1)
        {
          checkCommitInfo1(cdoCommitInfo);
        }
        else
        {
          fail();
        }
      }
      audit.close();
    }

    audit = session.openView(commitTime2);
    {
      CDOResource auditResource = audit.getResource(getResourcePath("/res1"));
      Company auditCompany = (Company)auditResource.getContents().get(0);
      assertEquals("Sympedia", auditCompany.getName());

      final CDOObjectHistory cdoObjectHistory = getCDOObjectHistory(audit, auditCompany);
      assertEquals(2, cdoObjectHistory.getElements().length);
      for (CDOCommitInfo cdoCommitInfo : cdoObjectHistory.getElements())
      {
        if (cdoCommitInfo.getTimeStamp() == commitTime1)
        {
          checkCommitInfo1(cdoCommitInfo);
        }
        else if (cdoCommitInfo.getTimeStamp() == commitTime2)
        {
          checkCommitInfo2(cdoCommitInfo);
        }
        else
        {
          fail();
        }
      }
      audit.close();
    }

    audit = session.openView(commitTime3);
    {
      CDOResource auditResource = audit.getResource(getResourcePath("/res1"));

      Company auditCompany = (Company)auditResource.getContents().get(0);
      assertEquals("Eclipse", auditCompany.getName());

      final CDOObjectHistory cdoObjectHistory = getCDOObjectHistory(audit, auditCompany);
      assertEquals(3, cdoObjectHistory.getElements().length);
      for (CDOCommitInfo cdoCommitInfo : cdoObjectHistory.getElements())
      {
        if (cdoCommitInfo.getTimeStamp() == commitTime1)
        {
          checkCommitInfo1(cdoCommitInfo);
        }
        else if (cdoCommitInfo.getTimeStamp() == commitTime2)
        {
          checkCommitInfo2(cdoCommitInfo);
        }
        else if (cdoCommitInfo.getTimeStamp() == commitTime3)
        {
          checkCommitInfo3(cdoCommitInfo);
        }
        else
        {
          fail();
        }
      }

      final CDOObject cdoObject = CDOUtil.getCDOObject(auditCompany);
      int initialVersion = cdoObject.cdoRevision().getVersion();
      assertEquals(3, initialVersion);

      final InternalCDORevision revision3 = (InternalCDORevision)CDOUtil.getRevisionByVersion(cdoObject, 3);
      final InternalCDORevision revision2 = (InternalCDORevision)CDOUtil.getRevisionByVersion(cdoObject, 2);
      final InternalCDORevision revision1 = (InternalCDORevision)CDOUtil.getRevisionByVersion(cdoObject, 1);

      CDORevisionDelta revisionDelta = revision3.compare(revision2);
      for (CDOFeatureDelta featureDelta : revisionDelta.getFeatureDeltas())
      {
        System.err
            .println(featureDelta.getFeature().getName() + " changed through changeType " + featureDelta.getType());
      }

      assertEquals("ESC", revision1.getValue(revision1.getEClass().getEStructuralFeature("name")));
      assertEquals("Sympedia", revision2.getValue(revision1.getEClass().getEStructuralFeature("name")));
      assertEquals("Eclipse", revision3.getValue(revision1.getEClass().getEStructuralFeature("name")));

      audit.close();
    }

    audit = session.openView(commitTime4);
    {
      final CDOCommitHistory cdoCommitHistory = getCDOCommitHistory(audit);
      assertEquals(5, cdoCommitHistory.getElements().length);
      for (CDOCommitInfo cdoCommitInfo : cdoCommitHistory.getElements())
      {
        if (cdoCommitInfo.getTimeStamp() == commitTime1)
        {
          checkCommitInfo1(cdoCommitInfo);
        }
        else if (cdoCommitInfo.getTimeStamp() == commitTime2)
        {
          checkCommitInfo2(cdoCommitInfo);
        }
        else if (cdoCommitInfo.getTimeStamp() == commitTime3)
        {
          checkCommitInfo3(cdoCommitInfo);
        }
        else if (cdoCommitInfo.getTimeStamp() == commitTime4)
        {
          checkCommitInfo4(cdoCommitInfo);
        }
        else if (cdoCommitInfo.getComment() != null && cdoCommitInfo.getComment().equals("<initialize>"))
        {
          // as expected
        }
        else
        {
          fail();
        }
      }
      audit.close();
    }

    session.close();
  }

  private void checkCommitInfo1(CDOCommitInfo cdoCommitInfo)
  {
    final List<CDOIDAndVersion> newObjects = cdoCommitInfo.getNewObjects();
    final List<CDORevisionKey> changedObjects = cdoCommitInfo.getChangedObjects();
    final List<CDOIDAndVersion> detachedObjects = cdoCommitInfo.getDetachedObjects();
    assertEquals(0, detachedObjects.size());
    assertEquals(4, newObjects.size());
    assertEquals(1, changedObjects.size());
    for (Object o : changedObjects)
    {
      final CDORevisionDelta cdoRevisionDelta = (CDORevisionDelta)o;
      final CDOFeatureDelta cdoFeatureDelta = cdoRevisionDelta
          .getFeatureDelta(EresourcePackage.eINSTANCE.getCDOResource_Contents());
      assertNotNull(cdoFeatureDelta);
      assertEquals(CDOFeatureDelta.Type.LIST, cdoFeatureDelta.getType());
    }
    int resourceCnt = 0;
    int resourceFolderCnt = 0;
    int companyCnt = 0;
    int productCnt = 0;
    for (Object o : newObjects)
    {
      final CDORevision cdoRevision = (CDORevision)o;
      if (cdoRevision.getEClass().getName().equals(Model1Package.eINSTANCE.getProduct1().getName()))
      {
        productCnt++;
      }
      if (cdoRevision.getEClass().getName().equals(Model1Package.eINSTANCE.getCompany().getName()))
      {
        companyCnt++;
      }
      if (cdoRevision.getEClass() == EresourcePackage.eINSTANCE.getCDOResource())
      {
        resourceCnt++;
      }
      if (cdoRevision.getEClass() == EresourcePackage.eINSTANCE.getCDOResourceFolder())
      {
        resourceFolderCnt++;
      }
    }
    assertEquals(1, productCnt);
    assertEquals(1, companyCnt);
    assertEquals(1, resourceCnt);
    assertEquals(1, resourceFolderCnt);
  }

  private void checkCommitInfo2(CDOCommitInfo cdoCommitInfo)
  {
    final List<CDOIDAndVersion> newObjects = cdoCommitInfo.getNewObjects();
    final List<CDORevisionKey> changedObjects = cdoCommitInfo.getChangedObjects();
    final List<CDOIDAndVersion> detachedObjects = cdoCommitInfo.getDetachedObjects();
    assertEquals(0, detachedObjects.size());
    assertEquals(0, newObjects.size());
    assertEquals(1, changedObjects.size());
    for (Object o : changedObjects)
    {
      final CDORevisionDelta cdoRevisionDelta = (CDORevisionDelta)o;
      final CDOSetFeatureDelta cdoFeatureDelta = (CDOSetFeatureDelta)cdoRevisionDelta
          .getFeatureDelta(cdoRevisionDelta.getEClass().getEStructuralFeature("name"));
      assertNotNull(cdoFeatureDelta);
      assertEquals("Sympedia", cdoFeatureDelta.getValue());
    }
  }

  private void checkCommitInfo3(CDOCommitInfo cdoCommitInfo)
  {
    final List<CDOIDAndVersion> newObjects = cdoCommitInfo.getNewObjects();
    final List<CDORevisionKey> changedObjects = cdoCommitInfo.getChangedObjects();
    final List<CDOIDAndVersion> detachedObjects = cdoCommitInfo.getDetachedObjects();
    assertEquals(0, detachedObjects.size());
    assertEquals(0, newObjects.size());
    assertEquals(1, changedObjects.size());
    for (Object o : changedObjects)
    {
      final CDORevisionDelta cdoRevisionDelta = (CDORevisionDelta)o;
      final CDOSetFeatureDelta cdoFeatureDelta = (CDOSetFeatureDelta)cdoRevisionDelta
          .getFeatureDelta(cdoRevisionDelta.getEClass().getEStructuralFeature("name"));
      assertNotNull(cdoFeatureDelta);
      assertEquals("Eclipse", cdoFeatureDelta.getValue());
    }
  }

  private void checkCommitInfo4(CDOCommitInfo cdoCommitInfo)
  {
    final List<CDOIDAndVersion> newObjects = cdoCommitInfo.getNewObjects();
    final List<CDORevisionKey> changedObjects = cdoCommitInfo.getChangedObjects();
    final List<CDOIDAndVersion> detachedObjects = cdoCommitInfo.getDetachedObjects();
    assertEquals(1, detachedObjects.size());
    assertEquals(0, newObjects.size());
    // due to a bug/issue in cdo hibernate store, there are 2 changedobjects
    // need to revisit after default/enum value setting has been changed
    // https://bugs.eclipse.org/bugs/show_bug.cgi?id=387752
    assertEquals(1, changedObjects.size());
    for (Object o : changedObjects)
    {
      final CDORevisionDelta cdoRevisionDelta = (CDORevisionDelta)o;
      if (cdoRevisionDelta.getEClass().getName().equals("Product1"))
      {
        continue;
      }
      final CDOFeatureDelta cdoFeatureDelta = cdoRevisionDelta
          .getFeatureDelta(EresourcePackage.eINSTANCE.getCDOResource_Contents());
      assertNotNull(cdoFeatureDelta);
      assertEquals(CDOFeatureDelta.Type.LIST, cdoFeatureDelta.getType());
    }
  }

  private synchronized CDOObjectHistory getCDOObjectHistory(CDOView audit, Object object)
  {
    CDOObjectHistory cdoObjectHistory = audit.getHistory((CDOObject)object);

    cdoObjectHistory.triggerLoad();
    long startTime = System.currentTimeMillis();
    while (cdoObjectHistory.isLoading())
    {
      ConcurrencyUtil.sleep(10);

      // waited too long
      if (System.currentTimeMillis() - startTime > 5000)
      {
        throw new IllegalStateException("commit info could not be loaded");
      }
    }
    return cdoObjectHistory;
  }

  private synchronized CDOCommitHistory getCDOCommitHistory(CDOView audit)
  {
    CDOCommitHistory cdoCommitHistory = audit.getHistory();

    cdoCommitHistory.triggerLoad();
    long startTime = System.currentTimeMillis();
    while (cdoCommitHistory.isLoading())
    {
      ConcurrencyUtil.sleep(10);

      // waited too long
      if (System.currentTimeMillis() - startTime > 5000)
      {
        throw new IllegalStateException("commit info could not be loaded");
      }
    }
    return cdoCommitHistory;
  }
}
