/*
 * 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.beans;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import freemarker.core.CollectionAndSequence;
import freemarker.core._DelayedFTLTypeDescription;
import freemarker.core._DelayedJQuote;
import freemarker.core._TemplateModelException;
import freemarker.ext.util.ModelFactory;
import freemarker.ext.util.WrapperTemplateModel;
import freemarker.log.Logger;
import freemarker.template.AdapterTemplateModel;
import freemarker.template.ObjectWrapper;
import freemarker.template.SimpleScalar;
import freemarker.template.SimpleSequence;
import freemarker.template.TemplateCollectionModel;
import freemarker.template.TemplateHashModelEx;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
import freemarker.template.TemplateModelIterator;
import freemarker.template.TemplateModelWithAPISupport;
import freemarker.template.TemplateScalarModel;
import freemarker.template.utility.StringUtil;

/**
 * A class that will wrap an arbitrary object into {@link freemarker.template.TemplateHashModel}
 * interface allowing calls to arbitrary property getters and invocation of
 * accessible methods on the object from a template using the
 * <tt>object.foo</tt> to access properties and <tt>object.bar(arg1, arg2)</tt> to
 * invoke methods on it. You can also use the <tt>object.foo[index]</tt> syntax to
 * access indexed properties. It uses Beans {@link java.beans.Introspector}
 * to dynamically discover the properties and methods. 
 */

public class BeanModel
implements TemplateHashModelEx, AdapterTemplateModel, WrapperTemplateModel, TemplateModelWithAPISupport {
    private static final Logger LOG = Logger.getLogger("freemarker.beans");
    protected final Object object;
    protected final BeansWrapper wrapper;
    
    // We use this to represent an unknown value as opposed to known value of null (JR)
    static final TemplateModel UNKNOWN = new SimpleScalar("UNKNOWN");
    
    static final ModelFactory FACTORY =
        new ModelFactory()
        {
            @Override
            public TemplateModel create(Object object, ObjectWrapper wrapper) {
                return new BeanModel(object, (BeansWrapper) wrapper);
            }
        };

    // I've tried to use a volatile ConcurrentHashMap field instead of HashMap + synchronized(this), but oddly it was
    // a bit slower, at least on Java 8 u66. 
    private HashMap<Object, TemplateModel> memberCache;

    /**
     * Creates a new model that wraps the specified object. Note that there are
     * specialized subclasses of this class for wrapping arrays, collections,
     * enumeration, iterators, and maps. Note also that the superclass can be
     * used to wrap String objects if only scalar functionality is needed. You
     * can also choose to delegate the choice over which model class is used for
     * wrapping to {@link BeansWrapper#wrap(Object)}.
     * @param object the object to wrap into a model.
     * @param wrapper the {@link BeansWrapper} associated with this model.
     * Every model has to have an associated {@link BeansWrapper} instance. The
     * model gains many attributes from its wrapper, including the caching 
     * behavior, method exposure level, method-over-item shadowing policy etc.
     */
    public BeanModel(Object object, BeansWrapper wrapper) {
        // [2.4]: All models were introspected here, then the results was discareded, and get() will just do the
        // introspection again. So is this necessary? (The inrospectNow parameter was added in 2.3.21 to allow
        // lazy-introspecting BeansWrapper.trueModel|falseModel.)
        this(object, wrapper, true);
    }

    /** @since 2.3.21 */
    BeanModel(Object object, BeansWrapper wrapper, boolean inrospectNow) {
        this.object = object;
        this.wrapper = wrapper;
        if (inrospectNow && object != null) {
            // [2.4]: Could this be removed?
            wrapper.getClassIntrospector().get(object.getClass());
        }
    }
    
    /**
     * Uses Beans introspection to locate a property or method with name
     * matching the key name. If a method or property is found, it's wrapped
     * into {@link freemarker.template.TemplateMethodModelEx} (for a method or
     * indexed property), or evaluated on-the-fly and the return value wrapped
     * into appropriate model (for a non-indexed property). Models for various
     * properties and methods are cached on a per-class basis, so the costly
     * introspection is performed only once per property or method of a class.
     * (Side-note: this also implies that any class whose method has been called
     * will be strongly referred to by the framework and will not become
     * unloadable until this class has been unloaded first. Normally this is not
     * an issue, but can be in a rare scenario where you create many classes on-
     * the-fly. Also, as the cache grows with new classes and methods introduced
     * to the framework, it may appear as if it were leaking memory. The
     * framework does, however detect class reloads (if you happen to be in an
     * environment that does this kind of things--servlet containers do it when
     * they reload a web application) and flushes the cache. If no method or
     * property matching the key is found, the framework will try to invoke
     * methods with signature
     * <tt>non-void-return-type get(java.lang.String)</tt>,
     * then <tt>non-void-return-type get(java.lang.Object)</tt>, or 
     * alternatively (if the wrapped object is a resource bundle) 
     * <tt>Object getObject(java.lang.String)</tt>.
     * @throws TemplateModelException if there was no property nor method nor
     * a generic <tt>get</tt> method to invoke.
     */
    @Override
    public TemplateModel get(String key)
        throws TemplateModelException {
        Class<?> clazz = object.getClass();
        Map<Object, Object> classInfo = wrapper.getClassIntrospector().get(clazz);
        TemplateModel retval = null;
        
        try {
            if (wrapper.isMethodsShadowItems()) {
                Object fd = classInfo.get(key);
                if (fd != null) {
                    retval = invokeThroughDescriptor(fd, classInfo);
                } else {
                    retval = invokeGenericGet(classInfo, clazz, key);
                }
            } else {
                TemplateModel model = invokeGenericGet(classInfo, clazz, key);
                final TemplateModel nullModel = wrapper.wrap(null);
                if (model != nullModel && model != UNKNOWN) {
                    return model;
                }
                Object fd = classInfo.get(key);
                if (fd != null) {
                    retval = invokeThroughDescriptor(fd, classInfo);
                    if (retval == UNKNOWN && model == nullModel) {
                        // This is the (somewhat subtle) case where the generic get() returns null
                        // and we have no bean info, so we respect the fact that
                        // the generic get() returns null and return null. (JR)
                        retval = nullModel;
                    }
                }
            }
            if (retval == UNKNOWN) {
                if (wrapper.isStrict()) {
                    throw new InvalidPropertyException("No such bean property: " + key);
                } else if (LOG.isDebugEnabled()) {
                    logNoSuchKey(key, classInfo);
                }
                retval = wrapper.wrap(null);
            }
            return retval;
        } catch (TemplateModelException e) {
            throw e;
        } catch (Exception e) {
            throw new _TemplateModelException(e,
                    "An error has occurred when reading existing sub-variable ", new _DelayedJQuote(key),
                    "; see cause exception! The type of the containing value was: ",
                    new _DelayedFTLTypeDescription(this)
            );
        }
    }

    private void logNoSuchKey(String key, Map<?, ?> keyMap) {
        LOG.debug("Key " + StringUtil.jQuoteNoXSS(key) + " was not found on instance of " + 
            object.getClass().getName() + ". Introspection information for " +
            "the class is: " + keyMap);
    }
    
    /**
     * Whether the model has a plain get(String) or get(Object) method
     */
    
    protected boolean hasPlainGetMethod() {
        return wrapper.getClassIntrospector().get(object.getClass()).get(ClassIntrospector.GENERIC_GET_KEY) != null;
    }
    
    private TemplateModel invokeThroughDescriptor(Object desc, Map<Object, Object> classInfo)
            throws IllegalAccessException, InvocationTargetException, TemplateModelException {
        // See if this particular instance has a cached implementation for the requested feature descriptor
        TemplateModel cachedModel;
        synchronized (this) {
            cachedModel = memberCache != null ? memberCache.get(desc) : null;
        }

        if (cachedModel != null) {
            return cachedModel;
        }

        TemplateModel resultModel = UNKNOWN;
        if (desc instanceof FastPropertyDescriptor) {
            FastPropertyDescriptor pd = (FastPropertyDescriptor) desc;
            Method indexedReadMethod = pd.getIndexedReadMethod(); 
            if (indexedReadMethod != null) {
                if (!wrapper.getPreferIndexedReadMethod() && (pd.getReadMethod()) != null) {
                    resultModel = wrapper.invokeMethod(object, pd.getReadMethod(), null);
                    // cachedModel remains null, as we don't cache these
                } else {
                    resultModel = cachedModel = 
                        new SimpleMethodModel(object, indexedReadMethod, 
                                ClassIntrospector.getArgTypes(classInfo, indexedReadMethod), wrapper);
                }
            } else {
                resultModel = wrapper.invokeMethod(object, pd.getReadMethod(), null);
                // cachedModel remains null, as we don't cache these
            }
        } else if (desc instanceof Field) {
            resultModel = wrapper.readField(object, (Field) desc);
            // cachedModel remains null, as we don't cache these
        } else if (desc instanceof Method) {
            Method method = (Method) desc;
            resultModel = cachedModel = new SimpleMethodModel(
                    object, method, ClassIntrospector.getArgTypes(classInfo, method), wrapper);
        } else if (desc instanceof OverloadedMethods) {
            resultModel = cachedModel = new OverloadedMethodsModel(
                    object, (OverloadedMethods) desc, wrapper);
        }
        
        // If new cachedModel was created, cache it
        if (cachedModel != null) {
            synchronized (this) {
                if (memberCache == null) {
                    memberCache = new HashMap<>();
                }
                memberCache.put(desc, cachedModel);
            }
        }
        return resultModel;
    }
    
    void clearMemberCache() {
        synchronized (this) {
            memberCache = null;
        }
    }

    protected TemplateModel invokeGenericGet(Map/*<Object, Object>*/ classInfo, Class<?> clazz, String key)
            throws IllegalAccessException, InvocationTargetException,
        TemplateModelException {
        Method genericGet = (Method) classInfo.get(ClassIntrospector.GENERIC_GET_KEY);
        if (genericGet == null) {
            return UNKNOWN;
        }

        return wrapper.invokeMethod(object, genericGet, new Object[] { key });
    }

    protected TemplateModel wrap(Object obj)
    throws TemplateModelException {
        return wrapper.getOuterIdentity().wrap(obj);
    }
    
    protected Object unwrap(TemplateModel model)
    throws TemplateModelException {
        return wrapper.unwrap(model);
    }

    /**
     * Tells whether the model is empty. It is empty if either the wrapped 
     * object is null, or it's a Boolean with false value.
     */
    @Override
    public boolean isEmpty() {
        if (object instanceof String) {
            return ((String) object).length() == 0;
        }
        if (object instanceof Collection) {
            return ((Collection<?>) object).isEmpty();
        }
        if (object instanceof Iterator && wrapper.is2324Bugfixed()) {
            return !((Iterator<?>) object).hasNext();
        }
        if (object instanceof Map) {
            return ((Map<?,?>) object).isEmpty();
        }
        return object == null || Boolean.FALSE.equals(object);
    }
    
    /**
     * Returns the same as {@link #getWrappedObject()}; to ensure that, this method will be final starting from 2.4.
     * This behavior of {@link BeanModel} is assumed by some FreeMarker code. 
     */
    @Override
    public Object getAdaptedObject(Class<?> hint) {
        return object;  // return getWrappedObject(); starting from 2.4
    }

    @Override
    public Object getWrappedObject() {
        return object;
    }
    
    @Override
    public int size() {
        return wrapper.getClassIntrospector().keyCount(object.getClass());
    }

    @Override
    public TemplateCollectionModel keys() {
        return new CollectionAndSequence(new SimpleSequence(keySet(), wrapper));
    }

    @Override
    public TemplateCollectionModel values() throws TemplateModelException {
        List<Object> values = new ArrayList<>(size());
        TemplateModelIterator it = keys().iterator();
        while (it.hasNext()) {
            String key = ((TemplateScalarModel) it.next()).getAsString();
            values.add(get(key));
        }
        return new CollectionAndSequence(new SimpleSequence(values, wrapper));
    }
    
    /**
     * Used for {@code classic_compatbile} mode; don't use it for anything else.
     * In FreeMarker 1.7 (and also at least in 2.1) {@link BeanModel} was a {@link TemplateScalarModel}. Some internal
     * FreeMarker code tries to emulate FreeMarker classic by calling this method when a {@link TemplateScalarModel} is
     * expected.
     * 
     * @return Never {@code null}
     */
    String getAsClassicCompatibleString() {
        if (object == null) {
            return "null";
        }
        String s = object.toString();
        return s != null ? s : "null";        
    }
    
    @Override
    public String toString() {
        return object.toString();
    }

    /**
     * Helper method to support TemplateHashModelEx. Returns the Set of
     * Strings which are available via the TemplateHashModel
     * interface. Subclasses that override <tt>invokeGenericGet</tt> to
     * provide additional hash keys should also override this method.
     */
    protected Set/*<Object>*/ keySet() {
        return wrapper.getClassIntrospector().keySet(object.getClass());
    }

    @Override
    public TemplateModel getAPI() throws TemplateModelException {
        return wrapper.wrapAsAPI(object);
    }
    
}