/*   Copyright 2004 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.xmlbeans.impl.config;

import org.apache.xmlbeans.impl.xb.xmlconfig.Extensionconfig;
import org.apache.xmlbeans.InterfaceExtension;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.impl.jam.JMethod;
import org.apache.xmlbeans.impl.jam.JClass;
import org.apache.xmlbeans.impl.jam.JParameter;
import org.apache.xmlbeans.impl.jam.JamClassLoader;

public class InterfaceExtensionImpl implements InterfaceExtension
{
    private NameSet _xbeanSet;
    private String _interfaceClassName;
    private String _delegateToClassName;
    private MethodSignatureImpl[] _methods;

    static InterfaceExtensionImpl newInstance(JamClassLoader loader, NameSet xbeanSet, Extensionconfig.Interface intfXO)
    {
        InterfaceExtensionImpl result = new InterfaceExtensionImpl();

        result._xbeanSet = xbeanSet;
        JClass interfaceJClass = validateInterface(loader, intfXO.getName(), intfXO);


        if (interfaceJClass == null)
        {
            BindingConfigImpl.error("Interface '" + intfXO.getStaticHandler() + "' not found.", intfXO);
            return null;
        }

        result._interfaceClassName = interfaceJClass.getQualifiedName();

        result._delegateToClassName = intfXO.getStaticHandler();
        JClass delegateJClass = validateClass(loader, result._delegateToClassName, intfXO);

        if (delegateJClass == null) // no HandlerClass
        {
            BindingConfigImpl.warning("Handler class '" + intfXO.getStaticHandler() + "' not found on classpath, skip validation.", intfXO);
            return result;
        }

        if (!result.validateMethods(interfaceJClass, delegateJClass, intfXO))
            return null;

        return result;
    }

    private static JClass validateInterface(JamClassLoader loader, String intfStr, XmlObject loc)
    {
        return validateJava(loader, intfStr, true, loc);
    }

    static JClass validateClass(JamClassLoader loader, String clsStr, XmlObject loc)
    {
        return validateJava(loader, clsStr, false, loc);
    }

    static JClass validateJava(JamClassLoader loader, String clsStr, boolean isInterface, XmlObject loc)
    {
        if (loader==null)
            return null;

        final String ent = isInterface ? "Interface" : "Class";
        JClass cls = loader.loadClass(clsStr);

        if (cls==null || cls.isUnresolvedType())
        {
            BindingConfigImpl.error(ent + " '" + clsStr + "' not found.", loc);
            return null;
        }

        if ( (isInterface && !cls.isInterface()) ||
                (!isInterface && cls.isInterface()))
        {
            BindingConfigImpl.error("'" + clsStr + "' must be " +
                (isInterface ? "an interface" : "a class") + ".", loc);
        }

        if (!cls.isPublic())
        {
            BindingConfigImpl.error(ent + " '" + clsStr + "' is not public.", loc);
        }

        return cls;
    }

    private boolean validateMethods(JClass interfaceJClass, JClass delegateJClass, XmlObject loc)
    {
        //assert _delegateToClass != null : "Delegate to class handler expected.";
        boolean valid = true;

        JMethod[] interfaceMethods = interfaceJClass.getMethods();
        _methods = new MethodSignatureImpl[interfaceMethods.length];

        for (int i = 0; i < interfaceMethods.length; i++)
        {
            JMethod method = validateMethod(interfaceJClass, delegateJClass, interfaceMethods[i], loc);
            if (method != null)
                _methods[i] = new MethodSignatureImpl(getStaticHandler(), method);
            else
                valid = false;
        }


        return valid;
    }

    private JMethod validateMethod(JClass interfaceJClass, JClass delegateJClass, JMethod method, XmlObject loc)
    {
        String methodName = method.getSimpleName();
        JParameter[] params = method.getParameters();
        JClass returnType = method.getReturnType();

        JClass[] delegateParams = new JClass[params.length+1];
        delegateParams[0] = returnType.forName("org.apache.xmlbeans.XmlObject");
        for (int i = 1; i < delegateParams.length; i++)
        {
            delegateParams[i] = params[i-1].getType();
        }

        JMethod handlerMethod = null;
        handlerMethod = getMethod(delegateJClass, methodName, delegateParams);
        if (handlerMethod==null)
        {
            BindingConfigImpl.error("Handler class '" + delegateJClass.getQualifiedName() + "' does not contain method " + methodName + "(" + listTypes(delegateParams) + ")", loc);
            return null;
        }

        // check for throws exceptions
        JClass[] intfExceptions = method.getExceptionTypes();
        JClass[] delegateExceptions = handlerMethod.getExceptionTypes();
        if ( delegateExceptions.length!=intfExceptions.length )
        {
            BindingConfigImpl.error("Handler method '" + delegateJClass.getQualifiedName() + "." + methodName + "(" + listTypes(delegateParams) +
                ")' must declare the same exceptions as the interface method '" + interfaceJClass.getQualifiedName() + "." + methodName + "(" + listTypes(params), loc);
            return null;
        }

        for (int i = 0; i < delegateExceptions.length; i++)
        {
            if ( delegateExceptions[i]!=intfExceptions[i] )
            {
                BindingConfigImpl.error("Handler method '" + delegateJClass.getQualifiedName() + "." + methodName + "(" + listTypes(delegateParams) +
                    ")' must declare the same exceptions as the interface method '" + interfaceJClass.getQualifiedName() + "." + methodName + "(" + listTypes(params), loc);
                return null;
            }
        }

        if (!handlerMethod.isPublic() || !handlerMethod.isStatic())
        {
            BindingConfigImpl.error("Method '" + delegateJClass.getQualifiedName() + "." + methodName + "(" + listTypes(delegateParams) + ")' must be declared public and static.", loc);
            return null;
        }

        if (!returnType.equals(handlerMethod.getReturnType()))
        {
            BindingConfigImpl.error("Return type for method '" + handlerMethod.getReturnType() + " " + delegateJClass.getQualifiedName() +
                    "." + methodName + "(" + listTypes(delegateParams) + ")' does not match the return type of the interface method :'" + returnType + "'.", loc);
            return null;
        }

        return method;
    }

    static JMethod getMethod(JClass cls, String name, JClass[] paramTypes)
    {
        JMethod[] methods = cls.getMethods();
        for (int i = 0; i < methods.length; i++)
        {
            JMethod method = methods[i];
            if (!name.equals(method.getSimpleName()))
                continue;

            JParameter[] mParams = method.getParameters();

            // can have methods with same name but different # of params
            if (mParams.length != paramTypes.length)
                continue;

            for (int j = 0; j < mParams.length; j++)
            {
                JParameter mParam = mParams[j];
                if (!mParam.getType().equals(paramTypes[j]))
                    continue;
            }

            return method;
        }
        return null;
    }

    private static String listTypes(JClass[] types)
    {
        StringBuffer result = new StringBuffer();
        for (int i = 0; i < types.length; i++)
        {
            JClass type = types[i];
            if (i>0)
                result.append(", ");
            result.append(emitType(type));
        }
        return result.toString();
    }

    private static String listTypes(JParameter[] params)
    {
        StringBuffer result = new StringBuffer();
        for (int i = 0; i < params.length; i++)
        {
            JClass type = params[i].getType();
            if (i>0)
                result.append(", ");
            result.append(emitType(type));
        }
        return result.toString();
    }

    public static String emitType(JClass cls)
    {
        if (cls.isArrayType())
            return emitType(cls.getArrayComponentType()) + "[]";
        else
            return cls.getQualifiedName().replace('$', '.');
    }

    /* public getters */
    public boolean contains(String fullJavaName)
    {
        return _xbeanSet.contains(fullJavaName);
    }

    public String getStaticHandler()
    {
        return _delegateToClassName;
    }

    public String getInterface()
    {
        return _interfaceClassName;
    }

    public InterfaceExtension.MethodSignature[] getMethods()
    {
        return _methods;
    }

    public String toString()
    {
        StringBuilder buf = new StringBuilder();
        buf.append("  static handler: ").append(_delegateToClassName).append("\n");
        buf.append("  interface: ").append(_interfaceClassName).append("\n");
        buf.append("  name set: ").append(_xbeanSet).append("\n");

        for (int i = 0; i < _methods.length; i++)
            buf.append("  method[").append(i).append("]=").append(_methods[i]).append("\n");

        return buf.toString();
    }

    // this is used only for detecting method colisions of extending interfaces
    static class MethodSignatureImpl implements InterfaceExtension.MethodSignature
    {
        private String _intfName;  
        private final int NOTINITIALIZED = -1;
        private int _hashCode = NOTINITIALIZED;
        private String _signature;

        private String _name;
        private String _return;
        private String[] _params;
        private String[] _exceptions;

        MethodSignatureImpl(String intfName, JMethod method)
        {
            if (intfName==null || method==null)
                throw new IllegalArgumentException("Interface: " + intfName + " method: " + method);

            _intfName = intfName;
            _hashCode = NOTINITIALIZED;
            _signature = null;

            _name = method.getSimpleName();
            _return = method.getReturnType().getQualifiedName().replace('$', '.');

            JParameter[] paramTypes = method.getParameters();
            _params = new String[paramTypes.length];
            for (int i = 0; i < paramTypes.length; i++)
                _params[i] = paramTypes[i].getType().getQualifiedName().replace('$', '.');;

            JClass[] exceptionTypes = method.getExceptionTypes();
            _exceptions = new String[exceptionTypes.length];
            for (int i = 0; i < exceptionTypes.length; i++)
                _exceptions[i] = exceptionTypes[i].getQualifiedName().replace('$', '.');
        }

        String getInterfaceName()
        {
            return _intfName;
        }

        public String getName()
        {
            return _name;
        }

        public String getReturnType()
        {
            return _return;
        }

        public String[] getParameterTypes()
        {
            return _params;
        }

        public String[] getExceptionTypes()
        {
            return _exceptions;
        }

        public boolean equals(Object o)
        {
            if ( !(o instanceof MethodSignatureImpl))
                return false;

            MethodSignatureImpl ms = (MethodSignatureImpl)o;

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

            String[] params = getParameterTypes();
            String[] msParams = ms.getParameterTypes();

            if (msParams.length != params.length )
                return false;

            for (int i = 0; i < params.length; i++)
            {
                if (!msParams[i].equals(params[i]))
                    return false;
            }

            if (!_intfName.equals(ms._intfName))
                return false;
            
            return true;
        }

        public int hashCode()
        {
            if (_hashCode!=NOTINITIALIZED)
                return _hashCode;

            int hash = getName().hashCode();

            String[] params = getParameterTypes();

            for (int i = 0; i < params.length; i++)
            {
                hash *= 19;
                hash += params[i].hashCode();
            }

            hash += 21 * _intfName.hashCode();

            _hashCode = hash;
            return _hashCode;
        }

        String getSignature()
        {
            if (_signature!=null)
                return _signature;

            StringBuffer sb = new StringBuffer(60);
            sb.append(_name).append("(");
            for (int i = 0; i < _params.length; i++)
                sb.append((i == 0 ? "" : " ,")).append(_params[i]);
            sb.append(")");

            _signature = sb.toString();

            return _signature;
        }

        public String toString()
        {
            StringBuilder buf = new StringBuilder();

            buf.append(getReturnType()).append(" ").append(getSignature());

            return buf.toString();
        }
    }
}
