/*
 * 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.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
                                        ? (Object) 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. Paramters "
                                    + "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 (TemplateModelException) e.getCause();
        }
        return new _TemplateModelException(e,
                "Error while invoking the ", new _DelayedJQuote(tagName), " JSP custom tag; see cause exception");
    }

    /**
     * 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;
    }
    
}
