/*
 * 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.type;

import java.util.HashMap;

/**
 * Representation of a method descriptor. Instances of this class are
 * generally interned and may be usefully compared with each other
 * using {@code ==}.
 */
public final class Prototype implements Comparable<Prototype> {
    /** {@code non-null;} intern table mapping string descriptors to instances */
    private static final HashMap<String, Prototype> internTable =
        new HashMap<String, Prototype>(500);

    /** {@code non-null;} method descriptor */
    private final String descriptor;

    /** {@code non-null;} return type */
    private final Type returnType;

    /** {@code non-null;} list of parameter types */
    private final StdTypeList parameterTypes;

    /** {@code null-ok;} list of parameter frame types, if calculated */
    private StdTypeList parameterFrameTypes;

    /**
     * Returns the unique instance corresponding to the
     * given method descriptor. See vmspec-2 sec4.3.3 for details on the
     * field descriptor syntax.
     *
     * @param descriptor {@code non-null;} the descriptor
     * @return {@code non-null;} the corresponding instance
     * @throws IllegalArgumentException thrown if the descriptor has
     * invalid syntax
     */
    public static Prototype intern(String descriptor) {
        if (descriptor == null) {
            throw new NullPointerException("descriptor == null");
        }

        Prototype result;
        synchronized (internTable) {
            result = internTable.get(descriptor);
        }
        if (result != null) {
            return result;
        }

        Type[] params = makeParameterArray(descriptor);
        int paramCount = 0;
        int at = 1;

        for (;;) {
            int startAt = at;
            char c = descriptor.charAt(at);
            if (c == ')') {
                at++;
                break;
            }

            // Skip array markers.
            while (c == '[') {
                at++;
                c = descriptor.charAt(at);
            }

            if (c == 'L') {
                // It looks like the start of a class name; find the end.
                int endAt = descriptor.indexOf(';', at);
                if (endAt == -1) {
                    throw new IllegalArgumentException("bad descriptor");
                }
                at = endAt + 1;
            } else {
                at++;
            }

            params[paramCount] =
                Type.intern(descriptor.substring(startAt, at));
            paramCount++;
        }

        Type returnType = Type.internReturnType(descriptor.substring(at));
        StdTypeList parameterTypes = new StdTypeList(paramCount);

        for (int i = 0; i < paramCount; i++) {
            parameterTypes.set(i, params[i]);
        }

        result = new Prototype(descriptor, returnType, parameterTypes);
        return putIntern(result);
    }

    /**
     * Helper for {@link #intern} which returns an empty array to
     * populate with parsed parameter types, and which also ensures
     * that there is a '(' at the start of the descriptor and a
     * single ')' somewhere before the end.
     *
     * @param descriptor {@code non-null;} the descriptor string
     * @return {@code non-null;} array large enough to hold all parsed parameter
     * types, but which is likely actually larger than needed
     */
    private static Type[] makeParameterArray(String descriptor) {
        int length = descriptor.length();

        if (descriptor.charAt(0) != '(') {
            throw new IllegalArgumentException("bad descriptor");
        }

        /*
         * This is a cheesy way to establish an upper bound on the
         * number of parameters: Just count capital letters.
         */
        int closeAt = 0;
        int maxParams = 0;
        for (int i = 1; i < length; i++) {
            char c = descriptor.charAt(i);
            if (c == ')') {
                closeAt = i;
                break;
            }
            if ((c >= 'A') && (c <= 'Z')) {
                maxParams++;
            }
        }

        if ((closeAt == 0) || (closeAt == (length - 1))) {
            throw new IllegalArgumentException("bad descriptor");
        }

        if (descriptor.indexOf(')', closeAt + 1) != -1) {
            throw new IllegalArgumentException("bad descriptor");
        }

        return new Type[maxParams];
    }

    /**
     * Interns an instance, adding to the descriptor as necessary based
     * on the given definer, name, and flags. For example, an init
     * method has an uninitialized object of type {@code definer}
     * as its first argument.
     *
     * @param descriptor {@code non-null;} the descriptor string
     * @param definer {@code non-null;} class the method is defined on
     * @param isStatic whether this is a static method
     * @param isInit whether this is an init method
     * @return {@code non-null;} the interned instance
     */
    public static Prototype intern(String descriptor, Type definer,
            boolean isStatic, boolean isInit) {
        Prototype base = intern(descriptor);

        if (isStatic) {
            return base;
        }

        if (isInit) {
            definer = definer.asUninitialized(Integer.MAX_VALUE);
        }

        return base.withFirstParameter(definer);
    }

    /**
     * Interns an instance which consists of the given number of
     * {@code int}s along with the given return type
     *
     * @param returnType {@code non-null;} the return type
     * @param count {@code > 0;} the number of elements in the prototype
     * @return {@code non-null;} the interned instance
     */
    public static Prototype internInts(Type returnType, int count) {
        // Make the descriptor...

        StringBuffer sb = new StringBuffer(100);

        sb.append('(');

        for (int i = 0; i < count; i++) {
            sb.append('I');
        }

        sb.append(')');
        sb.append(returnType.getDescriptor());

        // ...and intern it.
        return intern(sb.toString());
    }

    /**
     * Constructs an instance. This is a private constructor; use one
     * of the public static methods to get instances.
     *
     * @param descriptor {@code non-null;} the descriptor string
     */
    private Prototype(String descriptor, Type returnType,
            StdTypeList parameterTypes) {
        if (descriptor == null) {
            throw new NullPointerException("descriptor == null");
        }

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

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

        this.descriptor = descriptor;
        this.returnType = returnType;
        this.parameterTypes = parameterTypes;
        this.parameterFrameTypes = null;
    }

    /** {@inheritDoc} */
    @Override
    public boolean equals(Object other) {
        if (this == other) {
            /*
             * Since externally-visible instances are interned, this
             * check helps weed out some easy cases.
             */
            return true;
        }

        if (!(other instanceof Prototype)) {
            return false;
        }

        return descriptor.equals(((Prototype) other).descriptor);
    }

    /** {@inheritDoc} */
    @Override
    public int hashCode() {
        return descriptor.hashCode();
    }

    /** {@inheritDoc} */
    public int compareTo(Prototype other) {
        if (this == other) {
            return 0;
        }

        /*
         * The return type is the major order, and then args in order,
         * and then the shorter list comes first (similar to string
         * sorting).
         */

        int result = returnType.compareTo(other.returnType);

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

        int thisSize = parameterTypes.size();
        int otherSize = other.parameterTypes.size();
        int size = Math.min(thisSize, otherSize);

        for (int i = 0; i < size; i++) {
            Type thisType = parameterTypes.get(i);
            Type otherType = other.parameterTypes.get(i);

            result = thisType.compareTo(otherType);

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

        if (thisSize < otherSize) {
            return -1;
        } else if (thisSize > otherSize) {
            return 1;
        } else {
            return 0;
        }
    }

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

    /**
     * Gets the descriptor string.
     *
     * @return {@code non-null;} the descriptor
     */
    public String getDescriptor() {
        return descriptor;
    }

    /**
     * Gets the return type.
     *
     * @return {@code non-null;} the return type
     */
    public Type getReturnType() {
        return returnType;
    }

    /**
     * Gets the list of parameter types.
     *
     * @return {@code non-null;} the list of parameter types
     */
    public StdTypeList getParameterTypes() {
        return parameterTypes;
    }

    /**
     * Gets the list of frame types corresponding to the list of parameter
     * types. The difference between the two lists (if any) is that all
     * "intlike" types (see {@link Type#isIntlike}) are replaced by
     * {@link Type#INT}.
     *
     * @return {@code non-null;} the list of parameter frame types
     */
    public StdTypeList getParameterFrameTypes() {
        if (parameterFrameTypes == null) {
            int sz = parameterTypes.size();
            StdTypeList list = new StdTypeList(sz);
            boolean any = false;
            for (int i = 0; i < sz; i++) {
                Type one = parameterTypes.get(i);
                if (one.isIntlike()) {
                    any = true;
                    one = Type.INT;
                }
                list.set(i, one);
            }
            parameterFrameTypes = any ? list : parameterTypes;
        }

        return parameterFrameTypes;
    }

    /**
     * Returns a new interned instance, which is the same as this instance,
     * except that it has an additional parameter prepended to the original's
     * argument list.
     *
     * @param param {@code non-null;} the new first parameter
     * @return {@code non-null;} an appropriately-constructed instance
     */
    public Prototype withFirstParameter(Type param) {
        String newDesc = "(" + param.getDescriptor() + descriptor.substring(1);
        StdTypeList newParams = parameterTypes.withFirst(param);

        newParams.setImmutable();

        Prototype result =
            new Prototype(newDesc, returnType, newParams);

        return putIntern(result);
    }

    /**
     * Puts the given instance in the intern table if it's not already
     * there. If a conflicting value is already in the table, then leave it.
     * Return the interned value.
     *
     * @param desc {@code non-null;} instance to make interned
     * @return {@code non-null;} the actual interned object
     */
    private static Prototype putIntern(Prototype desc) {
        synchronized (internTable) {
            String descriptor = desc.getDescriptor();
            Prototype already = internTable.get(descriptor);
            if (already != null) {
                return already;
            }
            internTable.put(descriptor, desc);
            return desc;
        }
    }
}
