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

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import org.junit.Test;

import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.SimpleNumber;
import freemarker.template.TemplateCollectionModel;
import freemarker.template.TemplateCollectionModelEx;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
import freemarker.template.TemplateModelIterator;
import freemarker.template.TemplateSequenceModel;
import freemarker.test.TemplateTest;

/**
 * Tests operators and built-ins that are support getting and/or returning {@link LazilyGeneratedCollectionModel}.
 * @see MapBiTest
 * @see FilterBiTest
 */
public class LazilyGeneratedCollectionTest extends TemplateTest {

    @Override
    protected Configuration createConfiguration() throws Exception {
        Configuration cfg = super.createConfiguration();
        cfg.setIncompatibleImprovements(Configuration.VERSION_2_3_29);
        cfg.setBooleanFormat("c");
        cfg.setSharedVariable("seq", new MonitoredTemplateSequenceModel(1, 2, 3));
        cfg.setSharedVariable("seqLong", new MonitoredTemplateSequenceModel(1, 2, 3, 4, 5, 6));
        cfg.setSharedVariable("coll", new MonitoredTemplateCollectionModel(1, 2, 3));
        cfg.setSharedVariable("collLong", new MonitoredTemplateCollectionModel(1, 2, 3, 4, 5, 6));
        cfg.setSharedVariable("collEx", new MonitoredTemplateCollectionModelEx(1, 2, 3));

        DefaultObjectWrapper objectWrapper = new DefaultObjectWrapper(Configuration.VERSION_2_3_28);
        objectWrapper.setForceLegacyNonListCollections(false);
        cfg.setObjectWrapper(objectWrapper);

        return cfg;
    }

    @Test
    public void dynamicIndexTest() throws Exception {
        assertErrorContains("${coll?sequence?map(it -> it)['x']}",
                "hash", "evaluated to a sequence");

        assertOutput("${coll?sequence?map(it -> it)[0]}",
                "[iterator][hasNext][next]1");
        assertOutput("${coll?sequence?map(it -> it)[1]}",
                "[iterator][hasNext][next][hasNext][next]2");
        assertOutput("${coll?map(it -> it)?sequence[1]}",
                "[iterator][hasNext][next][hasNext][next]2");
        assertOutput("${coll?sequence?map(it -> it)[2]}",
                "[iterator][hasNext][next][hasNext][next][hasNext][next]3");
        assertOutput("${coll?sequence?map(it -> it)[3]!'missing'}",
                "[iterator][hasNext][next][hasNext][next][hasNext][next][hasNext]missing");
        assertOutput("${coll?sequence?filter(it -> it % 2 == 0)[0]}",
                "[iterator][hasNext][next][hasNext][next]2");
        assertOutput("${coll?sequence?filter(it -> it > 3)[0]!'missing'}",
                "[iterator][hasNext][next][hasNext][next][hasNext][next][hasNext]missing");

        assertOutput("${collLong?sequence?map(it -> it)[1 .. 2]?join(', ')}",
                "[iterator][hasNext][next][hasNext][next][hasNext][next]2, 3");
    }

    @Test
    public void dynamicIndexNonSequenceInput() throws Exception {
        assertErrorContains("${coll[1]}", "sequence", "evaluated to a collection");
        assertOutput("${coll?sequence[1]}", "[iterator][hasNext][next][hasNext][next]2");

        assertErrorContains("<#assign t = coll[1..2]>", "sequence", "evaluated to a collection");
        assertOutput("<#assign t = coll?sequence[1..2]>${t?join('')}",
                "[iterator][hasNext][next][hasNext][next][hasNext][next]23");
        assertOutput("<#list coll?sequence[1..2] as it>${it}</#list>",
                "[iterator][hasNext][next][hasNext][next]2[hasNext][next]3");
    }

    @Test
    public void sizeBasicsTest() throws Exception {
        assertOutput("${seq?size}",
                "[size]3");
        assertOutput("${collEx?size}",
                "[size]3");
        assertErrorContains("${coll?size}",
                "sequence", "extended collection");

        assertOutput("${seq?map(x -> x * 10)?size}",
                "[size]3");
        assertOutput("${collEx?sequence?map(x -> x * 10)?size}",
                "[size]3");
        assertOutput("${collEx?map(x -> x * 10)?sequence?size}",
                "[size]3");

        assertOutput("${seq?filter(x -> x != 1)?size}",
                "[size][get 0][get 1][get 2]2");
        assertOutput("${collEx?sequence?filter(x -> x != 1)?size}",
                "[iterator][hasNext][next][hasNext][next][hasNext][next][hasNext]2");
        assertOutput("${collEx?filter(x -> x != 1)?sequence?size}",
                "[iterator][hasNext][next][hasNext][next][hasNext][next][hasNext]2");
    }

    @Test
    public void sizeComparisonTest() throws Exception {
        // These actually aren't related to lazy generation...
        assertOutput("${collEx?size}",
                "[size]3");
        assertOutput("${collEx?size != 0}",
                "[isEmpty]true");
        assertOutput("${0 != collEx?size}",
                "[isEmpty]true");
        assertOutput("${collEx?size == 0}",
                "[isEmpty]false");
        assertOutput("${0 == collEx?size}",
                "[isEmpty]false");
        assertOutput("${(collEx?size >= 1)}",
                "[isEmpty]true");
        assertOutput("${1 <= collEx?size}",
                "[isEmpty]true");
        assertOutput("${collEx?size <= 0}",
                "[isEmpty]false");
        assertOutput("${(0 >= collEx?size)}",
                "[isEmpty]false");
        assertOutput("${collEx?size > 0}",
                "[isEmpty]true");
        assertOutput("${0 < collEx?size}",
                "[isEmpty]true");
        assertOutput("${collEx?size < 1}",
                "[isEmpty]false");
        assertOutput("${1 > collEx?size}",
                "[isEmpty]false");
        assertOutput("${collEx?size == 1}",
                "[size]false");
        assertOutput("${1 == collEx?size}",
                "[size]false");

        // Now the lazy generation things:
        assertOutput("${collLong?sequence?filter(x -> true)?size}",
                "[iterator]" +
                        "[hasNext][next][hasNext][next][hasNext][next]" +
                        "[hasNext][next][hasNext][next][hasNext][next][hasNext]6");
        // Note: "[next]" is added by ?filter, as it has to know if the element matches the predicate.
        assertOutput("${collLong?sequence?filter(x -> true)?size != 0}",
                "[iterator][hasNext][next]true");
        assertOutput("${collLong?sequence?filter(x -> true)?size != 1}",
                "[iterator][hasNext][next][hasNext][next]true");
        assertOutput("${collLong?sequence?filter(x -> true)?size == 1}",
                "[iterator][hasNext][next][hasNext][next]false");
        assertOutput("${collLong?filter(x -> true)?sequence?size == 1}",
                "[iterator][hasNext][next][hasNext][next]false");
        assertOutput("${collLong?sequence?filter(x -> true)?size < 3}",
                "[iterator][hasNext][next][hasNext][next][hasNext][next]false");
    }

    @Test
    public void sizeNonSequenceInput() throws Exception {
        assertErrorContains("${coll?size}", "sequence", "evaluated to a collection");
        assertOutput("${coll?sequence?size}", "[iterator][hasNext][next][hasNext][next][hasNext][next][hasNext]3");
    }

    @Test
    public void firstTest() throws Exception {
        assertOutput("${coll?first}",
                "[iterator][hasNext][next]1");
        assertOutput("${coll?filter(x -> x % 2 == 0)?first}",
                "[iterator][hasNext][next][hasNext][next]2");
    }

    @Test
    public void seqIndexOfTest() throws Exception {
        assertOutput("${coll?seqIndexOf(2)}",
                "[iterator][hasNext][next][hasNext][next]1");
        assertOutput("${coll?filter(x -> x % 2 == 0)?seqIndexOf(2)}",
                "[iterator][hasNext][next][hasNext][next]0");
    }

    @Test
    public void filterTest() throws Exception {
        assertOutput("${coll?filter(x -> x % 2 == 0)?filter(x -> true)?first}",
                "[iterator][hasNext][next][hasNext][next]2");
    }

    @Test
    public void listTest() throws Exception {
        // Note: #list has to fetch elements up to 4 to know if it?hasNext
        String commonSourceExp = "collLong?filter(x -> x % 2 == 0)";
        for (String sourceExp : new String[] {commonSourceExp, "(" + commonSourceExp + ")"}) {
            assertOutput("<#list " + sourceExp + " as it>${it} ${it?hasNext}<#break></#list>",
                    "[iterator][hasNext][next][hasNext][next][hasNext][next][hasNext][next]2 true");
        }
    }

    @Test
    public void biTargetParenthesisTest() throws Exception {
        assertOutput("${(coll?filter(x -> x % 2 == 0))?first}",
                "[iterator][hasNext][next][hasNext][next]2");
    }

    @Test
    public void rangeOperatorTest() throws Exception {
        assertErrorContains("${coll[1..2]?join(', ')}", "sequence", "collection");

        assertOutput("${seq[1..2]?first}", "[size][get 1][get 2]2");
        assertOutput("${seq[1..]?first}",  "[size][get 1][get 2]2");
        assertOutput("${seq[2..1]?first}",  "[size][get 2][get 1]3");

        assertOutput("${seqLong[1..3]?first}", "[size][get 1][get 2][get 3]2");
        assertOutput("${seqLong[1..]?first}",  "[size][get 1][get 2][get 3][get 4][get 5]2");
        assertOutput("${seqLong[3..1]?first}",  "[size][get 3][get 2][get 1]4");

        assertOutput("${seq?map(x->x)[1..2]?first}", "[size][size][get 0][get 1]2");
        assertOutput("${seq?map(x->x)[1..]?first}",  "[size][size][get 0][get 1]2");
        // Why 2 [size]-s above: 1st to validate range. 2nd for the 1st hasNext call on the iterator.
        assertOutput("${seq?map(x->x)[2..1]?first}",  "[size][size][get 0][get 1][get 2]3");

        assertOutput("${seqLong?map(x->x)[1..3]?first}", "[size][size][get 0][get 1]2");
        assertOutput("${seqLong?map(x->x)[1..]?first}",  "[size][size][get 0][get 1]2");
        assertOutput("${seqLong?map(x->x)[3..1]?first}",  "[size][size][get 0][get 1][get 2][get 3]4");

        assertOutput("${seq?filter(x->true)[1..2]?first}", "[size][get 0][get 1]2");
        assertOutput("${seq?filter(x->true)[1..]?first}",  "[size][get 0][get 1]2");
        assertOutput("${seq?filter(x->true)[2..1]?first}",  "[size][get 0][get 1][get 2]3");

        assertOutput("${seqLong?filter(x->true)[1..3]?first}", "[size][get 0][get 1]2");
        assertOutput("${seqLong?filter(x->true)[1..]?first}",  "[size][get 0][get 1]2");
        assertOutput("${seqLong?filter(x->true)[3..1]?first}",  "[size][get 0][get 1][get 2][get 3]4");

        assertOutput("${seq[1..2][0..1]?first}", "[size][get 1][get 2]2");
        assertOutput("${seq?map(x->x)[1..2][0..1]?first}", "[size][size][get 0][get 1]2");
        assertOutput("${seq?filter(x->true)[1..2][0..1]?first}", "[size][get 0][get 1]2");

        assertOutput("<#list seqLong?filter(x->true)[1..3] as it>${it}</#list>",
                "[size][get 0][get 1]2[get 2]3[get 3]4");
        assertOutput("<#list seqLong[1..3] as it>${it}</#list>",
                "[size][get 1][get 2][get 3]234");

        assertOutput("${seq?map(x->x)[1..2]?size}", "[size]2");
        assertOutput("${seq?filter(x->true)[1..2]?size}", "[size][get 0][get 1][get 2]2");
        assertOutput("${seqLong?map(x->x)[2..]?size}", "[size]4");
        assertOutput("${seqLong?filter(x->true)[2..]?size}", "[size][get 0][get 1][get 2][get 3][get 4][get 5]4");
        assertOutput("${seqLong?map(x->x)[2..*3]?size}", "[size]3");
        assertOutput("${seqLong?filter(x->true)[2..*3]?size}", "[size][get 0][get 1][get 2][get 3][get 4]3");
    }

    @Test
    public void testNonDirectCalledBuiltInsAreNotLazy() throws Exception {
        assertOutput("" +
                "<#assign changing = 1>" +
                "<#assign method = [1, 2]?filter(it -> it != changing)?join>" +
                "<#assign changing = 2>" +
                "${method(', ')}",
                "2");
        assertOutput("" +
                "<#assign changing = 1>" +
                "<#assign method = [1, 2]?filter(it -> it != changing)?seq_contains>" +
                "<#assign changing = 2>" +
                "${method(2)?c}",
                "true");
        assertOutput("" +
                "<#assign changing = 1>" +
                "<#assign method = [1, 2]?filter(it -> it != changing)?seq_index_of>" +
                "<#assign changing = 2>" +
                "${method(2)}",
                "0");
    }

    public static abstract class ListContainingTemplateModel {
        protected final List<Number> elements;

        public ListContainingTemplateModel(Number... elements) {
            this.elements = new ArrayList<Number>(Arrays.asList(elements));
        }

        public int size() {
            logCall("size");
            return elements.size();
        }

        protected void logCall(String callDesc) {
            try {
                Environment.getCurrentEnvironment().getOut().write("[" + callDesc + "]");
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

    }

    public static class MonitoredTemplateSequenceModel extends ListContainingTemplateModel
            implements TemplateSequenceModel {
        public MonitoredTemplateSequenceModel(Number... elements) {
            super(elements);
        }

        public TemplateModel get(int index) throws TemplateModelException {
            logCall("get " + index);
            return new SimpleNumber(elements.get(index));
        }

    }

    public static class MonitoredTemplateCollectionModel extends ListContainingTemplateModel
            implements TemplateCollectionModel {
        public MonitoredTemplateCollectionModel(Number... elements) {
            super(elements);
        }

        public TemplateModelIterator iterator() throws TemplateModelException {
            logCall("iterator");
            final Iterator<Number> iterator = elements.iterator();
            return new TemplateModelIterator() {
                public TemplateModel next() throws TemplateModelException {
                    logCall("next");
                    return new SimpleNumber(iterator.next());
                }

                public boolean hasNext() throws TemplateModelException {
                    logCall("hasNext");
                    return iterator.hasNext();
                }
            };
        }
    }

    public static class MonitoredTemplateCollectionModelEx extends MonitoredTemplateCollectionModel
            implements TemplateCollectionModelEx {
        public MonitoredTemplateCollectionModelEx(Number... elements) {
            super(elements);
        }

        public boolean isEmpty() throws TemplateModelException {
            logCall("isEmpty");
            return elements.isEmpty();
        }
    }

}
