/*
 * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.tools.jdi;

import com.sun.jdi.*;

import java.util.List;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.Comparator;

public abstract class MethodImpl extends TypeComponentImpl
    implements Method {
    private JNITypeParser signatureParser;
    abstract int argSlotCount() throws AbsentInformationException;

    abstract List<Location> allLineLocations(SDE.Stratum stratum,
                                   String sourceName)
                           throws AbsentInformationException;

    abstract List<Location> locationsOfLine(SDE.Stratum stratum,
                                  String sourceName,
                                  int lineNumber)
                           throws AbsentInformationException;

    MethodImpl(VirtualMachine vm, ReferenceTypeImpl declaringType,
               long ref,
               String name, String signature,
               String genericSignature, int modifiers) {
        super(vm, declaringType, ref, name, signature,
              genericSignature, modifiers);
        signatureParser = new JNITypeParser(signature);
    }

    static MethodImpl createMethodImpl(VirtualMachine vm,
                                       ReferenceTypeImpl declaringType,
                                       long ref,
                                       String name,
                                       String signature,
                                       String genericSignature,
                                       int modifiers) {
        if ((modifiers &
             (VMModifiers.NATIVE | VMModifiers.ABSTRACT)) != 0) {
            return new NonConcreteMethodImpl(vm, declaringType, ref,
                                             name, signature,
                                             genericSignature,
                                             modifiers);
        } else {
            return new ConcreteMethodImpl(vm, declaringType, ref,
                                          name, signature,
                                          genericSignature,
                                          modifiers);
        }
    }

    public boolean equals(Object obj) {
        if ((obj != null) && (obj instanceof MethodImpl)) {
            MethodImpl other = (MethodImpl)obj;
            return (declaringType().equals(other.declaringType())) &&
                   (ref() == other.ref()) &&
                   super.equals(obj);
        } else {
            return false;
        }
    }

    public int hashCode() {
        return (int)ref();
    }

    public final List<Location> allLineLocations()
                           throws AbsentInformationException {
        return allLineLocations(vm.getDefaultStratum(), null);
    }

    public List<Location> allLineLocations(String stratumID,
                                 String sourceName)
                           throws AbsentInformationException {
        return allLineLocations(declaringType.stratum(stratumID),
                                sourceName);
    }

    public final List<Location> locationsOfLine(int lineNumber)
                           throws AbsentInformationException {
        return locationsOfLine(vm.getDefaultStratum(),
                               null, lineNumber);
    }

    public List<Location> locationsOfLine(String stratumID,
                                String sourceName,
                                int lineNumber)
                           throws AbsentInformationException {
        return locationsOfLine(declaringType.stratum(stratumID),
                               sourceName, lineNumber);
    }

    LineInfo codeIndexToLineInfo(SDE.Stratum stratum,
                                 long codeIndex) {
        if (stratum.isJava()) {
            return new BaseLineInfo(-1, declaringType);
        } else {
            return new StratumLineInfo(stratum.id(), -1,
                                       null, null);
        }
    }

    /**
     * @return a text representation of the declared return type
     * of this method.
     */
    public String returnTypeName() {
        return signatureParser.typeName();
    }

    private String returnSignature() {
        return signatureParser.signature();
    }

    public Type returnType() throws ClassNotLoadedException {
        return findType(returnSignature());
    }

    public Type findType(String signature) throws ClassNotLoadedException {
        ReferenceTypeImpl enclosing = (ReferenceTypeImpl)declaringType();
        return enclosing.findType(signature);
    }

    public List<String> argumentTypeNames() {
        return signatureParser.argumentTypeNames();
    }

    public List<String> argumentSignatures() {
        return signatureParser.argumentSignatures();
    }

    Type argumentType(int index) throws ClassNotLoadedException {
        ReferenceTypeImpl enclosing = (ReferenceTypeImpl)declaringType();
        String signature = argumentSignatures().get(index);
        return enclosing.findType(signature);
    }

    public List<Type> argumentTypes() throws ClassNotLoadedException {
        int size = argumentSignatures().size();
        ArrayList<Type> types = new ArrayList<Type>(size);
        for (int i = 0; i < size; i++) {
            Type type = argumentType(i);
            types.add(type);
        }

        return types;
    }

    public int compareTo(Method method) {
        ReferenceTypeImpl declaringType = (ReferenceTypeImpl)declaringType();
        int rc = declaringType.compareTo(method.declaringType());
        if (rc == 0) {
            rc = declaringType.indexOf(this) -
                    declaringType.indexOf(method);
        }
        return rc;
    }

    public boolean isAbstract() {
        return isModifierSet(VMModifiers.ABSTRACT);
    }

    public boolean isSynchronized() {
        return isModifierSet(VMModifiers.SYNCHRONIZED);
    }

    public boolean isNative() {
        return isModifierSet(VMModifiers.NATIVE);
    }

    public boolean isVarArgs() {
        return isModifierSet(VMModifiers.VARARGS);
    }

    public boolean isBridge() {
        return isModifierSet(VMModifiers.BRIDGE);
    }

    public boolean isConstructor() {
        return name().equals("<init>");
    }

    public boolean isStaticInitializer() {
        return name().equals("<clinit>");
    }

    public boolean isObsolete() {
        try {
            return JDWP.Method.IsObsolete.process(vm,
                                    declaringType, ref).isObsolete;
        } catch (JDWPException exc) {
            throw exc.toJDIException();
        }
    }


    /*
     * A container class for the return value to allow
     * proper type-checking.
     */
    class ReturnContainer implements ValueContainer {
        ReturnContainer() {
        }
        public Type type() throws ClassNotLoadedException {
            return returnType();
        }
        public String typeName(){
            return returnTypeName();
        }
        public String signature() {
            return returnSignature(); //type().signature();
        }
        public Type findType(String signature) throws ClassNotLoadedException {
            return MethodImpl.this.findType(signature);
        }
    }
    ReturnContainer retValContainer = null;
    ReturnContainer getReturnValueContainer() {
        if (retValContainer == null) {
            retValContainer = new ReturnContainer();
        }
        return retValContainer;
    }

    /*
     * A container class for the argument to allow
     * proper type-checking.
     */
    class ArgumentContainer implements ValueContainer {
        int index;

        ArgumentContainer(int index) {
            this.index = index;
        }
        public Type type() throws ClassNotLoadedException {
            return argumentType(index);
        }
        public String typeName(){
            return argumentTypeNames().get(index);
        }
        public String signature() {
            return argumentSignatures().get(index);
        }
        public Type findType(String signature) throws ClassNotLoadedException {
            return MethodImpl.this.findType(signature);
        }
    }

    /*
     * This is a var args method.  Thus, its last param is an
     * array. If the method has n params, then:
     * 1.  If there are n args and the last is the same type as the type of
     *     the last param, do nothing.  IE, a String[]
     *     can be passed to a String...
     * 2.  If there are >= n arguments and for each arg whose number is >= n,
     *     the arg type is 'compatible' with the component type of
     *     the last param, then do
     *     - create an array of the type of the last param
     *     - put the n, ... args into this array.
     *       We might have to do conversions here.
     *     - put this array into arguments(n)
     *     - delete arguments(n+1), ...
     * NOTE that this might modify the input list.
     */
    void handleVarArgs(List<Value> arguments)
        throws ClassNotLoadedException, InvalidTypeException {
        List<Type> paramTypes = this.argumentTypes();
        ArrayType lastParamType = (ArrayType)paramTypes.get(paramTypes.size() - 1);
        Type componentType = lastParamType.componentType();
        int argCount = arguments.size();
        int paramCount = paramTypes.size();
        if (argCount < paramCount - 1) {
            // Error; will be caught later.
            return;
        }
        if (argCount == paramCount - 1) {
            // It is ok to pass 0 args to the var arg.
            // We have to gen a 0 length array.
            ArrayReference argArray = lastParamType.newInstance(0);
            arguments.add(argArray);
            return;
        }
        Value nthArgValue = arguments.get(paramCount - 1);
        if (nthArgValue == null) {
            return;
        }
        Type nthArgType = nthArgValue.type();
        if (nthArgType instanceof ArrayTypeImpl) {
            if (argCount == paramCount &&
                ((ArrayTypeImpl)nthArgType).isAssignableTo(lastParamType)) {
                /*
                 * This is case 1.  A compatible array is being passed to the
                 * var args array param.  We don't have to do anything.
                 */
                return;
            }
        }

        /*
         * Case 2.  We have to verify that the n, n+1, ... args are compatible
         * with componentType, and do conversions if necessary and create
         * an array of componentType to hold these possibly converted values.
         */
        int count = argCount - paramCount + 1;
        ArrayReference argArray = lastParamType.newInstance(count);

        /*
         * This will copy arguments(paramCount - 1) ... to argArray(0) ...
         * doing whatever conversions are needed!  It will throw an
         * exception if an incompatible arg is encountered
         */
        argArray.setValues(0, arguments, paramCount - 1, count);
        arguments.set(paramCount - 1, argArray);

        /*
         * Remove the excess args
         */
        for (int ii = paramCount; ii < argCount; ii++) {
            arguments.remove(paramCount);
        }
        return;
    }

    /*
     * The output list will be different than the input list.
     */
    List<Value> validateAndPrepareArgumentsForInvoke(List<? extends Value> origArguments)
                         throws ClassNotLoadedException, InvalidTypeException {

        List<Value> arguments = new ArrayList<Value>(origArguments);
        if (isVarArgs()) {
            handleVarArgs(arguments);
        }

        int argSize = arguments.size();

        JNITypeParser parser = new JNITypeParser(signature());
        List signatures = parser.argumentSignatures();

        if (signatures.size() != argSize) {
            throw new IllegalArgumentException("Invalid argument count: expected " +
                                               signatures.size() + ", received " +
                                               arguments.size());
        }

        for (int i = 0; i < argSize; i++) {
            Value value = arguments.get(i);
            value = ValueImpl.prepareForAssignment(value,
                                                   new ArgumentContainer(i));
            arguments.set(i, value);
        }
        return arguments;
    }

    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append(declaringType().name());
        sb.append(".");
        sb.append(name());
        sb.append("(");
        boolean first = true;
        for (String name : argumentTypeNames()) {
            if (!first) {
                sb.append(", ");
            }
            sb.append(name);
            first = false;
        }
        sb.append(")");
        return sb.toString();
    }
}
