/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 freemarker.ext.jsp;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import freemarker.core._DelayedJQuote;
import freemarker.core._DelayedShortClassName;
import freemarker.core._ErrorDescriptionBuilder;
import freemarker.core._TemplateModelException;
import freemarker.ext.beans.BeansWrapper;
import freemarker.ext.jsp.SimpleTagDirectiveModel.TemplateExceptionWrapperJspException;
import freemarker.template.ObjectWrapper;
import freemarker.template.ObjectWrapperAndUnwrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
import freemarker.template.utility.StringUtil;

class JspTagModelBase {
    protected final String tagName;
    private final Class tagClass;
    private final Method dynaSetter;
    private final Map propertySetters = new HashMap();
    
    protected JspTagModelBase(String tagName, Class tagClass) throws IntrospectionException {
        this.tagName = tagName;
        this.tagClass = tagClass;
        BeanInfo bi = Introspector.getBeanInfo(tagClass);
        PropertyDescriptor[] pda = bi.getPropertyDescriptors();
        for (int i = 0; i < pda.length; i++) {
            PropertyDescriptor pd = pda[i];
            Method m = pd.getWriteMethod();
            if (m != null) {
                propertySetters.put(pd.getName(), m);
            }
        }
        // Check to see if the tag implements the JSP2.0 DynamicAttributes
        // interface, to allow setting of arbitrary attributes
        Method dynaSetter;
        try {
            dynaSetter = tagClass.getMethod("setDynamicAttribute",
                            new Class[] {String.class, String.class, Object.class});
        } catch (NoSuchMethodException nsme) {
            dynaSetter = null;
        }
        this.dynaSetter = dynaSetter;
    }
    
    Object getTagInstance() throws IllegalAccessException, InstantiationException {
        return tagClass.newInstance();
    }
    
    void setupTag(Object tag, Map args, ObjectWrapper wrapper)
    throws TemplateModelException, 
        InvocationTargetException, 
        IllegalAccessException {
        if (args != null && !args.isEmpty()) {
            ObjectWrapperAndUnwrapper unwrapper = 
                    wrapper instanceof ObjectWrapperAndUnwrapper ? (ObjectWrapperAndUnwrapper) wrapper
                            : BeansWrapper.getDefaultInstance();  // [2.4] Throw exception in this case
            final Object[] argArray = new Object[1];
            for (Iterator iter = args.entrySet().iterator(); iter.hasNext(); ) {
                final Map.Entry entry = (Map.Entry) iter.next();
                final Object arg = unwrapper.unwrap((TemplateModel) entry.getValue());
                argArray[0] = arg;
                final Object paramName = entry.getKey();
                Method setterMethod = (Method) propertySetters.get(paramName);
                if (setterMethod == null) {
                    if (dynaSetter == null) {
                        throw new TemplateModelException("Unknown property "
                                + StringUtil.jQuote(paramName.toString())
                                + " on instance of " + tagClass.getName());
                    } else {
                        dynaSetter.invoke(tag, null, paramName, argArray[0]);
                    }
                } else {
                    if (arg instanceof BigDecimal) {
                        argArray[0] = BeansWrapper.coerceBigDecimal(
                                (BigDecimal) arg, setterMethod.getParameterTypes()[0]);
                    }
                    try {
                        setterMethod.invoke(tag, argArray);
                    } catch (Exception e) {
                        final Class setterType = setterMethod.getParameterTypes()[0];
                        final _ErrorDescriptionBuilder desc = new _ErrorDescriptionBuilder(
                                "Failed to set JSP tag parameter ", new _DelayedJQuote(paramName),
                                " (declared type: ", new _DelayedShortClassName(setterType)
                                + ", actual value's type: ",
                                (argArray[0] != null
                                        ? new _DelayedShortClassName(argArray[0].getClass()) : "Null"),
                                "). See cause exception for the more specific cause...");
                        if (e instanceof IllegalArgumentException && !(setterType.isAssignableFrom(String.class))
                                && argArray[0] != null && argArray[0] instanceof String) {
                            desc.tip("This problem is often caused by unnecessary parameter quotation. Parameters "
                                    + "aren't quoted in FTL, similarly as they aren't quoted in most languages. "
                                    + "For example, these parameter assignments are wrong: ",
                                    "<@my.tag p1=\"true\" p2=\"10\" p3=\"${someVariable}\" p4=\"${x+1}\" />",
                                    ". The correct form is: ",
                                    "<@my.tag p1=true p2=10 p3=someVariable p4=x+1 />",
                                    ". Only string literals are quoted (regardless of where they occur): ",
                                    "<@my.box style=\"info\" message=\"Hello ${name}!\" width=200 />",
                                    ".");
                        }
                        throw new _TemplateModelException(e, null, desc);
                    }
                }
            }
        }
    }

    protected final TemplateModelException toTemplateModelExceptionOrRethrow(Exception e) throws TemplateModelException {
        if (e instanceof RuntimeException && !isCommonRuntimeException((RuntimeException) e)) {
            throw (RuntimeException) e;
        }
        if (e instanceof TemplateModelException) {
            throw (TemplateModelException) e;
        }
        if (e instanceof TemplateExceptionWrapperJspException) {
            return toTemplateModelExceptionOrRethrow(((TemplateExceptionWrapperJspException) e).getCause());
        }
        return new TemplateModelException(
                "Error while invoking the " + StringUtil.jQuote(tagName) + " JSP custom tag; see cause exception",
                e instanceof TemplateException, e);
    }

    /**
     * Runtime exceptions that we don't want to propagate, instead we warp them into a more helpful exception. These are
     * the ones where it's very unlikely that someone tries to catch specifically these around
     * {@link Template#process(Object, java.io.Writer)}.
     */
    private boolean isCommonRuntimeException(RuntimeException e) {
        final Class eClass = e.getClass();
        // We deliberately don't accept sub-classes. Those are possibly application specific and some want to catch them
        // outside the template.
        return eClass == NullPointerException.class
                || eClass == IllegalArgumentException.class
                || eClass == ClassCastException.class
                || eClass == IndexOutOfBoundsException.class;
    }
    
}
