/* Copyright (c) 2013 OpenPlans. All rights reserved.
 * This code is licensed under the BSD New License, available at the root
 * application directory.
 */
package org.geogit.api;

import org.geogit.api.RevObject.TYPE;

import com.google.common.base.Preconditions;

/**
 * Pairing of a name and the {@link ObjectId} it currently has.
 * <p>
 * A ref in Git is (more or less) a variable that holds a single object identifier. The object
 * identifier can be any valid Git object (blob, tree, commit, annotated tag, ...).
 * <p>
 * The ref name has the attributes of the ref that was asked for as well as the ref it was resolved
 * to for symbolic refs plus the object id it points to and (for tags) the peeled target object id,
 * i.e. the tag resolved recursively until a non-tag object is referenced.
 */
public class Ref implements Comparable<Ref> {

    /**
     * By convention, name of the main branch
     */
    public static final String MASTER = "refs/heads/master";

    /**
     * Pointer to the latest commit in the current branch
     */
    public static final String HEAD = "HEAD";

    /**
     * Pointer to the current tree in the staging index
     */
    public static final String STAGE_HEAD = "STAGE_HEAD";

    /**
     * Pointer to the current tree in the working directory
     */
    public static final String WORK_HEAD = "WORK_HEAD";

    /**
     * Pointer to the commit to be merged during a merge operation
     */
    public static final String MERGE_HEAD = "MERGE_HEAD";

    /**
     * Pointer to the commit to be picked during a cherry-pick operation
     */
    public static final String CHERRY_PICK_HEAD = "CHERRY_PICK_HEAD";

    /**
     * Pointer to the commit onto which another commit is to be merged during a merge operation
     */
    public static final String ORIG_HEAD = "ORIG_HEAD";

    /**
     * Directory prefix for refs.
     */
    public static final String REFS_PREFIX = "refs/";

    /**
     * Directory prefix for remotes.
     */
    public static final String REMOTES_PREFIX = REFS_PREFIX + "remotes/";

    /**
     * Directory prefix for tags.
     */
    public static final String TAGS_PREFIX = REFS_PREFIX + "tags/";

    /**
     * Directory prefix for heads.
     */
    public static final String HEADS_PREFIX = REFS_PREFIX + "heads/";

    /**
     * By convention, the origin of the repository
     */
    public static final String ORIGIN = "refs/remotes/origin";

    private String name;

    private ObjectId objectId;

    /**
     * Constructs a new Ref with the given parameters.
     * 
     * @param name name of this ref
     * @param oid object id for this ref
     */
    public Ref(final String name, final ObjectId oid) {
        Preconditions.checkNotNull(name);
        Preconditions.checkNotNull(oid);
        this.name = name;
        this.objectId = oid;
    }

    /**
     * @return {@link TYPE#COMMIT}
     * @deprecated this method is scheduled to be removed in 0.9.0 as its practically of no use and
     *             forces ref-parse to unnecessarily call on resolve-object-type, which can be
     *             called separately in case some client code needs to figure out what kind of
     *             object a ref points to with the ref's object id as argument.
     */
    @Deprecated
    public RevObject.TYPE getType() {
        return RevObject.TYPE.COMMIT;
    }

    /**
     * @return the name for this ref
     */
    public String getName() {
        return name;
    }

    /**
     * @return the name for this ref with the prefix removed
     */
    public String localName() {
        return localName(name);
    }

    /**
     * @param ref the ref string
     * @return the local name of the given ref string
     */
    public static String localName(final String ref) {

        if (ref.startsWith(HEADS_PREFIX)) {
            return ref.substring(HEADS_PREFIX.length());
        } else if (ref.startsWith(TAGS_PREFIX)) {
            return ref.substring(TAGS_PREFIX.length());
        } else if (ref.startsWith(REMOTES_PREFIX)) {
            String remoteWithBranch = ref.substring(REMOTES_PREFIX.length());
            return remoteWithBranch.substring(remoteWithBranch.indexOf('/') + 1);
        } else if (ref.startsWith(REFS_PREFIX)) {
            return ref.substring(REFS_PREFIX.length());
        }
        return ref;
    }

    /**
     * @return the namespace for this ref
     */
    public String namespace() {
        return namespace(name);
    }

    /**
     * @param ref the ref string
     * @return the namespace of the given ref string
     */
    public static String namespace(final String ref) {
        if (ref.startsWith(HEADS_PREFIX)) {
            return HEADS_PREFIX;
        } else if (ref.startsWith(TAGS_PREFIX)) {
            return TAGS_PREFIX;
        } else if (ref.startsWith(REMOTES_PREFIX)) {
            String remote = ref.substring(REMOTES_PREFIX.length());
            remote = remote.substring(0, remote.indexOf('/'));
            return REMOTES_PREFIX + "/" + remote;
        } else if (ref.startsWith(REFS_PREFIX)) {
            return REFS_PREFIX;
        }
        return ref;
    }

    /**
     * @return the object id being referenced
     */
    public ObjectId getObjectId() {
        return objectId;
    }

    /**
     * @param o object to compare against
     * @return whether or not this ref is equal to the target object
     */
    @Override
    public boolean equals(Object o) {
        if (!(o instanceof Ref)) {
            return false;
        }
        Ref r = (Ref) o;
        return name.equals(r.getName()) && objectId.equals(r.getObjectId());
    }

    /**
     * @return a hash code for this ref
     */
    @Override
    public int hashCode() {
        return name.hashCode() * objectId.hashCode();
    }

    /**
     * @see java.lang.Comparable#compareTo(java.lang.Object)
     */
    @Override
    public int compareTo(Ref o) {
        return name.compareTo(o.getName());
    }

    /**
     * @return the ref represented by a readable string
     */
    @Override
    public String toString() {
        return new StringBuilder("Ref").append('[').append(name).append(" -> ").append(objectId)
                .append(']').toString();
    }

    public static String append(String namespace, String child) {
        StringBuilder sb = new StringBuilder();
        if (namespace.endsWith("/")) {
            namespace = namespace.substring(0, namespace.length() - 1);
        }
        sb.append(namespace);

        if (child.length() > 0 && child.charAt(0) == '/') {
            child = child.substring(1);
        }
        if (child.endsWith("/")) {
            child = child.substring(0, child.length() - 1);
        }
        if (!child.isEmpty()) {
            if (!namespace.isEmpty()) {
                sb.append('/');
            }
            sb.append(child);
        }
        return sb.toString();
    }

    /**
     * @return the relative name of the ref given by its full name and the namespace to truncate
     */
    public static String child(String namespace, String ref) {
        Preconditions.checkState(ref.startsWith(namespace));
        String relative = ref.substring(namespace.length());
        if (relative.length() > 0 && relative.charAt(0) == '/') {
            relative = relative.substring(1);
        }
        return relative;
    }
}
@@ -180,47 +180,8 @@
 i;%0A%0A
-import org.geogit.api.RevObject.TYPE;%0A%0A
 impo
@@ -2813,528 +2813,8 @@
  %7D%0A%0A
-    /**%0A     * @return %7B@link TYPE#COMMIT%7D%0A     * @deprecated this method is scheduled to be removed in 0.9.0 as its practically of no use and%0A     *             forces ref-parse to unnecessarily call on resolve-object-type, which can be%0A     *             called separately in case some client code needs to figure out what kind of%0A     *             object a ref points to with the ref's object id as argument.%0A     */%0A    @Deprecated%0A    public RevObject.TYPE getType() %7B%0A        return RevObject.TYPE.COMMIT;%0A    %7D%0A%0A
     

Remove method Ref.getType() deprecated in 0.8. Already unused.