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

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import freemarker.ext.beans.BeansWrapper;

/**
 * A simple implementation of the {@link TemplateSequenceModel} interface, using its own underlying {@link List} for
 * storing the list items. If you are wrapping an already existing {@link List} or {@code array}, you should certainly
 * use {@link DefaultMapAdapter} or {@link DefaultArrayAdapter} (see comparison below).
 * 
 * <p>
 * This class is thread-safe if you don't call modifying methods (like {@link #add(Object)}) after you have made the
 * object available for multiple threads (assuming you have published it safely to the other threads; see JSR-133 Java
 * Memory Model). These methods aren't called by FreeMarker, so it's usually not a concern.
 * 
 * <p>
 * <b>{@link SimpleSequence} VS {@link DefaultListAdapter}/{@link DefaultArrayAdapter} - Which to use when?</b>
 * </p>
 * 
 * <p>
 * For a {@link List} or {@code array} that exists regardless of FreeMarker, only you need to access it from templates,
 * {@link DefaultMapAdapter} should be the default choice, as it can be unwrapped to the originally wrapped object
 * (important when passing it to Java methods from the template). It also has more predictable performance (no spikes).
 * 
 * <p>
 * For a sequence that's made specifically to be used from templates, creating an empty {@link SimpleSequence} then
 * filling it with {@link SimpleSequence#add(Object)} is usually the way to go, as the resulting sequence is
 * significantly faster to read from templates than a {@link DefaultListAdapter} (though it's somewhat slower to read
 * from a plain Java method to which it had to be passed adapted to a {@link List}).
 * 
 * <p>
 * It also matters if for how many times will the <em>same</em> {@link List} entry be read from the template(s) later,
 * on average. If, on average, you read each entry for more than 4 times, {@link SimpleSequence} will be most
 * certainly faster, but if for 2 times or less (and especially if not at all) then {@link DefaultMapAdapter} will
 * be faster. Before choosing based on performance though, pay attention to the behavioral differences;
 * {@link SimpleSequence} will shallow-copy the original {@link List} at construction time, so it won't reflect
 * {@link List} content changes after the {@link SimpleSequence} construction, also {@link SimpleSequence} can't be
 * unwrapped to the original wrapped instance.
 *
 * @see DefaultListAdapter
 * @see DefaultArrayAdapter
 * @see TemplateSequenceModel
 */
public class SimpleSequence extends WrappingTemplateModel implements TemplateSequenceModel, Serializable {

    /**
     * The {@link List} that stored the elements of this sequence. It migth contains both {@link TemplateModel} elements
     * and non-{@link TemplateModel} elements.
     */
    protected final List list;
    
    private List unwrappedList;

    /**
     * Constructs an empty simple sequence that will use the the default object 
     * wrapper set in 
     * {@link WrappingTemplateModel#setDefaultObjectWrapper(ObjectWrapper)}.
     * 
     * @deprecated Use {@link #SimpleSequence(ObjectWrapper)} instead.
     */
    @Deprecated
    public SimpleSequence() {
        this((ObjectWrapper) null);
    }

    /**
     * Constructs an empty simple sequence with preallocated capacity and using
     * the default object wrapper set in 
     * {@link WrappingTemplateModel#setDefaultObjectWrapper(ObjectWrapper)}.
     * 
     * @deprecated Use {@link #SimpleSequence(int, ObjectWrapper)}.
     */
    @Deprecated
    public SimpleSequence(int capacity) {
        list = new ArrayList(capacity);
    }
    
    /**
     * Constructs a simple sequence that will contain the elements
     * from the specified {@link Collection} and will use the the default 
     * object wrapper set in 
     * {@link WrappingTemplateModel#setDefaultObjectWrapper(ObjectWrapper)}.
     * @param collection the collection containing initial values. Note that a
     * copy of the collection is made for internal use.
     * 
     * @deprecated Use {@link #SimpleSequence(Collection, ObjectWrapper)}.
     */
    @Deprecated
    public SimpleSequence(Collection collection) {
        this(collection, null);
    }
    
    /**
     * Constructs a simple sequence from the passed collection model, which shouldn't be added to later. The internal
     * list will be build immediately (not lazily). The resulting sequence shouldn't be extended with
     * {@link #add(Object)}, because the appropriate {@link ObjectWrapper} won't be available; use
     * {@link #SimpleSequence(Collection, ObjectWrapper)} instead, if you need that.
     */
    public SimpleSequence(TemplateCollectionModel tcm) throws TemplateModelException {
        ArrayList alist = new ArrayList();
        for (TemplateModelIterator it = tcm.iterator(); it.hasNext(); ) {
            alist.add(it.next());
        }
        alist.trimToSize();
        list = alist;
    }

    /**
     * Constructs an empty sequence using the specified object wrapper.
     * 
     * @param wrapper
     *            The object wrapper to use to wrap the list items into {@link TemplateModel} instances. {@code null} is
     *            allowed, but deprecated, and will cause the deprecated default object wrapper (set in
     *            {@link WrappingTemplateModel#setDefaultObjectWrapper(ObjectWrapper)}) to be used.
     */
    public SimpleSequence(ObjectWrapper wrapper) {
        super(wrapper);
        list = new ArrayList();
    }
    
    /**
     * Constructs an empty simple sequence with preallocated capacity.
     * 
     * @param wrapper
     *            See the similar parameter of {@link SimpleSequence#SimpleSequence(ObjectWrapper)}.
     * 
     * @since 2.3.21
     */
    public SimpleSequence(int capacity, ObjectWrapper wrapper) {
        super(wrapper);
        list = new ArrayList(capacity);
    }    
    
    /**
     * Constructs a simple sequence that will contain the elements from the specified {@link Collection}; consider
     * using {@link DefaultListAdapter} instead.
     * 
     * @param collection
     *            The collection containing the initial items of the sequence. A shallow copy of this collection is made
     *            immediately for internal use (thus, later modification on the parameter collection won't be visible in
     *            the resulting sequence). The items however, will be only wrapped with the {@link ObjectWrapper}
     *            lazily, when first needed.
     * @param wrapper
     *            See the similar parameter of {@link SimpleSequence#SimpleSequence(ObjectWrapper)}.
     */
    public SimpleSequence(Collection collection, ObjectWrapper wrapper) {
        super(wrapper);
        list = new ArrayList(collection);
    }

    /**
     * Adds an arbitrary object to the end of this sequence. If the newly added object does not implement the
     * {@link TemplateModel} interface, it will be wrapped into the appropriate {@link TemplateModel} interface when
     * it's first read (lazily).
     *
     * @param obj
     *            The object to be added.
     */
    public void add(Object obj) {
        list.add(obj);
        unwrappedList = null;
    }

    /**
     * Adds a boolean value to the end of this sequence. The newly added boolean will be immediately converted into
     * {@link TemplateBooleanModel#TRUE} or {@link TemplateBooleanModel#FALSE}, without using the {@link ObjectWrapper}.
     *
     * @param b
     *            The boolean value to be added.
     * 
     * @deprecated Use {@link #add(Object)} instead, as this bypasses the {@link ObjectWrapper}.
     */
    @Deprecated
    public void add(boolean b) {
        add(b ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE);
    }
    
    /**
     * Builds a deep-copy of the underlying list, unwrapping any values that were already converted to
     * {@link TemplateModel}-s. When called for the second time (or later), it just reuses the first result, unless the
     * sequence was modified since then.
     * 
     * @deprecated No replacement exists; not a reliable way of getting back the original list elemnts.
     */
    @Deprecated
    public List toList() throws TemplateModelException {
        if (unwrappedList == null) {
            Class listClass = list.getClass();
            List result = null;
            try {
                result = (List) listClass.newInstance();
            } catch (Exception e) {
                throw new TemplateModelException("Error instantiating an object of type " + listClass.getName(),
                        e);
            }
            BeansWrapper bw = BeansWrapper.getDefaultInstance();
            for (int i = 0; i < list.size(); i++) {
                Object elem = list.get(i);
                if (elem instanceof TemplateModel) {
                    elem = bw.unwrap((TemplateModel) elem);
                }
                result.add(elem);
            }
            unwrappedList = result;
        }
        return unwrappedList;
    }
    
    /**
     * Returns the item at the specified index of the list. If the item isn't yet an {@link TemplateModel}, it will wrap
     * it to one now, and writes it back into the backing list.
     */
    @Override
    public TemplateModel get(int index) throws TemplateModelException {
        try {
            Object value = list.get(index);
            if (value instanceof TemplateModel) {
                return (TemplateModel) value;
            }
            TemplateModel tm = wrap(value);
            list.set(index, tm);
            return tm;
        } catch (IndexOutOfBoundsException e) {
            return null;
        }
    }

    @Override
    public int size() {
        return list.size();
    }

    /**
     * @return a synchronized wrapper for list.
     */
    public SimpleSequence synchronizedWrapper() {
        return new SynchronizedSequence();
    }
    
    @Override
    public String toString() {
        return list.toString();
    }

    private class SynchronizedSequence extends SimpleSequence {
        private SynchronizedSequence() {
            super(SimpleSequence.this.getObjectWrapper());
        }

        @Override
        public void add(Object obj) {
            synchronized (SimpleSequence.this) {
                SimpleSequence.this.add(obj);
            }
        }

        @Override
        public TemplateModel get(int i) throws TemplateModelException {
            synchronized (SimpleSequence.this) {
                return SimpleSequence.this.get(i);
            }
        }
        
        @Override
        public int size() {
            synchronized (SimpleSequence.this) {
                return SimpleSequence.this.size();
            }
        }
        
        @Override
        public List toList() throws TemplateModelException {
            synchronized (SimpleSequence.this) {
                return SimpleSequence.this.toList();
            }
        }

        @Override
        public SimpleSequence synchronizedWrapper() {
            return this;
        }
    }
    
}