//  Copyright 2008 The Apache Software Foundation
//
// 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 org.apache.tapestry.enhance;

import org.apache.tapestry.enhance.javassist.ClassFabUtils;

import java.lang.reflect.Method;

/**
 * JDK 1.4 based version of {@link MethodSignature}.
 */
public class MethodSignatureImpl implements MethodSignature
{
    protected int _hashCode = -1;

    protected Class _returnType;

    protected String _name;

    protected Class[] _parameterTypes;

    protected Class[] _exceptionTypes;

    public MethodSignatureImpl(Class returnType, String name,
            Class[] parameterTypes, Class[] exceptionTypes)
    {
        _returnType = returnType;
        _name = name;
        _parameterTypes = parameterTypes;
        _exceptionTypes = exceptionTypes;
    }

    public MethodSignatureImpl(Method m)
    {
        this(m.getReturnType(), m.getName(), m.getParameterTypes(), m.getExceptionTypes());
    }

    public Class[] getExceptionTypes()
    {
        return _exceptionTypes;
    }

    public String getName()
    {
        return _name;
    }

    public Class[] getParameterTypes()
    {
        return _parameterTypes;
    }

    public Class getReturnType()
    {
        return _returnType;
    }

    public int hashCode()
    {
        if (_hashCode == -1)
        {
            _hashCode = _returnType.hashCode();

            _hashCode = 31 * _hashCode + _name.hashCode();

            int count = count(_parameterTypes);

            for (int i = 0; i < count; i++)
                _hashCode = 31 * _hashCode + _parameterTypes[i].hashCode();

            count = count(_exceptionTypes);

            for (int i = 0; i < count; i++)
                _hashCode = 31 * _hashCode + _exceptionTypes[i].hashCode();
        }

        return _hashCode;
    }

    protected static int count(Object[] array)
    {
        return array == null ? 0 : array.length;
    }

    /**
     * Returns true if the other object is an instance of MethodSignature with identical values for
     * return type, name, parameter types and exception types.
     */
    public boolean equals(Object o)
    {
        if (o == null || !(o instanceof MethodSignatureImpl))
            return false;

        MethodSignatureImpl ms = (MethodSignatureImpl) o;

        if (_returnType != ms._returnType)
            return false;

        if (!_name.equals(ms._name))
            return false;

        if (mismatch(_parameterTypes, ms._parameterTypes))
            return false;

        return !mismatch(_exceptionTypes, ms._exceptionTypes);
    }

    protected boolean mismatch(Class[] a1, Class[] a2)
    {
        int a1Count = count(a1);
        int a2Count = count(a2);

        if (a1Count != a2Count)
            return true;

        // Hm. What if order is important (for exceptions)? We're really saying here that they
        // were derived from the name Method.

        for (int i = 0; i < a1Count; i++)
        {
            if (!a1[i].isAssignableFrom(a2[i]))
                return true;
        }

        return false;
    }

    public String toString()
    {
        StringBuffer buffer = new StringBuffer();

        buffer.append(ClassFabUtils.getJavaClassName(_returnType));
        buffer.append(" ");
        buffer.append(_name);
        buffer.append("(");

        for (int i = 0; i < count(_parameterTypes); i++)
        {
            if (i > 0)
                buffer.append(", ");

            buffer.append(ClassFabUtils.getJavaClassName(_parameterTypes[i]));
        }

        buffer.append(")");

        for (int i = 0; i < count(_exceptionTypes); i++)
        {
            if (i == 0)
                buffer.append(" throws ");
            else
                buffer.append(", ");

            buffer.append(_exceptionTypes[i].getName());
        }

        return buffer.toString();
    }

    public String getUniqueId()
    {
        StringBuffer buffer = new StringBuffer(_name);
        buffer.append("(");

        for (int i = 0; i < count(_parameterTypes); i++)
        {
            if (i > 0)
                buffer.append(",");

            buffer.append(ClassFabUtils.getJavaClassName(_parameterTypes[i]));
        }

        buffer.append(")");

        return buffer.toString();
    }

    public boolean isGeneric()
    {
        return false;
    }

    public boolean isOverridingSignatureOf(MethodSignature ms)
    {
        if (!(ms instanceof MethodSignatureImpl))
            return false;

        MethodSignatureImpl sig = (MethodSignatureImpl)ms;

        if (!sig._returnType.isAssignableFrom(_returnType))
            return false;

        if (!_name.equals(sig._name))
            return false;

        if (mismatch(_parameterTypes, sig._parameterTypes))
            return false;

        return exceptionsEncompass(sig._exceptionTypes);
    }

    /**
     * The nuts and bolts of checking that another method signature's exceptions are a subset of
     * this signature's.
     */

    protected boolean exceptionsEncompass(Class[] otherExceptions)
    {
        int ourCount = count(_exceptionTypes);
        int otherCount = count(otherExceptions);

        // If we have no exceptions, then ours encompass theirs only if they
        // have no exceptions, either.

        if (ourCount == 0)
            return otherCount == 0;

        boolean[] matched = new boolean[otherCount];
        int unmatched = otherCount;

        for (int i = 0; i < ourCount && unmatched > 0; i++)
        {
            for (int j = 0; j < otherCount; j++)
            {
                // Ignore exceptions that have already been matched

                if (matched[j])
                    continue;

                // When one of our exceptions is a super-class of one of their exceptions,
                // then their exceptions is matched.

                if (_exceptionTypes[i].isAssignableFrom(otherExceptions[j]))
                {
                    matched[j] = true;
                    unmatched--;
                }
            }
        }

        return unmatched == 0;
    }
}
