/***************************************************************************
 * Copyright (c) 2004 - 2008 Eike Stepper, 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
 *    Martin Taal - specific hibernate functionality
 **************************************************************************/
package org.eclipse.emf.cdo.server.internal.hibernate;

import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.id.CDOIDTemp;
import org.eclipse.emf.cdo.common.id.CDOIDUtil;
import org.eclipse.emf.cdo.common.model.CDOClassifierRef;
import org.eclipse.emf.cdo.common.model.CDOFeature;
import org.eclipse.emf.cdo.common.model.CDOPackage;
import org.eclipse.emf.cdo.common.model.CDOPackageInfo;
import org.eclipse.emf.cdo.common.model.resource.CDOResourceNodeClass;
import org.eclipse.emf.cdo.common.query.CDOQueryInfo;
import org.eclipse.emf.cdo.common.revision.CDORevision;
import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
import org.eclipse.emf.cdo.internal.server.StoreAccessor;
import org.eclipse.emf.cdo.server.IQueryContext;
import org.eclipse.emf.cdo.server.ISession;
import org.eclipse.emf.cdo.server.IStoreAccessor;
import org.eclipse.emf.cdo.server.ITransaction;
import org.eclipse.emf.cdo.server.hibernate.IHibernateStoreAccessor;
import org.eclipse.emf.cdo.server.hibernate.id.CDOIDHibernate;
import org.eclipse.emf.cdo.server.hibernate.internal.id.CDOIDHibernateFactoryImpl;
import org.eclipse.emf.cdo.server.internal.hibernate.bundle.OM;
import org.eclipse.emf.cdo.server.internal.hibernate.tuplizer.PersistableListHolder;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;

import org.eclipse.net4j.util.ObjectUtil;
import org.eclipse.net4j.util.WrappedException;
import org.eclipse.net4j.util.collection.CloseableIterator;
import org.eclipse.net4j.util.om.monitor.OMMonitor;
import org.eclipse.net4j.util.om.trace.ContextTracer;

import org.hibernate.Criteria;
import org.hibernate.FlushMode;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Expression;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

/**
 * @author Eike Stepper
 * @author Martin Taal
 */
public class HibernateStoreAccessor extends StoreAccessor implements IHibernateStoreAccessor
{
  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, HibernateStoreAccessor.class);

  private Session hibernateSession;

  private boolean errorOccured = false;

  public HibernateStoreAccessor(HibernateStore store, ISession session)
  {
    super(store, session);
    HibernateThreadContext.setCurrentHibernateStoreAccessor(this);
    if (TRACER.isEnabled())
    {
      TRACER.trace("Created " + this.getClass().getName() + " for repository " + store.getRepository().getName());
    }
  }

  public HibernateStoreAccessor(HibernateStore store, ITransaction transaction)
  {
    super(store, transaction);
    HibernateThreadContext.setCurrentHibernateStoreAccessor(this);
    if (TRACER.isEnabled())
    {
      TRACER.trace("Created " + this.getClass().getName() + " for repository " + store.getRepository().getName());
    }
  }

  /** Clears the current hibernate session and sets a new one in the thread context */
  public void resetHibernateSession()
  {
    endHibernateSession();
    beginHibernateSession();
  }

  @Override
  public HibernateStore getStore()
  {
    return (HibernateStore)super.getStore();
  }

  /**
   * starts a hibernate session and begins a transaction
   * 
   * @since 2.0
   */
  public void beginHibernateSession()
  {
    if (TRACER.isEnabled())
    {
      TRACER.trace("Creating hibernate session and transaction");
    }

    assert hibernateSession == null;
    final SessionFactory sessionFactory = getStore().getHibernateSessionFactory();
    hibernateSession = sessionFactory.openSession();
    hibernateSession.beginTransaction();
  }

  /**
   * Commits the session
   * 
   * @since 2.0
   */
  public void commitRollbackHibernateSession()
  {
    if (TRACER.isEnabled())
    {
      TRACER.trace("Commiting hibernate session");
    }

    if (isErrorOccured())
    {
      if (TRACER.isEnabled())
      {
        TRACER.trace("Rolling back hb transaction");
      }

      hibernateSession.getTransaction().rollback();
    }
    else
    {
      if (TRACER.isEnabled())
      {
        TRACER.trace("Committing hb transaction");
      }

      hibernateSession.getTransaction().commit();
    }
  }

  /**
   * commits/rollbacks and closes the session
   * 
   * @since 2.0
   */
  public void endHibernateSession()
  {
    if (TRACER.isEnabled())
    {
      TRACER.trace("Closing hibernate session");
    }

    if (hibernateSession != null && hibernateSession.isOpen())
    {
      try
      {
        if (hibernateSession.getTransaction().isActive())
        {
          commitRollbackHibernateSession();
        }
      }
      finally
      {
        hibernateSession.close();
      }
    }

    hibernateSession = null;
  }

  public Session getHibernateSession()
  {
    if (hibernateSession == null)
    {
      beginHibernateSession();
    }

    return hibernateSession;
  }

  /**
   * @since 2.0
   */
  public boolean isErrorOccured()
  {
    return errorOccured;
  }

  /**
   * @since 2.0
   */
  public void setErrorOccured(boolean errorOccured)
  {
    this.errorOccured = errorOccured;
  }

  public HibernateStoreChunkReader createChunkReader(CDORevision revision, CDOFeature feature)
  {
    return new HibernateStoreChunkReader(this, revision, feature);
  }

  public CloseableIterator<Object> createQueryIterator(CDOQueryInfo queryInfo)
  {
    // TODO: implement HibernateStoreAccessor.createQueryIterator(queryInfo)
    throw new UnsupportedOperationException();
  }

  public CloseableIterator<CDOID> readObjectIDs()
  {
    throw new UnsupportedOperationException();
  }

  public CDOClassifierRef readObjectType(CDOID id)
  {
    CDORevision cdoRevision = readRevision(id, -1);
    return cdoRevision.getCDOClass().createClassRef();
  }

  public void readPackage(CDOPackage cdoPackage)
  {
    getStore().getPackageHandler().readPackage(cdoPackage);
  }

  public void readPackageEcore(CDOPackage cdoPackage)
  {
    throw new UnsupportedOperationException();
  }

  public Collection<CDOPackageInfo> readPackageInfos()
  {
    return getStore().getPackageHandler().getCDOPackageInfos();
  }

  public CDORevision readRevision(CDOID id, int referenceChunk)
  {
    return HibernateUtil.getInstance().getCDORevision(id);
  }

  public CDORevision readRevisionByTime(CDOID id, int referenceChunk, long timeStamp)
  {
    throw new UnsupportedOperationException();
  }

  public CDORevision readRevisionByVersion(CDOID id, int referenceChunk, int version)
  {
    // TODO Could be necessary to implement
    throw new UnsupportedOperationException();
  }

  /**
   * TODO Clarify the meaning of {@link IStoreAccessor#refreshRevisions()}
   * 
   * @since 2.0
   */
  public void refreshRevisions()
  {
    // Do nothing
  }

  /**
   * @since 2.0
   */
  public void queryResources(QueryResourcesContext context)
  {
    CDOIDHibernate folderID = getHibernateID(context.getFolderID());
    String name = context.getName();
    boolean exactMatch = context.exactMatch();

    final Session session = getHibernateSession();
    final Criteria criteria = session.createCriteria(CDOResourceNodeClass.NAME);
    if (folderID == null)
    {
      criteria.add(Expression.isNull("containerID"));
    }
    else
    {
      criteria.add(Expression.eq("containerID", folderID));
    }

    List<?> result = criteria.list();
    for (Object o : result)
    {
      final CDORevision revision = (CDORevision)o;
      String revisionName = (String)revision.data().get(getResourceNameFeature(), 0);
      boolean match = exactMatch || revisionName == null || name == null ? ObjectUtil.equals(revisionName, name)
          : revisionName.startsWith(name);

      if (match && !context.addResource(revision.getID()))
      {
        // No more results allowed
        break;
      }
    }
  }

  private CDOIDHibernate getHibernateID(CDOID id)
  {
    if (!CDOIDUtil.isNull(id))
    {
      if (id instanceof CDOIDHibernate)
      {
        return (CDOIDHibernate)id;
      }

      // TODO Can this happen? When?
      final long longID = CDOIDUtil.getLong(id);
      return CDOIDHibernateFactoryImpl.getInstance().createCDOID(longID, CDOResourceNodeClass.NAME);
    }

    return null;
  }

  private CDOFeature getResourceNameFeature()
  {
    return getResourceNodeClass().getCDONameFeature();
  }

  private CDOResourceNodeClass getResourceNodeClass()
  {
    return getStore().getRepository().getPackageManager().getCDOResourcePackage().getCDOResourceNodeClass();
  }

  /**
   * @since 2.0
   */
  public void executeQuery(CDOQueryInfo info, IQueryContext context)
  {
    // TODO: implement HibernateStoreAccessor.executeQuery(info, context)
    throw new UnsupportedOperationException();
  }

  /**
   * Is handled through {@link #endHibernateSession()}.
   */
  public void commit(OMMonitor monitor)
  {
    commitRollbackHibernateSession();
    HibernateThreadContext.setCommitContext(null);
  }

  @Override
  public void write(CommitContext context, OMMonitor monitor)
  {
    List<InternalCDORevision> adjustRevisions = new ArrayList<InternalCDORevision>();
    HibernateThreadContext.setCommitContext(context);
    if (context.getNewPackages().length > 0)
    {
      writePackages(context.getNewPackages(), monitor);
    }
    try
    {
      // start with fresh hibernate session
      final Session session = getHibernateSession();
      session.setFlushMode(FlushMode.MANUAL);

      // first repair the version for all dirty objects
      for (CDORevision cdoRevision : context.getDirtyObjects())
      {
        if (cdoRevision instanceof InternalCDORevision)
        {
          InternalCDORevision internalCDORevision = (InternalCDORevision)cdoRevision;
          internalCDORevision.setVersion(cdoRevision.getVersion() - 1);
          adjustRevisions.add(internalCDORevision);
        }
      }

      // delete all objects
      for (CDOID cdoID : context.getDetachedObjects())
      {
        final CDORevision revision = HibernateUtil.getInstance().getCDORevision(cdoID);
        session.delete(revision);
      }

      final List<CDORevision> cdoRevisions = Arrays.asList(context.getNewObjects());

      // keep track for which cdoRevisions the container id needs to be repaired afterwards
      final List<InternalCDORevision> repairContainerIDs = new ArrayList<InternalCDORevision>();

      // first save the non-cdoresources
      for (CDORevision cdoRevision : cdoRevisions)
      {
        if (cdoRevision instanceof InternalCDORevision)
        {
          final CDOID containerID = (CDOID)((InternalCDORevision)cdoRevision).getContainerID();
          if (containerID instanceof CDOIDTemp && !containerID.isNull())
          {
            repairContainerIDs.add((InternalCDORevision)cdoRevision);
          }
        }

        session.save(HibernateUtil.getInstance().getEntityName(cdoRevision), cdoRevision);
        if (TRACER.isEnabled())
        {
          TRACER.trace("Persisted new Object " + cdoRevision.getCDOClass().getName() + " id: " + cdoRevision.getID());
        }
      }

      for (CDORevision cdoRevision : context.getDirtyObjects())
      {
        session.merge(HibernateUtil.getInstance().getEntityName(cdoRevision), cdoRevision);
        if (TRACER.isEnabled())
        {
          TRACER.trace("Updated Object " + cdoRevision.getCDOClass().getName() + " id: " + cdoRevision.getID());
        }
      }

      session.flush();

      // now do an update of the container without incrementing the version
      for (InternalCDORevision cdoRevision : repairContainerIDs)
      {
        final CDORevision container = HibernateUtil.getInstance().getCDORevision((CDOID)cdoRevision.getContainerID());
        final String entityName = HibernateUtil.getInstance().getEntityName(cdoRevision);
        final CDOIDHibernate id = (CDOIDHibernate)cdoRevision.getID();
        final CDOIDHibernate containerID = (CDOIDHibernate)container.getID();
        final String hqlUpdate = "update " + entityName
            + " set contID_Entity = :contEntity, contID_ID=:contID, contID_class=:contClass where e_id = :id";
        final Query qry = session.createQuery(hqlUpdate);
        qry.setParameter("contEntity", containerID.getEntityName());
        qry.setParameter("contID", containerID.getId().toString());
        qry.setParameter("contClass", containerID.getId().getClass().getName());
        qry.setParameter("id", id.getId());
        if (qry.executeUpdate() != 1)
        {
          throw new IllegalStateException("Not able to update container columns of " + entityName + " with id " + id);
        }
      }

      session.flush();

    }
    catch (Exception e)
    {
      OM.LOG.error(e);
      throw WrappedException.wrap(e);
    }
    finally
    {
      for (InternalCDORevision cdoRevision : adjustRevisions)
      {
        cdoRevision.setVersion(cdoRevision.getVersion() + 1);
      }
    }

    context.applyIDMappings(monitor);
  }

  @Override
  protected void detachObjects(CDOID[] detachedObjects, long revised, OMMonitor monitor)
  {
    // TODO: implement HibernateStoreAccessor.detachObjects(detachedObjects)
    throw new UnsupportedOperationException();
  }

  @Override
  protected void rollback(CommitContext context)
  {
    setErrorOccured(true);
    endHibernateSession();
    HibernateThreadContext.setCommitContext(null);
  }

  @Override
  protected void writePackages(CDOPackage[] cdoPackages, OMMonitor monitor)
  {
    if (cdoPackages != null && cdoPackages.length != 0)
    {
      getStore().getPackageHandler().writePackages(cdoPackages);
    }

    // Set a new hibernatesession in the thread
    resetHibernateSession();
  }

  @Override
  protected void writeRevisions(CDORevision[] revisions, OMMonitor monitor)
  {
    // Don't do anything it is done at commit
  }

  @Override
  protected void writeRevisionDeltas(CDORevisionDelta[] revisionDeltas, long created, OMMonitor monitor)
  {
    throw new UnsupportedOperationException();
  }

  @Override
  protected void doActivate() throws Exception
  {
  }

  @Override
  protected void doDeactivate() throws Exception
  {
    // TODO This method is called when this accessor is not needed anymore
    if (TRACER.isEnabled())
    {
      TRACER.trace("Committing/rollback and closing hibernate session");
    }

    try
    {
      endHibernateSession();
      PersistableListHolder.getInstance().clearListMapping();
    }
    finally
    {
      HibernateThreadContext.setCurrentHibernateStoreAccessor(this);
    }
  }

  @Override
  protected void doPassivate() throws Exception
  {
    // TODO This method is called right before this accessor is added to a pool
  }

  @Override
  protected void doUnpassivate() throws Exception
  {
    // TODO This method is called right after this accessor is removed from a pool
  }
}
