/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed 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 com.android.dx.rop.annotation;

import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.cst.CstType;
import com.android.dx.util.MutabilityControl;
import com.android.dx.util.ToHuman;

import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.TreeMap;

/**
 * An annotation on an element of a class. Annotations have an
 * associated type and additionally consist of a set of (name, value)
 * pairs, where the names are unique.
 */
public final class Annotation extends MutabilityControl
        implements Comparable<Annotation>, ToHuman {
    /** {@code non-null;} type of the annotation */
    private final CstType type;

    /** {@code non-null;} the visibility of the annotation */
    private final AnnotationVisibility visibility;

    /** {@code non-null;} map from names to {@link NameValuePair} instances */
    private final TreeMap<CstString, NameValuePair> elements;

    /**
     * Construct an instance. It initially contains no elements.
     *
     * @param type {@code non-null;} type of the annotation
     * @param visibility {@code non-null;} the visibility of the annotation
     */
    public Annotation(CstType type, AnnotationVisibility visibility) {
        if (type == null) {
            throw new NullPointerException("type == null");
        }

        if (visibility == null) {
            throw new NullPointerException("visibility == null");
        }

        this.type = type;
        this.visibility = visibility;
        this.elements = new TreeMap<CstString, NameValuePair>();
    }

    /** {@inheritDoc} */
    @Override
    public boolean equals(Object other) {
        if (! (other instanceof Annotation)) {
            return false;
        }

        Annotation otherAnnotation = (Annotation) other;

        if (! (type.equals(otherAnnotation.type)
                        && (visibility == otherAnnotation.visibility))) {
            return false;
        }

        return elements.equals(otherAnnotation.elements);
    }

    /** {@inheritDoc} */
    public int hashCode() {
        int hash = type.hashCode();
        hash = (hash * 31) + elements.hashCode();
        hash = (hash * 31) + visibility.hashCode();
        return hash;
    }

    /** {@inheritDoc} */
    public int compareTo(Annotation other) {
        int result = type.compareTo(other.type);

        if (result != 0) {
            return result;
        }

        result = visibility.compareTo(other.visibility);

        if (result != 0) {
            return result;
        }

        Iterator<NameValuePair> thisIter = elements.values().iterator();
        Iterator<NameValuePair> otherIter = other.elements.values().iterator();

        while (thisIter.hasNext() && otherIter.hasNext()) {
            NameValuePair thisOne = thisIter.next();
            NameValuePair otherOne = otherIter.next();

            result = thisOne.compareTo(otherOne);
            if (result != 0) {
                return result;
            }
        }

        if (thisIter.hasNext()) {
            return 1;
        } else if (otherIter.hasNext()) {
            return -1;
        }

        return 0;
    }

    /** {@inheritDoc} */
    @Override
    public String toString() {
        return toHuman();
    }

    /** {@inheritDoc} */
    public String toHuman() {
        StringBuilder sb = new StringBuilder();

        sb.append(visibility.toHuman());
        sb.append("-annotation ");
        sb.append(type.toHuman());
        sb.append(" {");

        boolean first = true;
        for (NameValuePair pair : elements.values()) {
            if (first) {
                first = false;
            } else {
                sb.append(", ");
            }
            sb.append(pair.getName().toHuman());
            sb.append(": ");
            sb.append(pair.getValue().toHuman());
        }

        sb.append("}");
        return sb.toString();
    }

    /**
     * Gets the type of this instance.
     *
     * @return {@code non-null;} the type
     */
    public CstType getType() {
        return type;
    }

    /**
     * Gets the visibility of this instance.
     *
     * @return {@code non-null;} the visibility
     */
    public AnnotationVisibility getVisibility() {
        return visibility;
    }

    /**
     * Put an element into the set of (name, value) pairs for this instance.
     * If there is a preexisting element with the same name, it will be
     * replaced by this method.
     *
     * @param pair {@code non-null;} the (name, value) pair to place into this instance
     */
    public void put(NameValuePair pair) {
        throwIfImmutable();

        if (pair == null) {
            throw new NullPointerException("pair == null");
        }

        elements.put(pair.getName(), pair);
    }

    /**
     * Add an element to the set of (name, value) pairs for this instance.
     * It is an error to call this method if there is a preexisting element
     * with the same name.
     *
     * @param pair {@code non-null;} the (name, value) pair to add to this instance
     */
    public void add(NameValuePair pair) {
        throwIfImmutable();

        if (pair == null) {
            throw new NullPointerException("pair == null");
        }

        CstString name = pair.getName();

        if (elements.get(name) != null) {
            throw new IllegalArgumentException("name already added: " + name);
        }

        elements.put(name, pair);
    }

    /**
     * Gets the set of name-value pairs contained in this instance. The
     * result is always unmodifiable.
     *
     * @return {@code non-null;} the set of name-value pairs
     */
    public Collection<NameValuePair> getNameValuePairs() {
        return Collections.unmodifiableCollection(elements.values());
    }
}
