/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.jackrabbit.oak.plugins.version;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.jcr.RepositoryException;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Root;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.commons.UUIDUtils;
import org.apache.jackrabbit.oak.namepath.NamePathMapper;
import org.apache.jackrabbit.oak.plugins.memory.PropertyBuilder;
import org.apache.jackrabbit.oak.plugins.nodetype.ReadOnlyNodeTypeManager;
import org.apache.jackrabbit.oak.plugins.nodetype.TypePredicate;
import org.apache.jackrabbit.oak.plugins.tree.factories.RootFactory;
import org.apache.jackrabbit.oak.plugins.tree.factories.TreeFactory;
import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.apache.jackrabbit.util.ISO8601;
import org.apache.jackrabbit.util.Text;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.apache.jackrabbit.JcrConstants.JCR_BASEVERSION;
import static org.apache.jackrabbit.JcrConstants.JCR_CREATED;
import static org.apache.jackrabbit.JcrConstants.JCR_ISCHECKEDOUT;
import static org.apache.jackrabbit.JcrConstants.JCR_PREDECESSORS;
import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
import static org.apache.jackrabbit.JcrConstants.JCR_ROOTVERSION;
import static org.apache.jackrabbit.JcrConstants.JCR_SUCCESSORS;
import static org.apache.jackrabbit.JcrConstants.JCR_UUID;
import static org.apache.jackrabbit.JcrConstants.JCR_VERSIONABLEUUID;
import static org.apache.jackrabbit.JcrConstants.JCR_VERSIONHISTORY;
import static org.apache.jackrabbit.JcrConstants.JCR_VERSIONLABELS;
import static org.apache.jackrabbit.JcrConstants.NT_VERSION;
import static org.apache.jackrabbit.JcrConstants.NT_VERSIONHISTORY;
import static org.apache.jackrabbit.JcrConstants.NT_VERSIONLABELS;
import static org.apache.jackrabbit.oak.plugins.version.Utils.uuidFromNode;
import static org.apache.jackrabbit.oak.spi.version.VersionConstants.JCR_COPIED_FROM;
import static org.apache.jackrabbit.oak.spi.version.VersionConstants.REP_VERSIONSTORAGE;
import static org.apache.jackrabbit.oak.spi.version.VersionConstants.VERSION_STORE_PATH;

/**
 * Extends the {@link ReadOnlyVersionManager} with methods to modify the
 * version store.
 */
public class ReadWriteVersionManager extends ReadOnlyVersionManager {

    private static final Logger LOG = LoggerFactory.getLogger(ReadWriteVersionManager.class);

    private final NodeBuilder versionStorageNode;
    private final NodeBuilder workspaceRoot;
    private final TypePredicate isVersion;
    private ReadOnlyNodeTypeManager ntMgr;

    public ReadWriteVersionManager(NodeBuilder versionStorageNode,
                            NodeBuilder workspaceRoot) {
        this.versionStorageNode = checkNotNull(versionStorageNode);
        this.workspaceRoot = checkNotNull(workspaceRoot);
        this.isVersion = new TypePredicate(workspaceRoot.getNodeState(), NT_VERSION);
    }

    @NotNull
    @Override
    protected Tree getVersionStorage() {
        return TreeFactory.createReadOnlyTree(versionStorageNode.getNodeState());
    }

    @NotNull
    @Override
    protected Root getWorkspaceRoot() {
        return RootFactory.createReadOnlyRoot(workspaceRoot.getNodeState());
    }

    @NotNull
    @Override
    protected ReadOnlyNodeTypeManager getNodeTypeManager() {
        if (ntMgr == null) {
            ntMgr = ReadOnlyNodeTypeManager.getInstance(
                    getWorkspaceRoot(), NamePathMapper.DEFAULT);
        }
        return ntMgr;
    }

    /**
     * Gets or creates the version history for the given
     * {@code versionable} node.
     *
     * @param versionable the versionable node.
     * @param infoMap The additional information as provided by {@link org.apache.jackrabbit.oak.spi.commit.CommitInfo#getInfo()}
     * @return the version history node.
     * @throws IllegalArgumentException if the given node does not have a
     *                                  {@code jcr:uuid} property.
     */
    @NotNull
    public NodeBuilder getOrCreateVersionHistory(@NotNull NodeBuilder versionable, @NotNull Map<String, Object> infoMap) {
        checkNotNull(versionable);
        String vUUID = uuidFromNode(versionable);
        String relPath = getVersionHistoryPath(vUUID);
        NodeBuilder node = versionStorageNode;
        for (Iterator<String> it = PathUtils.elements(relPath).iterator(); it.hasNext(); ) {
            String name = it.next();
            node = node.child(name);
            if (!node.hasProperty(JCR_PRIMARYTYPE)) {
                String nt;
                if (it.hasNext()) {
                    nt = REP_VERSIONSTORAGE;
                } else {
                    // last path element denotes nt:versionHistory node
                    nt = NT_VERSIONHISTORY;
                }
                node.setProperty(JCR_PRIMARYTYPE, nt, Type.NAME);
            }
        }
        Object copiedFrom = infoMap.get(JCR_COPIED_FROM);
        if (copiedFrom != null) {
            node.setProperty(JCR_COPIED_FROM, copiedFrom.toString(), Type.WEAKREFERENCE);
        }

        // use jcr:rootVersion node to detect if we need to initialize the
        // version history
        if (!node.hasChildNode(JCR_ROOTVERSION)) {
            // jcr:versionableUuid property
            node.setProperty(JCR_VERSIONABLEUUID, vUUID, Type.STRING);
            node.setProperty(JCR_UUID,
                    UUIDUtils.generateUUID(), Type.STRING);

            // jcr:versionLabels child node
            NodeBuilder vLabels = node.child(JCR_VERSIONLABELS);
            vLabels.setProperty(JCR_PRIMARYTYPE, NT_VERSIONLABELS, Type.NAME);

            // jcr:rootVersion child node
            createRootVersion(node, versionable);
        } else if (!versionable.hasProperty(JCR_VERSIONHISTORY)) {
            // connect versionable node with existing history
            connectHistory(node.getChildNode(JCR_ROOTVERSION),
                    uuidFromNode(node), versionable);
        }
        return node;
    }

    void removeVersion(String versionRelPath) throws CommitFailedException {
        String historyRelPath = PathUtils.getAncestorPath(versionRelPath, 1);
        String versionName = Text.getName(versionRelPath);

        NodeBuilder vh = resolve(versionStorageNode, historyRelPath);

        if (JCR_ROOTVERSION.equals(versionName)) {
            String msg = "Removal of root version not allowed.";
            throw new CommitFailedException(CommitFailedException.VERSION, VersionExceptionCode.ROOT_VERSION_REMOVAL.ordinal(), msg);
        }

        NodeBuilder versionNode = vh.getChildNode(versionName);
        String versionId = versionNode.getProperty(JCR_UUID).getValue(Type.STRING);
        // unregister from labels
        for (String label : getVersionLabels(historyRelPath, versionId)) {
            removeVersionLabel(historyRelPath, label);
        }
        // reconnected predecessors and successors of the version being removed
        PropertyState successorIds = versionNode.getProperty(JCR_SUCCESSORS);
        PropertyState predecessorIds = versionNode.getProperty(JCR_PREDECESSORS);

        for (String succId :  successorIds.getValue(Type.REFERENCES)) {
            NodeBuilder successor = getVersionById(vh, succId);
            if (successor == null) {
                LOG.info("removeVersion : successor not found with uuid: {}, historyRelPath: {}, versionNode: {}, versionHistory: {}",
                        succId, historyRelPath, asLoggableString(versionNode), asLoggableString(vh));
                continue;
            }
            PropertyBuilder<String> pb = PropertyBuilder.array(Type.REFERENCE);
            pb.setName(JCR_PREDECESSORS);
            PropertyState successorsPredecessors = successor.getProperty(JCR_PREDECESSORS);
            if (successorsPredecessors == null) {
                LOG.info("removeVersion : successor has no jcr:predecessors property, uuid: {}, historyRelPath: {}, versionNode: {}, successor: {}, versionHistory: {}",
                        succId, historyRelPath, asLoggableString(versionNode), asLoggableString(successor), asLoggableString(vh));
            } else {
                pb.setValues(successorsPredecessors.getValue(Type.REFERENCES));
            }

            pb.removeValue(versionId);
            pb.addValues(predecessorIds.getValue(Type.REFERENCES));

            successor.setProperty(pb.getPropertyState());
        }

        for (String predId :  predecessorIds.getValue(Type.REFERENCES)) {
            NodeBuilder predecessor = getVersionById(vh, predId);
            if (predecessor == null) {
                LOG.info("removeVersion : predecessor not found with uuid: {}, historyRelPath: {}, versionNode: {}, versionHistory: {}",
                        predId, historyRelPath, asLoggableString(versionNode), asLoggableString(vh));
                continue;
            }
            PropertyBuilder<String> pb = PropertyBuilder.array(Type.REFERENCE);
            pb.setName(JCR_SUCCESSORS);
            PropertyState predecessorsSuccessors = predecessor.getProperty(JCR_SUCCESSORS);
            if (predecessorsSuccessors == null) {
                LOG.info("removeVersion : predecessor has no jcr:successors property, uuid: {}, historyRelPath: {}, versionNode: {}, predecessor: {}, versionHistory: {}",
                        predId, historyRelPath, asLoggableString(versionNode), asLoggableString(predecessor), asLoggableString(vh));
            } else {
                pb.setValues(predecessorsSuccessors.getValue(Type.REFERENCES));
            }

            pb.removeValue(versionId);
            pb.addValues(successorIds.getValue(Type.REFERENCES));

            predecessor.setProperty(pb.getPropertyState());
        }
        versionNode.remove();
    }

    /** small helper to log a node - useful for later debugging **/
    private static String asLoggableString(NodeBuilder nb) {
        try {
            final StringBuilder sb = new StringBuilder();
            boolean empty = true;
            for (PropertyState p : nb.getProperties()) {
                if (empty) {
                    empty = false;
                } else {
                    sb.append(", ");
                }
                sb.append(p);
            }
            return "{ " + sb + " }";
        } catch (Exception e) {
            return "{ exception: " + e + ", message: " + e.getMessage() + " }";
        }
    }

    public void checkout(NodeBuilder versionable) {
        versionable.setProperty(JCR_ISCHECKEDOUT, true, Type.BOOLEAN);
        PropertyState baseVersion = versionable.getProperty(JCR_BASEVERSION);
        List<String> predecessors = Collections.singletonList(baseVersion.getValue(Type.REFERENCE));
        versionable.setProperty(JCR_PREDECESSORS, predecessors, Type.REFERENCES);
    }

    public void checkin(@NotNull NodeBuilder versionable)
            throws CommitFailedException {
        NodeBuilder history = getOrCreateVersionHistory(versionable,
                Collections.<String, Object>emptyMap());
        createVersion(history, versionable);
    }

    public void restore(@NotNull NodeBuilder versionable,
                        @NotNull String versionUUID,
                        @Nullable VersionSelector selector)
            throws CommitFailedException {
        String versionPath = getIdentifierManager().getPath(versionUUID);
        NodeBuilder history = getOrCreateVersionHistory(versionable,
                Collections.<String, Object>emptyMap());
        NodeBuilder version = null;
        if (versionPath != null) {
            String versionName = PathUtils.getName(versionPath);
            if (history.hasChildNode(versionName)) {
                version = history.getChildNode(versionName);
            }
        }
        if (version == null) {
            throw new CommitFailedException(CommitFailedException.VERSION,
                    VersionExceptionCode.NO_SUCH_VERSION.ordinal(),
                    "The VersionHistory with UUID: " + uuidFromNode(versionable) +
                            " does not have a Version with UUID: " + versionUUID);
        }
        VersionableState versionableState = VersionableState.forRestore(
                version, history, versionable, this, ntMgr);
        versionableState.restore(selector);
    }

    /**
     * Restores a version from the history identified by {@code historyIdentifier}
     * using the given version {@code selector}.
     *
     * @param historyIdentifier identifier of the version history node.
     * @param selector the version selector.
     * @param versionable the versionable node where the version is restored to.
     * @throws CommitFailedException if an error occurs while restoring.
     */
    void restore(@NotNull String historyIdentifier,
                 @NotNull VersionSelector selector,
                 @NotNull NodeBuilder versionable)
            throws CommitFailedException, RepositoryException {
        String historyPath = getIdentifierManager().getPath(historyIdentifier);
        String historyRelPath = PathUtils.relativize(VERSION_STORE_PATH, historyPath);
        NodeBuilder history = resolve(versionStorageNode, historyRelPath);
        checkState(history.exists(), "Version history does not exist: " + historyPath);
        NodeBuilder version = selector.select(history);
        if (version == null) {
            throw new CommitFailedException(CommitFailedException.VERSION,
                    VersionExceptionCode.NO_VERSION_TO_RESTORE.ordinal(),
                    "VersionSelector did not select any version from " +
                            "history: " + historyPath);
        }
        // make sure versionable nodes has a jcr:uuid
        // (required to identify its version history)
        String versionableUUUID = history.getProperty(
                JCR_VERSIONABLEUUID).getValue(Type.STRING);
        versionable.setProperty(JCR_UUID, versionableUUUID, Type.STRING);
        restore(versionable, uuidFromNode(version), selector);
    }

    /**
     * Removes a version label from the jcr:versionLabels node of the referenced
     * version history.
     *
     * @param historyRelPath relative path from the jcr:versionStorage node to
     *                       the version history node.
     * @param label          the version label.
     * @throws CommitFailedException if there is no such version history or if
     * there is no label with the given name.
     */
    public void removeVersionLabel(@NotNull String historyRelPath,
                                   @NotNull String label)
            throws CommitFailedException {
        NodeBuilder labels = getVersionLabelsFor(checkNotNull(historyRelPath));
        if (!labels.hasProperty(checkNotNull(label))) {
            throw new CommitFailedException(CommitFailedException.VERSION,
                    VersionExceptionCode.NO_SUCH_VERSION_LABEL.ordinal(),
                    "Version label " + label + " does not exist on this version history");
        }
        labels.removeProperty(label);
    }

    /**
     * Removes the version history if it's empty.
     *
     * @param versionable the versionable node.
     */
    void removeEmptyHistory(@NotNull NodeState versionable) {
        NodeBuilder history = getVersionHistory(versionable);
        if (isEmptyHistory(history.getNodeState())) {
            history.remove();
        }
    }

    // TODO: more methods that modify versions

    //------------------------------< internal >--------------------------------

    /**
     * Resolves the {@code relPath} based on the given {@code node}
     * and returns the resulting node, possibly non-existing.
     *
     * @param node the resolved node.
     * @param relPath a relative path.
     * @return the resolved node.
     */
    @NotNull
    private NodeBuilder resolve(NodeBuilder node, String relPath) {
        checkArgument(!PathUtils.isAbsolute(relPath), "Not a relative path");
        for (String name : PathUtils.elements(relPath)) {
            node = node.getChildNode(name);
        }
        return node;
    }

    /**
     * Creates the root version in the given version history.
     *
     * @param vHistory the version history node.
     * @param versionable the versionable node.
     */
    private void createRootVersion(@NotNull NodeBuilder vHistory,
                                   @NotNull NodeBuilder versionable) {
        String versionUUID = UUIDUtils.generateUUID();
        NodeBuilder version = vHistory.child(JCR_ROOTVERSION);
        version.setProperty(JCR_UUID, versionUUID, Type.STRING);
        version.setProperty(JCR_PRIMARYTYPE, NT_VERSION, Type.NAME);
        version.setProperty(JCR_CREATED, ISO8601.format(Calendar.getInstance()), Type.DATE);
        version.setProperty(JCR_PREDECESSORS, Collections.emptyList(), Type.REFERENCES);
        version.setProperty(JCR_SUCCESSORS, Collections.emptyList(), Type.REFERENCES);

        // incomplete frozen node on root-version (don't call create on versionable-state)
        VersionableState.fromVersion(version, vHistory, versionable, this, getNodeTypeManager());

        // set jcr:isCheckedOut, jcr:versionHistory, jcr:baseVersion and
        // jcr:predecessors on versionable node
        versionable.setProperty(JCR_ISCHECKEDOUT, true, Type.BOOLEAN);
        versionable.setProperty(JCR_VERSIONHISTORY, uuidFromNode(vHistory), Type.REFERENCE);
        versionable.setProperty(JCR_BASEVERSION, versionUUID, Type.REFERENCE);
        // set predecessors to base version for the root version
        versionable.setProperty(JCR_PREDECESSORS, Collections.singletonList(versionUUID), Type.REFERENCES);
    }

    /**
     * Creates a version in the given version history. If the given version
     * history does not yet have a version, then a root version is created and
     * the versionable node is in a checked out state. Otherwise a version is
     * created and the versionable node is set to checked in.
     *
     * @param vHistory the version history node.
     * @param versionable the versionable node.
     * @throws CommitFailedException if creating the version fails. E.g. because
     * the versionable node contains a OPV item with ABORT.
     */
    private void createVersion(@NotNull NodeBuilder vHistory,
                                      @NotNull NodeBuilder versionable)
            throws IllegalArgumentException, CommitFailedException {
        if (!vHistory.hasChildNode(JCR_ROOTVERSION)) {
            createRootVersion(vHistory, versionable);
            return;
        }

        checkState(versionable.hasProperty(JCR_PREDECESSORS));
        PropertyState state = versionable.getProperty(JCR_PREDECESSORS);
        List<String> predecessors = ImmutableList.copyOf(state.getValue(Type.REFERENCES));
        NodeBuilder version = vHistory.child(calculateVersion(vHistory, versionable));

        String versionUUID = UUIDUtils.generateUUID();
        version.setProperty(JCR_UUID, versionUUID, Type.STRING);
        version.setProperty(JCR_PRIMARYTYPE, NT_VERSION, Type.NAME);
        version.setProperty(JCR_CREATED, ISO8601.format(Calendar.getInstance()), Type.DATE);
        version.setProperty(JCR_PREDECESSORS, predecessors, Type.REFERENCES);
        version.setProperty(JCR_SUCCESSORS, Collections.<String>emptyList(), Type.REFERENCES);

        // update successors of versions identified by predecessors
        for (String id : predecessors) {
            String name = PathUtils.getName(getIdentifierManager().getPath(id));
            NodeBuilder predecessor = vHistory.getChildNode(name);
            state = predecessor.getProperty(JCR_SUCCESSORS);
            if (state == null) {
                throw new IllegalStateException("Missing " + JCR_SUCCESSORS +
                        " property on " + predecessor);
            }
            Set<String> refs = Sets.newHashSet(state.getValue(Type.REFERENCES));
            refs.add(versionUUID);
            predecessor.setProperty(JCR_SUCCESSORS, refs, Type.REFERENCES);
        }

        // jcr:frozenNode of created version
        VersionableState versionableState = VersionableState.fromVersion(version, vHistory, versionable, this, getNodeTypeManager());
        versionableState.create();

        // set jcr:isCheckedOut, jcr:versionHistory, jcr:baseVersion and
        // jcr:predecessors on versionable node
        versionable.setProperty(JCR_ISCHECKEDOUT, false, Type.BOOLEAN);
        versionable.setProperty(JCR_VERSIONHISTORY, uuidFromNode(vHistory), Type.REFERENCE);
        versionable.setProperty(JCR_BASEVERSION, versionUUID, Type.REFERENCE);
        // clear predecessors for check-in
        versionable.setProperty(JCR_PREDECESSORS, Collections.emptyList(), Type.REFERENCES);
    }

    /**
     * Connects a versionable node with the root version of an existing version
     * history.
     *
     * @param rootVersion the root version of a version history.
     * @param vHistoryUUID the uuid of the version history node.
     * @param versionable the versionable node.
     */
    private void connectHistory(@NotNull NodeBuilder rootVersion,
                                @NotNull String vHistoryUUID,
                                @NotNull NodeBuilder versionable) {
        String rootVersionUUID = uuidFromNode(rootVersion);
        versionable.setProperty(JCR_ISCHECKEDOUT, true, Type.BOOLEAN);
        versionable.setProperty(JCR_VERSIONHISTORY, vHistoryUUID, Type.REFERENCE);
        versionable.setProperty(JCR_BASEVERSION, rootVersionUUID, Type.REFERENCE);
        versionable.setProperty(JCR_PREDECESSORS,
                Collections.singleton(rootVersionUUID), Type.REFERENCES);
    }

    /**
     * <i>Copied from Apache Jackrabbit Core</i>
     * <p>
     * Calculates the name of the new version that will be created by a
     * checkin call. The name is determined as follows:
     * <ul>
     * <li> first the predecessor version with the shortest name is searched.
     * <li> if that predecessor version is the root version, the new version gets
     *      the name "{number of successors}+1" + ".0"
     * <li> if that predecessor version has no successor, the last digit of it's
     *      version number is incremented.
     * <li> if that predecessor version has successors but the incremented name
     *      does not exist, that name is used.
     * <li> otherwise a ".0" is added to the name until a non conflicting name
     *      is found.
     * </ul>
     * <p>
     * Example Graph:
     * <pre>
     * jcr:rootVersion
     *  |     |
     * 1.0   2.0
     *  |
     * 1.1
     *  |
     * 1.2 ---\  ------\
     *  |      \        \
     * 1.3   1.2.0   1.2.0.0
     *  |      |
     * 1.4   1.2.1 ----\
     *  |      |        \
     * 1.5   1.2.2   1.2.1.0
     *  |      |        |
     * 1.6     |     1.2.1.1
     *  |-----/
     * 1.7
     * </pre>
     *
     * @param history the version history
     * @param versionable the node to checkin
     * @return the new version name
     * @throws IllegalStateException if mandatory version properties are missing.
     */
    protected String calculateVersion(@NotNull NodeBuilder history,
                                      @NotNull NodeBuilder versionable)
            throws IllegalStateException {

        // 1. search a predecessor, suitable for generating the new name
        PropertyState predecessors = versionable.getProperty(JCR_PREDECESSORS);

        if (predecessors == null || predecessors.count() == 0) {
            String message;
            if (predecessors == null) {
                message = "Mandatory jcr:predecessors property missing on node " + uuidFromNode(versionable);
            } else {
                message = "Mandatory jcr:predecessors property is empty on node " + uuidFromNode(versionable);
            }
            throw new IllegalStateException(message);
        }

        String best = null;
        for (String id : predecessors.getValue(Type.REFERENCES)) {
            String name = PathUtils.getName(getIdentifierManager().getPath(id));
            if (best == null || name.length() < best.length()) {
                best = name;
            }
        }

        if (best == null) {
            String message = "Could not find 'best' predecessor node for " +
                    uuidFromNode(versionable);
            throw new IllegalStateException(message);
        }

        // 2. generate version name (assume no namespaces in version names)
        String versionName = best;
        int pos = versionName.lastIndexOf('.');
        if (pos > 0) {
            String newVersionName = versionName.substring(0, pos + 1)
                    + (Integer.parseInt(versionName.substring(pos + 1)) + 1);
            while (history.hasChildNode(newVersionName)) {
                versionName += ".0";
                newVersionName = versionName;
            }
            return newVersionName;
        } else {
            // best is root version
            checkState(history.hasChildNode(JCR_ROOTVERSION));
            NodeBuilder v = history.getChildNode(JCR_ROOTVERSION);
            return String.valueOf(v.getProperty(JCR_SUCCESSORS).count() + 1) + ".0";
        }
    }

    /**
     * Returns the jcr:versionLabels node of the version history referenced
     * by the given path.
     *
     * @param historyRelPath relative path from the jcr:versionStorage node
     *                       to the history node.
     * @return the jcr:versionLabels node.
     * @throws CommitFailedException if there is no version history at the
     * given path.
     */
    private NodeBuilder getVersionLabelsFor(String historyRelPath)
            throws CommitFailedException {
        NodeBuilder history = resolve(versionStorageNode, historyRelPath);
        if (!history.exists()) {
            throw new CommitFailedException(CommitFailedException.VERSION,
                    VersionExceptionCode.UNEXPECTED_REPOSITORY_EXCEPTION.ordinal(),
                    "Version history does not exist: " + PathUtils.concat(
                            VERSION_STORE_PATH, historyRelPath));
        }
        return history.child(JCR_VERSIONLABELS);
    }

    @NotNull
    private Iterable<String> getVersionLabels(@NotNull String historyRelPath, @NotNull String versionId) throws CommitFailedException {
        List<String> labels = new ArrayList<String>();
        NodeBuilder labelNode = getVersionLabelsFor(historyRelPath);
        for (PropertyState ps : labelNode.getProperties()) {
            if (Type.REFERENCE == ps.getType()) {
                if (versionId.equals(ps.getValue(Type.REFERENCE))) {
                    labels.add(ps.getName());
                }
            }
        }
        return labels;
    }

    @Nullable
    private NodeBuilder getVersionById(@NotNull NodeBuilder vhBuilder, @NotNull String versionId) {
        for (String childName : vhBuilder.getChildNodeNames()) {
            NodeBuilder nb = vhBuilder.getChildNode(childName);
            PropertyState uuid = nb.getProperty(JCR_UUID);
            if (uuid != null && versionId.equals(uuid.getValue(Type.STRING))) {
                return nb;
            }
        }
        return null;
    }

    /**
     * Gets the version history for the given
     * {@code versionable} node.
     *
     * @param versionable the versionable node.
     * @return the version history node.
     * @throws IllegalArgumentException if the given node does not have a
     *                                  {@code jcr:uuid} property.
     */
    @NotNull
    private NodeBuilder getVersionHistory(@NotNull NodeState versionable) {
        checkNotNull(versionable);
        String vUUID = uuidFromNode(versionable);
        String relPath = getVersionHistoryPath(vUUID);
        NodeBuilder node = versionStorageNode;
        for (Iterator<String> it = PathUtils.elements(relPath).iterator(); it.hasNext(); ) {
            String name = it.next();
            node = node.getChildNode(name);
            if (!node.exists()) {
                throw new IllegalArgumentException("No version history for this node");
            }
        }
        return node;
    }

    /**
     * Checks whether the passed node history hasn't been modified since its
     * creation. It means that: (1) there's just one version, called jcr:rootVersion
     * and (2) there are no custom labels.
     *
     * @param versionHistory to test
     * @return {@code true} if the version history hasn't been changed yet
     */
    private boolean isEmptyHistory(NodeState versionHistory) {
        for (ChildNodeEntry entry : versionHistory.getChildNodeEntries()) {
            String name = entry.getName();
            NodeState node = entry.getNodeState();
            if (!JCR_ROOTVERSION.equals(name) && isVersion.test(node)) {
                return false; // a checked-in version
            }
        }
        NodeState labels = versionHistory.getChildNode(JCR_VERSIONLABELS);
        for (PropertyState prop : labels.getProperties()) {
            if (prop.getType() == Type.REFERENCE) {
                return false; // custom label
            }
        }
        return true;
    }

}
