/*
 * Copyright (c) 2010-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:
 *    Victor Roldan Betancort - initial API and implementation
 */
package org.eclipse.emf.cdo.server.internal.db4o;

import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.id.CDOIDUtil;
import org.eclipse.emf.cdo.server.ISession;
import org.eclipse.emf.cdo.server.IStore;
import org.eclipse.emf.cdo.server.IStoreAccessor;
import org.eclipse.emf.cdo.server.ITransaction;
import org.eclipse.emf.cdo.server.IView;
import org.eclipse.emf.cdo.server.db4o.IDB4OIdentifiableObject;
import org.eclipse.emf.cdo.server.db4o.IDB4OStore;
import org.eclipse.emf.cdo.spi.server.LongIDStore;
import org.eclipse.emf.cdo.spi.server.StoreAccessorPool;

import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump;
import org.eclipse.net4j.util.lifecycle.LifecycleUtil;

import com.db4o.Db4o;
import com.db4o.ObjectContainer;
import com.db4o.ObjectServer;
import com.db4o.ObjectSet;
import com.db4o.config.Configuration;
import com.db4o.constraints.UniqueFieldValueConstraint;
import com.db4o.query.Query;
import com.db4o.reflect.jdk.JdkReflector;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author Victor Roldan Betancort
 */
public class DB4OStore extends LongIDStore implements IDB4OStore
{
  private static final String ID_ATTRIBUTE = "id";

  private transient String storeLocation;

  private transient int port;

  private transient ObjectServer server;

  private transient Configuration serverConfiguration;

  private ServerInfo serverInfo;

  private DB4ODurableLockingManager durableLockingManager = new DB4ODurableLockingManager();

  @ExcludeFromDump
  private transient final StoreAccessorPool readerPool = new StoreAccessorPool(this, null);

  @ExcludeFromDump
  private transient final StoreAccessorPool writerPool = new StoreAccessorPool(this, null);

  public DB4OStore(String storeLocation, int port)
  {
    super(IDB4OStore.TYPE, set(ChangeFormat.REVISION), set(RevisionTemporality.NONE, RevisionTemporality.AUDITING),
        set(RevisionParallelism.NONE, RevisionParallelism.BRANCHING));

    // setRevisionTemporality(RevisionTemporality.AUDITING);
    // setRevisionParallelism(RevisionParallelism.BRANCHING);

    this.storeLocation = storeLocation;
    this.port = port;
  }

  public DB4OStore(String storeLocation, int port, Configuration serverConfiguration)
  {
    this(storeLocation, port);
    this.serverConfiguration = serverConfiguration;
  }

  public String getStoreLocation()
  {
    return storeLocation;
  }

  public int getPort()
  {
    return port;
  }

  public long getCreationTime()
  {
    return getServerInfo().getCreationTime();
  }

  public void setCreationTime(long creationTime)
  {
    getServerInfo().setCreationTime(creationTime);
  }

  public boolean isFirstStart()
  {
    return getServerInfo().isFirstTime();
  }

  public DB4ODurableLockingManager getDurableLockingManager()
  {
    return durableLockingManager;
  }

  public Map<String, String> getPersistentProperties(Set<String> names)
  {
    if (names == null || names.isEmpty())
    {
      return new HashMap<String, String>(getServerInfo().getProperties());
    }

    Map<String, String> result = new HashMap<String, String>();
    for (String key : names)
    {
      String value = getServerInfo().getProperties().get(key);
      if (value != null)
      {
        result.put(key, value);
      }
    }

    return result;
  }

  public void setPersistentProperties(Map<String, String> properties)
  {
    ServerInfo serverInfo = getServerInfo();
    serverInfo.getProperties().putAll(properties);
    commitServerInfo(null);
  }

  public void removePersistentProperties(Set<String> names)
  {
    ServerInfo serverInfo = getServerInfo();
    Map<String, String> properties = serverInfo.getProperties();
    for (String key : names)
    {
      properties.remove(key);
    }

    commitServerInfo(null);
  }

  // @Override
  // public CDOID getNextCDOID(LongIDStoreAccessor accessor, CDORevision revision)
  // {
  // ObjectContainer objectContainer = ((DB4OStoreAccessor)accessor).getObjectContainer();
  // ExtObjectContainer ext = objectContainer.ext();
  // ext.store(revision);
  //
  // long id = ext.getID(revision);
  // return CDOIDUtil.createLong(id);
  // }

  public ObjectContainer openClient()
  {
    return server.openClient();
  }

  @Override
  protected void doActivate() throws Exception
  {
    super.doActivate();
    initObjectServer();
    initServerInfo();
    setLastCommitTime(getServerInfo().getLastCommitTime());
    setLastObjectID(fetchLastObjectID());
    LifecycleUtil.activate(durableLockingManager);
  }

  private long fetchLastObjectID()
  {
    ObjectContainer container = openClient();

    try
    {
      Query query = container.query();
      query.constrain(DB4ORevision.class);
      query.descend("id").orderDescending();
      ObjectSet<?> results = query.execute();
      int size = results.size();
      if (size > 0)
      {
        DB4ORevision rev = (DB4ORevision)results.next();
        return rev.getID();
      }
      return 0;
    }
    finally
    {
      closeClient(container);
    }
  }

  @SuppressWarnings("deprecation")
  protected void initObjectServer()
  {
    Configuration configuration = serverConfiguration;
    if (configuration == null)
    {
      configuration = createServerConfiguration();
    }
    {
      File file = new File(getStoreLocation());
      if (!file.exists())
      {
        try
        {
          file.createNewFile();
        }
        catch (IOException ex)
        {
          throw new RuntimeException(ex);
        }
      }
    }

    server = Db4o.openServer(configuration, getStoreLocation(), getPort());
  }

  protected void tearDownObjectServer()
  {
    server.close();
    server = null;
  }

  private ServerInfo getServerInfo()
  {
    if (serverInfo == null)
    {
      initServerInfo();
    }

    return serverInfo;
  }

  private void initServerInfo()
  {
    ObjectContainer container = openClient();

    try
    {
      serverInfo = getServerInfoFromDatabase(container);

      if (serverInfo == null)
      {
        serverInfo = new ServerInfo();
        serverInfo.setFirstTime(true);
        serverInfo.setCreationTime(System.currentTimeMillis());
        commitServerInfo(container);
      }
      else
      {
        if (serverInfo.isFirstTime())
        {
          serverInfo.setFirstTime(false);
          commitServerInfo(container);
        }
      }
    }
    finally
    {
      closeClient(container);
    }
  }

  private ServerInfo getServerInfoFromDatabase(ObjectContainer container)
  {
    ObjectSet<ServerInfo> infos = container.query(ServerInfo.class);
    if (infos.size() > 1)
    {
      throw new IllegalStateException("ServeInfo is stored in container more than once");
    }

    if (infos.size() == 1)
    {
      return infos.get(0);
    }

    return null;
  }

  protected void closeClient(ObjectContainer container)
  {
    container.close();
  }

  private void commitServerInfo(ObjectContainer container)
  {
    ObjectContainer usedContainer = container != null ? container : openClient();

    try
    {
      ServerInfo storedInfo = getServerInfoFromDatabase(usedContainer);
      if (storedInfo != null && storedInfo != serverInfo)
      {
        storedInfo.setCreationTime(serverInfo.getCreationTime());
        storedInfo.setFirstTime(serverInfo.isFirstTime());
        storedInfo.setLastCommitTime(serverInfo.getLastCommitTime());
        storedInfo.setProperties(serverInfo.getProperties());
        serverInfo = storedInfo;
      }

      usedContainer.store(serverInfo);
      usedContainer.commit();
    }
    finally
    {
      if (usedContainer != container)
      {
        closeClient(usedContainer);
      }
    }
  }

  @Override
  protected void doDeactivate() throws Exception
  {
    ObjectContainer container = openClient();

    try
    {
      getServerInfo().setLastCommitTime(getLastCommitTime());
      commitServerInfo(container);
    }
    finally
    {
      closeClient(container);
    }

    LifecycleUtil.deactivate(durableLockingManager);
    tearDownObjectServer();

    super.doDeactivate();
  }

  protected Configuration createServerConfiguration()
  {
    @SuppressWarnings("deprecation")
    Configuration config = Db4o.newConfiguration();
    config.reflectWith(new JdkReflector(getClass().getClassLoader()));

    config.objectClass(DB4ORevision.class).objectField("id").indexed(true);
    config.add(new UniqueFieldValueConstraint(DB4ORevision.class, "id"));

    config.objectClass(DB4OPackageUnit.class).objectField("id").indexed(true);
    config.add(new UniqueFieldValueConstraint(DB4OPackageUnit.class, "id"));

    config.objectClass(DB4OIdentifiableObject.class).objectField("id").indexed(true);
    config.add(new UniqueFieldValueConstraint(DB4OIdentifiableObject.class, "id"));

    config.objectClass(DB4OCommitInfo.class).objectField("timeStamp").indexed(true);

    config.objectClass(DB4OLockArea.class).objectField("id").indexed(true);
    config.add(new UniqueFieldValueConstraint(DB4OLockArea.class, "id"));
    config.objectClass(DB4OLockArea.class).cascadeOnUpdate(true);
    config.objectClass(DB4OLockArea.class).cascadeOnDelete(true);

    return config;
  }

  @Override
  protected IStoreAccessor createReader(ISession session)
  {
    return new DB4OStoreAccessor(this, session);
  }

  @Override
  protected IStoreAccessor createWriter(ITransaction transaction)
  {
    return new DB4OStoreAccessor(this, transaction);
  }

  @Override
  protected StoreAccessorPool getReaderPool(ISession session, boolean forReleasing)
  {
    return readerPool;
  }

  @Override
  protected StoreAccessorPool getWriterPool(IView view, boolean forReleasing)
  {
    return writerPool;
  }

  public static DB4ORevision getRevision(ObjectContainer container, CDOID id)
  {
    Query query = container.query();
    query.constrain(DB4ORevision.class);
    query.descend(ID_ATTRIBUTE).constrain(CDOIDUtil.getLong(id));

    ObjectSet<?> revisions = query.execute();
    if (revisions.isEmpty())
    {
      return null;
    }

    return (DB4ORevision)revisions.get(0);
  }

  public static <T> List<T> getElementsOfType(ObjectContainer container, Class<T> clazz)
  {
    ObjectSet<T> elements = container.query(clazz);
    return elements;
  }

  public static IDB4OIdentifiableObject getIdentifiableObject(ObjectContainer container, String id)
  {
    Query query = container.query();
    query.constrain(IDB4OIdentifiableObject.class);
    query.descend(ID_ATTRIBUTE).constrain(id);

    ObjectSet<?> revisions = query.execute();
    if (revisions.isEmpty())
    {
      return null;
    }

    return (IDB4OIdentifiableObject)revisions.get(0);
  }

  public static void removeRevision(ObjectContainer container, CDOID id)
  {
    DB4ORevision revision = getRevision(container, id);
    if (revision != null)
    {
      container.delete(revision);
    }
  }

  /**
   * Carries {@link IStore}-related information.
   *
   * @author Victor Roldan Betancort
   */
  private static final class ServerInfo
  {
    private boolean isFirstTime;

    private long creationTime;

    private long lastCommitTime;

    private Map<String, String> properties = new HashMap<String, String>();

    public boolean isFirstTime()
    {
      return isFirstTime;
    }

    public void setFirstTime(boolean isFirstTime)
    {
      this.isFirstTime = isFirstTime;
    }

    public void setCreationTime(long creationTime)
    {
      this.creationTime = creationTime;
    }

    public long getCreationTime()
    {
      return creationTime;
    }

    public void setProperties(Map<String, String> properties)
    {
      this.properties = properties;
    }

    public Map<String, String> getProperties()
    {
      return properties;
    }

    public long getLastCommitTime()
    {
      return lastCommitTime;
    }

    public void setLastCommitTime(long lastCommitTime)
    {
      this.lastCommitTime = lastCommitTime;
    }
  }
}
