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

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

import org.python.core.Py;
import org.python.core.PyDictionary;
import org.python.core.PyFloat;
import org.python.core.PyInteger;
import org.python.core.PyLong;
import org.python.core.PyObject;
import org.python.core.PySequence;
import org.python.core.PyString;
import org.python.core.PyStringMap;

import freemarker.ext.util.ModelCache;
import freemarker.ext.util.WrapperTemplateModel;
import freemarker.template.AdapterTemplateModel;
import freemarker.template.ObjectWrapper;
import freemarker.template.TemplateBooleanModel;
import freemarker.template.TemplateHashModel;
import freemarker.template.TemplateHashModelEx;
import freemarker.template.TemplateMethodModel;
import freemarker.template.TemplateMethodModelEx;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelAdapter;
import freemarker.template.TemplateModelException;
import freemarker.template.TemplateNumberModel;
import freemarker.template.TemplateScalarModel;
import freemarker.template.TemplateSequenceModel;
import freemarker.template.utility.OptimizerUtil;

/**
 * An object wrapper that wraps Jython objects into FreeMarker template models
 * and vice versa.
 */
public class JythonWrapper implements ObjectWrapper {
    private static final Class PYOBJECT_CLASS = PyObject.class;
    public static final JythonWrapper INSTANCE = new JythonWrapper();

    private final ModelCache modelCache = new JythonModelCache(this);

    private boolean attributesShadowItems = true;

    public JythonWrapper() {
    }
    
    /**
     * Sets whether this wrapper caches model instances. Default is false.
     * When set to true, calling {@link #wrap(Object)} multiple times for
     * the same object will return the same model.
     */
    public void setUseCache(boolean useCache) {
        modelCache.setUseCache(useCache);
    }
    
    /**
     * Sets whether attributes shadow items in wrapped objects. When true 
     * (this is the default value), <code>${object.name}</code> will first 
     * try to locate a python attribute with the specified name on the object
     * using {@link PyObject#__findattr__(java.lang.String)}, and only if it 
     * doesn't find the attribute will it call 
     * {@link PyObject#__getitem__(org.python.core.PyObject)}.
     * When set to false, the lookup order is reversed and items
     * are looked up before attributes.
     */
    public synchronized void setAttributesShadowItems(boolean attributesShadowItems) {
        this.attributesShadowItems = attributesShadowItems;
    }
    
    boolean isAttributesShadowItems() {
        return attributesShadowItems;
    }
    
    /**
     * Wraps the passed Jython object into a FreeMarker template model. If
     * the object is not a Jython object, it's first coerced into one using
     * {@link Py#java2py(java.lang.Object)}. {@link PyDictionary} and {@link
     * PyStringMap} are wrapped into a hash model, {@link PySequence}
     * descendants are wrapped into a sequence model, {@link PyInteger}, {@link
     * PyLong}, and {@link PyFloat} are wrapped into a number model. All objects
     * are wrapped into a scalar model (using {@link Object#toString()} and a
     * boolean model (using {@link PyObject#__nonzero__()}. For internal
     * general-purpose {@link PyObject}s returned from a call to {@link
     * #unwrap(TemplateModel)}, the template model that was passed to
     * <code>unwrap</code> is returned.
     */
    @Override
    public TemplateModel wrap(Object obj) {
        if (obj == null) {
            return null;
        }
        return modelCache.getInstance(obj);
    }
    
    /**
     * Coerces a template model into a {@link PyObject}.
     * @param model the model to coerce
     * @return the coerced model.
     * <ul>
     * <li>
     * <li>{@link AdapterTemplateModel}s (i.e. {@link freemarker.ext.beans.BeanModel}) are marshalled
     *   using the standard Python marshaller {@link Py#java2py(Object)} on 
     *   the result of <code>getWrappedObject(PyObject.class)</code>s. The 
     *   native JythonModel instances will just return the underlying PyObject. 
     * <li>All other models that are {@link TemplateScalarModel scalars} are 
     *   marshalled as {@link PyString}.
     * <li>All other models that are {@link TemplateNumberModel numbers} are 
     *   marshalled using the standard Python marshaller
     *   {@link Py#java2py(Object)} on their underlying <code>Number</code></li>
     * <li>All other models  are marshalled to a generic internal 
     *   <code>PyObject</code> subclass that'll correctly pass
     *   <code>__finditem__</code>, <code>__len__</code>,
     *   <code>__nonzero__</code>, and <code>__call__</code> invocations to 
     *   appropriate hash, sequence, and method models.</li>
     * </ul>
     */
    public PyObject unwrap(TemplateModel model) throws TemplateModelException {
        if (model instanceof AdapterTemplateModel) {
            return Py.java2py(((AdapterTemplateModel) model).getAdaptedObject(
                    PYOBJECT_CLASS));
        }
        if (model instanceof WrapperTemplateModel) {
            return Py.java2py(((WrapperTemplateModel) model).getWrappedObject());
        }

        // Scalars are marshalled to PyString.
        if (model instanceof TemplateScalarModel) {
            return new PyString(((TemplateScalarModel) model).getAsString());
        }
        
        // Numbers are wrapped to Python built-in numeric types.
        if (model instanceof TemplateNumberModel) {
            Number number = ((TemplateNumberModel) model).getAsNumber();
            if (number instanceof BigDecimal) {
                number = OptimizerUtil.optimizeNumberRepresentation(number);
            }
            if (number instanceof BigInteger) {
                // Py.java2py can't automatically coerce a BigInteger into
                // a PyLong. This will probably get fixed in later Jython
                // release.
                return new PyLong((BigInteger) number);
            } else {
                return Py.java2py(number);
            }
        }
        // Return generic TemplateModel-to-Python adapter
        return new TemplateModelToJythonAdapter(model);
    }

    private class TemplateModelToJythonAdapter extends PyObject 
    implements TemplateModelAdapter {
        private final TemplateModel model;
        
        TemplateModelToJythonAdapter(TemplateModel model) {
            this.model = model;
        }
        
        @Override
        public TemplateModel getTemplateModel() {
            return model;
        }
        
        @Override
        public PyObject __finditem__(PyObject key) {
            if (key instanceof PyInteger) {
                return __finditem__(((PyInteger) key).getValue());
            }
            return __finditem__(key.toString());
        }

        @Override
        public PyObject __finditem__(String key) {
            if (model instanceof TemplateHashModel) {
                try {
                    return unwrap(((TemplateHashModel) model).get(key));
                } catch (TemplateModelException e) {
                    throw Py.JavaError(e);
                }
            }
            throw Py.TypeError("item lookup on non-hash model (" + getModelClass() + ")");
        }
        
        @Override
        public PyObject __finditem__(int index) {
            if (model instanceof TemplateSequenceModel) {
                try {
                    return unwrap(((TemplateSequenceModel) model).get(index));
                } catch (TemplateModelException e) {
                    throw Py.JavaError(e);
                }
            }
            throw Py.TypeError("item lookup on non-sequence model (" + getModelClass() + ")");
        }
        
        @Override
        public PyObject __call__(PyObject args[], String keywords[]) {
            if (model instanceof TemplateMethodModel) {
                boolean isEx = model instanceof TemplateMethodModelEx;
                List list = new ArrayList(args.length);
                try {
                    for (int i = 0; i < args.length; ++i) {
                        list.add(
                            isEx 
                            ? wrap(args[i])
                            : args[i] == null
                            ? null
                            : args[i].toString());
                    }
                    return unwrap((TemplateModel) ((TemplateMethodModelEx) model).exec(list));
                } catch (TemplateModelException e) {
                    throw Py.JavaError(e);
                }
            }
            throw Py.TypeError("call of non-method model (" + getModelClass() + ")");
        }
        
        @Override
        public int __len__() {
            try {
                if (model instanceof TemplateSequenceModel) {
                    return ((TemplateSequenceModel) model).size();
                }
                if (model instanceof TemplateHashModelEx) {
                    return ((TemplateHashModelEx) model).size();
                }
            } catch (TemplateModelException e) {
                throw Py.JavaError(e);
            }
            
            return 0;
        }
        
        @Override
        public boolean __nonzero__() {
            try {
                if (model instanceof TemplateBooleanModel) {
                    return ((TemplateBooleanModel) model).getAsBoolean();
                }
                if (model instanceof TemplateSequenceModel) {
                    return ((TemplateSequenceModel) model).size() > 0;
                }
                if (model instanceof TemplateHashModel) {
                    return !((TemplateHashModelEx) model).isEmpty();
                }
            } catch (TemplateModelException e) {
                throw Py.JavaError(e);
            }
            return false;
        }
        
        private String getModelClass() {
            return model == null ? "null" : model.getClass().getName();
        }
    }
}
