/*******************************************************************************
 * Copyright (c) 2008-2011 Chair for Applied Software Engineering,
 * Technische Universitaet Muenchen.
 * 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:
 * Otto von Wesendonk - initial API and implementation
 ******************************************************************************/
package org.eclipse.emf.emfstore.internal.server.core.subinterfaces;

import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import org.apache.commons.lang.StringUtils;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.emfstore.internal.common.APIUtil;
import org.eclipse.emf.emfstore.internal.common.ESCollections;
import org.eclipse.emf.emfstore.internal.common.model.Project;
import org.eclipse.emf.emfstore.internal.common.model.impl.ProjectImpl;
import org.eclipse.emf.emfstore.internal.common.model.util.ModelUtil;
import org.eclipse.emf.emfstore.internal.common.model.util.SerializationException;
import org.eclipse.emf.emfstore.internal.server.EMFStoreController;
import org.eclipse.emf.emfstore.internal.server.ServerConfiguration;
import org.eclipse.emf.emfstore.internal.server.core.AbstractEmfstoreInterface;
import org.eclipse.emf.emfstore.internal.server.core.AbstractSubEmfstoreInterface;
import org.eclipse.emf.emfstore.internal.server.exceptions.BranchInfoMissingException;
import org.eclipse.emf.emfstore.internal.server.exceptions.FatalESException;
import org.eclipse.emf.emfstore.internal.server.exceptions.InvalidVersionSpecException;
import org.eclipse.emf.emfstore.internal.server.exceptions.StorageException;
import org.eclipse.emf.emfstore.internal.server.model.ProjectHistory;
import org.eclipse.emf.emfstore.internal.server.model.ProjectId;
import org.eclipse.emf.emfstore.internal.server.model.SessionId;
import org.eclipse.emf.emfstore.internal.server.model.accesscontrol.ACUser;
import org.eclipse.emf.emfstore.internal.server.model.impl.api.ESUserImpl;
import org.eclipse.emf.emfstore.internal.server.model.versioning.AbstractChangePackage;
import org.eclipse.emf.emfstore.internal.server.model.versioning.AncestorVersionSpec;
import org.eclipse.emf.emfstore.internal.server.model.versioning.BranchInfo;
import org.eclipse.emf.emfstore.internal.server.model.versioning.BranchVersionSpec;
import org.eclipse.emf.emfstore.internal.server.model.versioning.ChangePackage;
import org.eclipse.emf.emfstore.internal.server.model.versioning.ChangePackageEnvelope;
import org.eclipse.emf.emfstore.internal.server.model.versioning.DateVersionSpec;
import org.eclipse.emf.emfstore.internal.server.model.versioning.FileBasedChangePackage;
import org.eclipse.emf.emfstore.internal.server.model.versioning.HeadVersionSpec;
import org.eclipse.emf.emfstore.internal.server.model.versioning.LogMessage;
import org.eclipse.emf.emfstore.internal.server.model.versioning.PagedUpdateVersionSpec;
import org.eclipse.emf.emfstore.internal.server.model.versioning.PrimaryVersionSpec;
import org.eclipse.emf.emfstore.internal.server.model.versioning.TagVersionSpec;
import org.eclipse.emf.emfstore.internal.server.model.versioning.Version;
import org.eclipse.emf.emfstore.internal.server.model.versioning.VersionSpec;
import org.eclipse.emf.emfstore.internal.server.model.versioning.VersioningFactory;
import org.eclipse.emf.emfstore.internal.server.model.versioning.Versions;
import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.AbstractOperation;
import org.eclipse.emf.emfstore.server.ESCloseableIterable;
import org.eclipse.emf.emfstore.server.auth.ESMethod;
import org.eclipse.emf.emfstore.server.auth.ESMethod.MethodId;
import org.eclipse.emf.emfstore.server.exceptions.ESException;
import org.eclipse.emf.emfstore.server.exceptions.ESUpdateRequiredException;
import org.eclipse.emf.emfstore.server.model.ESSessionId;
import org.eclipse.emf.emfstore.server.model.ESUser;

import com.google.common.base.Optional;

/**
 * This subinterface implements all version related functionality.
 *
 * @author wesendon
 */
public class VersionSubInterfaceImpl extends AbstractSubEmfstoreInterface {

	/**
	 * Default constructor.
	 *
	 * @param parentInterface
	 *            parent interface
	 * @throws FatalESException
	 *             in case of failure
	 */
	public VersionSubInterfaceImpl(AbstractEmfstoreInterface parentInterface) throws FatalESException {
		super(parentInterface);
	}

	/**
	 * Resolves a versionSpec and delivers the corresponding primary
	 * versionSpec.
	 *
	 * @param projectId
	 *            project id
	 * @param versionSpec
	 *            versionSpec
	 * @return primary versionSpec
	 *
	 * @throws InvalidVersionSpecException
	 *             if the project ID is invalid
	 * @throws ESException
	 *             if versionSpec can't be resolved or other failure
	 */
	@ESMethod(MethodId.RESOLVEVERSIONSPEC)
	public PrimaryVersionSpec resolveVersionSpec(ProjectId projectId, VersionSpec versionSpec)
		throws InvalidVersionSpecException, ESException {

		sanityCheckObjects(projectId, versionSpec);

		synchronized (getMonitor()) {
			final ProjectHistory projectHistory = getSubInterface(ProjectSubInterfaceImpl.class).getProject(projectId);

			if (versionSpec instanceof PrimaryVersionSpec) {
				return resolvePrimaryVersionSpec(projectHistory, (PrimaryVersionSpec) versionSpec);
			} else if (versionSpec instanceof HeadVersionSpec) {
				return resolveHeadVersionSpec(projectHistory, (HeadVersionSpec) versionSpec);
			} else if (versionSpec instanceof DateVersionSpec) {
				return resolveDateVersionSpec(projectHistory, (DateVersionSpec) versionSpec);
			} else if (versionSpec instanceof TagVersionSpec) {
				return resolveTagVersionSpec(projectHistory, (TagVersionSpec) versionSpec);
			} else if (versionSpec instanceof BranchVersionSpec) {
				return resolveBranchVersionSpec(projectHistory, (BranchVersionSpec) versionSpec);
			} else if (versionSpec instanceof AncestorVersionSpec) {
				return resolveAncestorVersionSpec(projectHistory, (AncestorVersionSpec) versionSpec);
			} else if (versionSpec instanceof PagedUpdateVersionSpec) {
				return resolvePagedUpdateVersionSpec(projectHistory, (PagedUpdateVersionSpec) versionSpec);
			}

			throw new InvalidVersionSpecException(Messages.VersionSubInterfaceImpl_UnknownVersionSpec);
		}
	}

	private PrimaryVersionSpec resolveAncestorVersionSpec(ProjectHistory projectHistory,
		AncestorVersionSpec versionSpec)
			throws InvalidVersionSpecException {

		Version currentSource = getVersion(projectHistory, versionSpec.getSource());
		Version currentTarget = getVersion(projectHistory, versionSpec.getTarget());

		if (currentSource == null || currentTarget == null) {
			throw new InvalidVersionSpecException(Messages.VersionSubInterfaceImpl_Invalid_Source_Or_Target);
		}

		// The goal is to find the common ancestor version of the source and
		// target version from different branches. In
		// order to find the ancestor the algorithm starts at the specified
		// version and walks down the version tree in
		// parallel for source and target until the current versions are equal
		// and the ancestor is found. In Each step
		// only one version (of target and source) is decremented. To find the
		// global ancestor it is necessary that the
		// version with the higher version number is decremented.
		while (currentSource != null && currentTarget != null) {
			if (currentSource == currentTarget) {
				return currentSource.getPrimarySpec();
			}

			// Shortcut for most common merge usecase: If you have 2 parallel
			// branches, only seperated by one level and merge several times from the one branch into the another.
			// This case is also supported by #getVersions
			if (currentSource.getMergedFromVersion().contains(currentTarget)) {
				return currentTarget.getPrimarySpec();
			}

			if (currentSource.getPrimarySpec().getIdentifier() >= currentTarget.getPrimarySpec().getIdentifier()) {
				currentSource = findNextVersion(currentSource);
			} else {
				currentTarget = findNextVersion(currentTarget);
			}

		}
		throw new InvalidVersionSpecException(Messages.VersionSubInterfaceImpl_NoAncestorFound);
	}

	private PrimaryVersionSpec resolvePrimaryVersionSpec(ProjectHistory projectHistory, PrimaryVersionSpec versionSpec)
		throws InvalidVersionSpecException {
		final int index = versionSpec.getIdentifier();
		final String branch = versionSpec.getBranch();
		final int versions = projectHistory.getVersions().size();
		if (0 > index || index >= versions || branch == null) {
			throw new InvalidVersionSpecException(MessageFormat.format(
				Messages.VersionSubInterfaceImpl_InvalidVersionRequested,
				index));
		}

		if (branch.equals(VersionSpec.GLOBAL)) {
			return projectHistory.getVersions().get(index).getPrimarySpec();
		}

		// Get biggest primary version of given branch which is equal or lower
		// to the given versionSpec
		for (int i = index; i >= 0; i--) {
			final Version version = projectHistory.getVersions().get(i);
			if (branch.equals(version.getPrimarySpec().getBranch())) {
				return version.getPrimarySpec();
			}

		}
		throw new InvalidVersionSpecException(Messages.VersionSubInterfaceImpl_PrimaryVersionNotFound);
	}

	private PrimaryVersionSpec resolveHeadVersionSpec(ProjectHistory projectHistory, HeadVersionSpec versionSpec)
		throws InvalidVersionSpecException {
		if (VersionSpec.GLOBAL.equals(versionSpec.getBranch())) {
			return projectHistory.getVersions().get(projectHistory.getVersions().size() - 1).getPrimarySpec();
		}
		final BranchInfo info = getBranchInfo(projectHistory, versionSpec);
		if (info != null) {
			return info.getHead();
		}
		throw new InvalidVersionSpecException(Messages.VersionSubInterfaceImpl_HeadVersionNotFound);
	}

	private PrimaryVersionSpec resolveDateVersionSpec(ProjectHistory projectHistory, DateVersionSpec versionSpec) {
		for (final Version version : projectHistory.getVersions()) {
			final LogMessage logMessage = version.getLogMessage();
			if (logMessage == null || logMessage.getDate() == null) {
				continue;
			}
			if (versionSpec.getDate().before(logMessage.getDate())) {
				final Version previousVersion = version.getPreviousVersion();
				if (previousVersion == null) {
					return VersioningFactory.eINSTANCE.createPrimaryVersionSpec();
				}
				return previousVersion.getPrimarySpec();
			}
		}
		return projectHistory.getLastVersion().getPrimarySpec();
	}

	private PrimaryVersionSpec resolveTagVersionSpec(ProjectHistory projectHistory, TagVersionSpec versionSpec)
		throws InvalidVersionSpecException {
		for (final Version version : projectHistory.getVersions()) {
			for (final TagVersionSpec tag : version.getTagSpecs()) {
				if (versionSpec.equals(tag)) {
					return ModelUtil.clone(version.getPrimarySpec());
				}
			}
		}
		throw new InvalidVersionSpecException(Messages.VersionSubInterfaceImpl_TagVersionNotFound);
	}

	private PrimaryVersionSpec resolveBranchVersionSpec(ProjectHistory projectHistory, BranchVersionSpec versionSpec)
		throws BranchInfoMissingException {
		final BranchInfo branchInfo = getBranchInfo(projectHistory, versionSpec);
		if (branchInfo == null) {
			throw new BranchInfoMissingException(Messages.VersionSubInterfaceImpl_NoBranchInfo);
		}
		return branchInfo.getHead();
	}

	/**
	 * Given a {@link ChangePackageEnvelope} which contains a change package fragment,
	 * stores one or more fragments by attaching them to a session specific adapter.
	 *
	 * @param sessionId
	 *            the {@link SessionId} belonging to the calling user
	 * @param projectId
	 *            the {@link ProjectId}
	 * @param envelope
	 *            the {@link ChangePackageEnvelope} containing the fragment
	 * @return an ID identifying the stored fragment(s)
	 * @throws ESException in case the fragment couldn't be stored
	 */
	@ESMethod(MethodId.UPLOADCHANGEPACKAGEFRAGMENT)
	public String uploadChangePackageFragment(SessionId sessionId,
		ProjectId projectId,
		ChangePackageEnvelope envelope) throws ESException {

		final String proxyId = generateProxyId(projectId.getId());

		final ESSessionId resolvedSession = getAccessControl().getSessions().resolveSessionById(sessionId.getId());

		if (resolvedSession == null) {
			throw new ESException(
				MessageFormat.format(
					Messages.VersionSubInterfaceImpl_0, sessionId.getId()));
		}

		final SessionId session = APIUtil.toInternal(SessionId.class, resolvedSession);
		final Optional<ChangePackageFragmentUploadAdapter> maybeAdapter = ESCollections.find(session.eAdapters(),
			ChangePackageFragmentUploadAdapter.class);
		ChangePackageFragmentUploadAdapter adapter;

		if (!maybeAdapter.isPresent()) {
			adapter = new ChangePackageFragmentUploadAdapter();
			session.eAdapters().add(adapter);
		} else {
			adapter = maybeAdapter.get();
		}

		adapter.addFragment(proxyId, envelope.getFragment());
		if (envelope.isLast()) {
			adapter.markAsComplete(proxyId);
		}

		return proxyId;
	}

	/**
	 * Fetches a single change package fragment.
	 *
	 * @param sessionId
	 *            the {@link SessionId} representing the requesting user
	 * @param proxyId
	 *            the ID that identifies the list of stored fragments
	 * @param fragmentIndex
	 *            allows to request different change package fragments
	 * @return a {@link ChangePackageEnvelope} containing the change package fragment
	 * @throws ESException in case the mandatory session adapter is missing
	 */
	@ESMethod(MethodId.DOWNLOADCHANGEPACKAGEFRAGMENT)
	public ChangePackageEnvelope downloadChangePackageFragment(SessionId sessionId, String proxyId, int fragmentIndex)
		throws ESException {

		final ESSessionId resolvedSession = getAccessControl().getSessions().resolveSessionById(sessionId.getId());
		final SessionId session = APIUtil.toInternal(SessionId.class, resolvedSession);
		final Optional<ChangePackageFragmentProviderAdapter> maybeAdapter = ESCollections.find(session.eAdapters(),
			ChangePackageFragmentProviderAdapter.class);

		if (!maybeAdapter.isPresent()) {
			throw new ESException(Messages.VersionSubInterfaceImpl_ChangePackageFragmentProviderAdapterMissing
				+ sessionId);
		}

		final ChangePackageFragmentProviderAdapter adapter = maybeAdapter.get();
		final ChangePackageEnvelope envelope = VersioningFactory.eINSTANCE.createChangePackageEnvelope();
		final List<AbstractOperation> fragment = adapter.getFragment(proxyId, fragmentIndex);

		envelope.getFragment().addAll(fragment);
		envelope.setFragmentCount(adapter.getFragmentSize(proxyId));
		envelope.setFragmentIndex(fragmentIndex);

		if (envelope.isLast()) {
			adapter.markAsConsumed(proxyId);
		}

		return envelope;
	}

	private String generateProxyId(String projectId) {
		return UUID.nameUUIDFromBytes(projectId.getBytes()).toString();
	}

	/**
	 * Create a new version.
	 *
	 * @param sessionId
	 *            the ID of the session being used to create a new version
	 * @param projectId
	 *            the ID of the project for which a new version is created
	 * @param baseVersionSpec
	 *            the base version
	 * @param changePackage
	 *            the change package containing all changes that make up the new version
	 * @param targetBranch
	 *            the target branch for which to create the new version
	 * @param sourceVersion
	 *            the source version
	 * @param logMessage
	 *            a log message
	 * @return the new version
	 * @throws ESException in case of failure
	 */
	@ESMethod(MethodId.CREATEVERSION)
	public PrimaryVersionSpec createVersion(SessionId sessionId, ProjectId projectId,
		PrimaryVersionSpec baseVersionSpec, AbstractChangePackage changePackage, BranchVersionSpec targetBranch,
		PrimaryVersionSpec sourceVersion, LogMessage logMessage) throws ESException {

		getAccessControl().getSessions().isValid(sessionId.toAPI());
		final ESUser rawUser = getAccessControl().getSessions().getRawUser(sessionId.toAPI());
		final ACUser tmpUser = (ACUser) ESUserImpl.class.cast(rawUser).toInternalAPI();
		final ESUser copyAndResolveUser = getAccessControl().getOrgUnitResolverServive().copyAndResolveUser(
			tmpUser.toAPI());
		final ACUser user = (ACUser) ESUserImpl.class.cast(copyAndResolveUser).toInternalAPI();
		sanityCheckObjects(sessionId, projectId, baseVersionSpec, changePackage, logMessage);

		if (FileBasedChangePackage.class.isInstance(changePackage)
			&& !ServerConfiguration.useFileBasedChangePackageOnServer()) {
			// File-based change package should never arrive here in production mode
			throw new ESException(Messages.VersionSubInterfaceImpl_FileBasedChangePackageNotAllowed);
		} else if (ChangePackage.class.isInstance(changePackage)
			&& ServerConfiguration.useFileBasedChangePackageOnServer()) {
			// Regular change package should never arrive here in production mode
			throw new ESException(Messages.VersionSubInterfaceImpl_FileBasedChangePackageExpected);
		}

		return internalCreateVersion(projectId, baseVersionSpec, changePackage, targetBranch, sourceVersion,
			logMessage, user);
	}

	private PrimaryVersionSpec internalCreateVersion(ProjectId projectId, PrimaryVersionSpec baseVersionSpec,
		AbstractChangePackage changePackage, BranchVersionSpec targetBranch, PrimaryVersionSpec sourceVersion,
		LogMessage logMessage, final ACUser user) throws ESException {
		synchronized (getMonitor()) {

			final long currentTimeMillis = System.currentTimeMillis();
			final ProjectHistory projectHistory = getSubInterface(ProjectSubInterfaceImpl.class).getProject(projectId);

			// Find branch
			final BranchInfo baseBranch = getBranchInfo(projectHistory, baseVersionSpec);
			final Version baseVersion = getVersion(projectHistory, baseVersionSpec);

			if (baseVersion == null || baseBranch == null) {
				throw new InvalidVersionSpecException(
					Messages.VersionSubInterfaceImpl_InvalidBranchOrVersion);
			}

			// defined here fore scoping reasons
			Version newVersion = null;
			BranchInfo newBranch = null;

			// copy project and apply changes
			final Project newProjectState = ((ProjectImpl) getSubInterface(ProjectSubInterfaceImpl.class).getProject(
				baseVersion)).copy();
			changePackage.apply(newProjectState);

			// regular commit
			if (isRegularCommit(targetBranch, baseVersion)) {

				newVersion = performRegularCommit(baseVersionSpec, logMessage, user, projectHistory, baseBranch,
					baseVersion, newProjectState);

				// case for new branch creation
			} else if (isNewBranchCommit(targetBranch, projectHistory)) {
				checkNewBranchCommitPreRequisites(targetBranch.getBranch());
				// when branch does NOT exist, create new branch
				newVersion = createVersion(projectHistory, newProjectState, logMessage, user, baseVersion);
				newBranch = createNewBranch(projectHistory, baseVersion.getPrimarySpec(), newVersion.getPrimarySpec(),
					targetBranch);
				newVersion.setAncestorVersion(baseVersion);

			} else {
				// This point only can be reached with invalid input
				throw new IllegalStateException(Messages.VersionSubInterfaceImpl_TargetBranchCombination_Invalid);
			}

			if (sourceVersion != null) {
				newVersion.getMergedFromVersion().add(getVersion(projectHistory, sourceVersion));
			}

			// try to save
			try {
				try {
					trySave(projectId, changePackage, projectHistory, newVersion, newProjectState);
				} catch (final FatalESException e) {
					// try to roll back. removing version is necessary in all cases
					rollback(projectHistory, baseBranch, baseVersion, newVersion, newBranch, e);
				}

				// if ancestor isn't null, a new branch was created. In this
				// case we want to keep the old base project
				// state
				if (newVersion.getAncestorVersion() == null && baseVersion.getProjectState() != null) {
					// delete projectstate from last revision depending on
					// persistence policy
					deleteOldProjectSpaceAccordingToOptions(projectId, baseVersion);
				}

				save(baseVersion);
				save(projectHistory);

			} catch (final FatalESException e) {
				// roll back failed
				EMFStoreController.getInstance().shutdown(e);
				throw new ESException(Messages.VersionSubInterfaceImpl_ShuttingServerDown);
			}

			ModelUtil.logInfo(
				Messages.VersionSubInterfaceImpl_TotalTimeForCommit + (System.currentTimeMillis() - currentTimeMillis));
			return newVersion.getPrimarySpec();
		}
	}

	/**
	 * @param targetBranch
	 * @throws InvalidVersionSpecException
	 */
	private void checkNewBranchCommitPreRequisites(String targetBranchName) throws InvalidVersionSpecException {
		if (targetBranchName.equals(StringUtils.EMPTY)) {
			throw new InvalidVersionSpecException(Messages.VersionSubInterfaceImpl_EmptyBranch_Not_Allowed);
		} else if (targetBranchName.equals(VersionSpec.GLOBAL)) {
			throw new InvalidVersionSpecException(
				Messages.VersionSubInterfaceImpl_BranchName_Reserved_1
					+ VersionSpec.GLOBAL + Messages.VersionSubInterfaceImpl_BranchName_Reserved_2);
		}
	}

	private Version performRegularCommit(PrimaryVersionSpec baseVersionSpec, LogMessage logMessage, final ACUser user,
		final ProjectHistory projectHistory, final BranchInfo baseBranch, final Version baseVersion,
		final Project newProjectState) throws ESUpdateRequiredException, ESException {
		Version newVersion;
		// If branch is null or branch equals base branch, create new
		// version for specific branch
		if (!baseVersionSpec.equals(isHeadOfBranch(projectHistory, baseVersion.getPrimarySpec()))) {
			throw new ESUpdateRequiredException();
		}
		newVersion = createVersion(projectHistory, newProjectState, logMessage, user, baseVersion);
		newVersion.setPreviousVersion(baseVersion);
		baseBranch.setHead(ModelUtil.clone(newVersion.getPrimarySpec()));
		return newVersion;
	}

	/**
	 * @param targetBranch
	 * @param projectHistory
	 * @return
	 */
	private boolean isNewBranchCommit(BranchVersionSpec targetBranch, final ProjectHistory projectHistory) {
		return getBranchInfo(projectHistory, targetBranch) == null;
	}

	/**
	 * @param targetBranch
	 * @param baseVersion
	 * @return
	 */
	private boolean isRegularCommit(BranchVersionSpec targetBranch, final Version baseVersion) {
		return targetBranch == null || baseVersion.getPrimarySpec().getBranch().equals(targetBranch.getBranch());
	}

	private void rollback(final ProjectHistory projectHistory, final BranchInfo baseBranch,
		final Version baseVersion, Version newVersion, BranchInfo newBranch, final FatalESException e)
			throws StorageException {
		projectHistory.getVersions().remove(newVersion);

		if (newBranch == null) {
			// normal commit
			baseVersion.setNextVersion(null);
			baseBranch.setHead(ModelUtil.clone(baseVersion.getPrimarySpec()));
		} else {
			// branch commit
			baseVersion.getBranchedVersions().remove(newVersion);
			projectHistory.getBranches().remove(newBranch);
		}
		// TODO: delete obsolete project, change package and version files
		throw new StorageException(StorageException.NOSAVE, e);
	}

	/**
	 * @param projectId
	 * @param changePackage
	 * @param projectHistory
	 * @param newVersion
	 * @param newProjectState
	 * @throws FatalESException
	 */
	private void trySave(ProjectId projectId, AbstractChangePackage changePackage, final ProjectHistory projectHistory,
		Version newVersion, final Project newProjectState) throws FatalESException {
		getResourceHelper().createResourceForProject(newProjectState,
			newVersion.getPrimarySpec(), projectHistory.getProjectId());
		getResourceHelper().createResourceForChangePackage(changePackage, newVersion.getPrimarySpec(),
			projectId);
		if (FileBasedChangePackage.class.isInstance(changePackage)) {
			try {
				/* move the temporary file to the project folder */
				final URI uri = changePackage.eResource().getURI();
				final URI normalizedUri = changePackage.eResource().getResourceSet().getURIConverter().normalize(uri);
				final String filePath = normalizedUri.toFileString() + ".1"; //$NON-NLS-1$
				FileBasedChangePackage.class.cast(changePackage).move(filePath);
				ModelUtil.saveResource(changePackage.eResource(), ModelUtil.getResourceLogger());
			} catch (final IOException ex) {
				throw new FatalESException(StorageException.NOSAVE, ex);
			}
		}

		getResourceHelper().createResourceForVersion(newVersion, projectHistory.getProjectId());

		newVersion.setProjectStateResource(newProjectState.eResource());
		newVersion.setChangeResource(changePackage.eResource());
	}

	private BranchInfo createNewBranch(ProjectHistory projectHistory, PrimaryVersionSpec baseSpec,
		PrimaryVersionSpec primarySpec, BranchVersionSpec branch) {
		primarySpec.setBranch(branch.getBranch());

		final BranchInfo branchInfo = VersioningFactory.eINSTANCE.createBranchInfo();
		branchInfo.setName(branch.getBranch());
		branchInfo.setSource(ModelUtil.clone(baseSpec));
		branchInfo.setHead(ModelUtil.clone(primarySpec));

		projectHistory.getBranches().add(branchInfo);

		return branchInfo;
	}

	private Version createVersion(ProjectHistory projectHistory, Project projectState, LogMessage logMessage,
		ACUser user, Version previousVersion) throws ESException {
		final Version newVersion = VersioningFactory.eINSTANCE.createVersion();

		long computedChecksum = ModelUtil.NO_CHECKSUM;

		try {
			if (ServerConfiguration.isComputeChecksumOnCommitActive()) {
				computedChecksum = ModelUtil.computeChecksum(projectState);
			}
		} catch (final SerializationException exception) {
			// TODO: clarify what to do in case checksum computation fails + provide ext. point
			throw new ESException(MessageFormat.format(
				Messages.VersionSubInterfaceImpl_ChecksumComputationFailed,
				projectHistory.getProjectName()), exception);
		}

		// newVersion.setChanges(changePackage);

		logMessage.setDate(new Date());
		logMessage.setAuthor(user.getName());
		newVersion.setLogMessage(logMessage);

		// latest version == getVersion.size() (version start with index 0 as
		// the list), branch from previous is used.
		newVersion.setPrimarySpec(Versions.createPRIMARY(previousVersion.getPrimarySpec(), projectHistory.getVersions()
			.size()));
		newVersion.getPrimarySpec().setProjectStateChecksum(computedChecksum);
		newVersion.setNextVersion(null);

		projectHistory.getVersions().add(newVersion);
		return newVersion;
	}

	private Version getVersion(ProjectHistory projectHistory, PrimaryVersionSpec baseVersionSpec) {
		if (0 > baseVersionSpec.getIdentifier()
			|| baseVersionSpec.getIdentifier() > projectHistory.getVersions().size() - 1) {
			return null;
		}
		final Version version = projectHistory.getVersions().get(baseVersionSpec.getIdentifier());
		if (version == null || !version.getPrimarySpec().equals(baseVersionSpec)) {
			return null;
		}
		return version;
	}

	private PrimaryVersionSpec isHeadOfBranch(ProjectHistory projectHistory, PrimaryVersionSpec versionSpec) {
		final BranchInfo branchInfo = getBranchInfo(projectHistory, versionSpec);
		if (branchInfo != null && branchInfo.getHead().equals(versionSpec)) {
			return branchInfo.getHead();
		}
		return null;
	}

	private BranchInfo getBranchInfo(ProjectHistory projectHistory, VersionSpec versionSpec) {
		for (final BranchInfo branchInfo : projectHistory.getBranches()) {
			if (branchInfo.getName().equals(versionSpec.getBranch())) {
				return branchInfo;
			}
		}
		return null;
	}

	/**
	 * Returns all branches for the project with the given ID.
	 *
	 * @param projectId
	 *            the ID of a project
	 * @return a list containing information about each branch
	 * @throws ESException in case of failure
	 */
	@ESMethod(MethodId.GETBRANCHES)
	public List<BranchInfo> getBranches(ProjectId projectId) throws ESException {
		synchronized (getMonitor()) {
			final ProjectHistory projectHistory = getSubInterface(ProjectSubInterfaceImpl.class).getProject(projectId);
			final ArrayList<BranchInfo> result = new ArrayList<BranchInfo>();
			for (final BranchInfo branch : projectHistory.getBranches()) {
				result.add(ModelUtil.clone(branch));
			}
			return result;
		}
	}

	/**
	 * Deletes projectstate from last revision depending on persistence policy.
	 *
	 * @param projectId
	 *            project id
	 * @param previousHeadVersion
	 *            last head version
	 */
	private void deleteOldProjectSpaceAccordingToOptions(ProjectId projectId, Version previousHeadVersion) {
		final String property = ServerConfiguration.getProperties().getProperty(
			ServerConfiguration.PROJECTSTATE_VERSION_PERSISTENCE,
			ServerConfiguration.PROJECTSPACE_VERSION_PERSISTENCE_DEFAULT);

		if (property.equals(ServerConfiguration.PROJECTSTATE_VERSION_PERSISTENCE_EVERYXVERSIONS)) {

			final int x = getResourceHelper().getXFromPolicy(
				ServerConfiguration.PROJECTSTATE_VERSION_PERSISTENCE_EVERYXVERSIONS_X,
				ServerConfiguration.PROJECTSTATE_VERSION_PERSISTENCE_EVERYXVERSIONS_X_DEFAULT, false);

			// always save projecstate of first version
			final int lastVersion = previousHeadVersion.getPrimarySpec().getIdentifier();
			if (lastVersion != 0 && lastVersion % x != 0) {
				getResourceHelper().deleteProjectState(previousHeadVersion, projectId);
			}

		} else {
			getResourceHelper().deleteProjectState(previousHeadVersion, projectId);
		}
	}

	/**
	 * Returns all changes within the specified version range for a given project.
	 *
	 * @param projectId
	 *            the ID of a project
	 * @param source
	 *            the source version
	 * @param target
	 *            the target version (inclusive)
	 * @return a list of change packages containing all the changes for the specified version range
	 *
	 * @throws InvalidVersionSpecException
	 *             if an invalid version has been specified
	 * @throws ESException
	 *             in case of failure
	 */
	@ESMethod(MethodId.GETCHANGES)
	public List<AbstractChangePackage> getChanges(ProjectId projectId, VersionSpec source, VersionSpec target)
		throws InvalidVersionSpecException, ESException {

		sanityCheckObjects(projectId, source, target);
		final PrimaryVersionSpec resolvedSource = resolveVersionSpec(projectId, source);
		final PrimaryVersionSpec resolvedTarget = resolveVersionSpec(projectId, target);
		// if target and source are equal return empty list
		if (resolvedSource.getIdentifier() == resolvedTarget.getIdentifier()) {
			return new ArrayList<AbstractChangePackage>();
		}

		synchronized (getMonitor()) {

			final boolean updateForward = resolvedTarget.getIdentifier() > resolvedSource.getIdentifier();

			// Example: if you want the changes to get from version 5 to 7, you
			// need the changes contained in version 6
			// and 7. The reason is that each version holds the changes which
			// occurred from the predecessor to the
			// version itself. Version 5 holds the changes to get from version 4
			// to 5 and therefore is irrelevant.
			// For that reason the first version is removed, since getVersions
			// always sorts ascending order.
			final List<Version> versions = getVersions(projectId, resolvedSource, resolvedTarget);
			if (versions.size() > 1) {
				versions.remove(0);
			}

			List<AbstractChangePackage> result = new ArrayList<AbstractChangePackage>();
			for (final Version version : versions) {
				final AbstractChangePackage changes = version.getChanges();
				if (changes != null) {
					changes.setLogMessage(ModelUtil.clone(version.getLogMessage()));
					result.add(changes);
				}
			}

			// if source is after target in time
			if (!updateForward) {
				// reverse list and change packages
				final List<AbstractChangePackage> resultReverse = new ArrayList<AbstractChangePackage>();
				for (final AbstractChangePackage changePackage : result) {

					final ChangePackage changePackageReverse = VersioningFactory.eINSTANCE.createChangePackage();
					final ESCloseableIterable<AbstractOperation> reversedOperations = changePackage
						.reversedOperations();
					final ArrayList<AbstractOperation> copiedReversedOperations = new ArrayList<AbstractOperation>();
					try {
						for (final AbstractOperation op : reversedOperations.iterable()) {
							copiedReversedOperations.add(op.reverse());
						}
					} finally {
						reversedOperations.close();
					}

					for (final AbstractOperation reversedOperation : copiedReversedOperations) {
						changePackageReverse.add(reversedOperation);
					}

					// copy again log message
					// reverse() created a new change package without copying
					// existent attributes
					changePackageReverse.setLogMessage(ModelUtil.clone(
						changePackage.getLogMessage()));
					resultReverse.add(changePackageReverse);
				}

				Collections.reverse(resultReverse);
				result = resultReverse;
			}

			return result;
		}
	}

	/**
	 * Returns the specified version of a project.
	 *
	 * @param projectId
	 *            project id
	 * @param versionSpec
	 *            versionSpec
	 * @return the version
	 * @throws ESException
	 *             if version couldn't be found
	 */
	protected Version getVersion(ProjectId projectId, PrimaryVersionSpec versionSpec) throws ESException {
		final ProjectHistory project = getSubInterface(ProjectSubInterfaceImpl.class).getProject(projectId);
		return getVersion(project, versionSpec);
	}

	/**
	 * Returns a list of versions starting from source and ending with target.
	 * This method returns the version always in an ascanding order. So if you
	 * need it ordered differently you have to reverse the list.
	 *
	 * @param projectId
	 *            project id
	 * @param source
	 *            source
	 * @param target
	 *            target
	 * @return list of versions
	 * @throws ESException
	 *             if source or target are out of range or any other problem
	 *             occurs
	 */
	protected List<Version> getVersions(ProjectId projectId, PrimaryVersionSpec source, PrimaryVersionSpec target)
		throws ESException {
		if (source.compareTo(target) < 1) {
			final ProjectHistory projectHistory = getSubInterface(ProjectSubInterfaceImpl.class).getProject(projectId);

			final Version sourceVersion = getVersion(projectHistory, source);
			final Version targetVersion = getVersion(projectHistory, target);

			if (sourceVersion == null || targetVersion == null) {
				throw new InvalidVersionSpecException(Messages.VersionSubInterfaceImpl_NoSourceNorTarget);
			}
			final List<Version> result = new ArrayList<Version>();

			// since the introduction of branches the versions are collected
			// in different order.
			Version currentVersion = targetVersion;
			while (currentVersion != null) {
				result.add(currentVersion);
				if (currentVersion.equals(sourceVersion)) {
					break;
				}
				if (currentVersion.getPrimarySpec().compareTo(sourceVersion.getPrimarySpec()) < 0) {
					// walked too far, invalid path.
					throw new InvalidVersionSpecException(Messages.VersionSubInterfaceImpl_InvalidPath);
				}
				// Shortcut for most common merge usecase: If you have 2
				// parallel branches and merge several times
				// from the one branch into the another.
				if (currentVersion.getMergedFromVersion().contains(sourceVersion)) {
					// add sourceVersion because #getChanges always removes
					// the first version
					result.add(sourceVersion);
					break;
				}

				currentVersion = findNextVersion(currentVersion);
			}
			// versions are collected in descending order, so the result has to be reversed.
			Collections.reverse(result);
			return result;
		}

		return getVersions(projectId, target, source);
	}

	/**
	 * Helper method which retrieves the next version in the history tree. This
	 * method must be used in reversed order. With the introduction of branches, the versions are organized in a tree
	 * structure. Therefore, next versions are always searched for walking up the tree.
	 *
	 * @param currentVersion
	 *            current version
	 * @return version
	 * @throws InvalidVersionSpecException
	 *             if the path can't be followed further
	 */
	public static Version findNextVersion(Version currentVersion) throws InvalidVersionSpecException {
		// find next version
		if (currentVersion.getPreviousVersion() != null) {
			currentVersion = currentVersion.getPreviousVersion();
		} else if (currentVersion.getAncestorVersion() != null) {
			currentVersion = currentVersion.getAncestorVersion();
		} else {
			throw new InvalidVersionSpecException(Messages.VersionSubInterfaceImpl_NextVersionInvalid);
		}
		return currentVersion;
	}

	private PrimaryVersionSpec resolvePagedUpdateVersionSpec(ProjectHistory projectHistory,
		PagedUpdateVersionSpec baseVersion) {

		int changes = 0;
		PrimaryVersionSpec resolvedSpec = baseVersion.getBaseVersionSpec();
		int maxChanges = baseVersion.getMaxChanges();

		int i = resolvedSpec.getIdentifier();

		AbstractChangePackage cp = projectHistory.getVersions().get(i).getChanges();

		if (i == projectHistory.getVersions().size() - 1) {
			return projectHistory.getVersions().get(i).getPrimarySpec();
		}

		do {
			cp = projectHistory.getVersions().get(++i).getChanges();
		} while (cp == null && i < projectHistory.getVersions().size());

		// pull at least one change package
		if (cp.leafSize() > maxChanges) {
			maxChanges = cp.leafSize();
		}

		while (changes < maxChanges && i < projectHistory.getVersions().size()) {
			resolvedSpec = projectHistory.getVersions().get(i).getPrimarySpec();
			final Version version = projectHistory.getVersions().get(i);
			final AbstractChangePackage changePackage = version.getChanges();

			if (changePackage != null) {
				final int size = changePackage.leafSize();
				if (changes + size >= maxChanges) {
					resolvedSpec = projectHistory.getVersions().get(i).getPrimarySpec();
					break;
				}
				changes += size;
			}
			i += 1;
		}

		return resolvedSpec;
	}
}