/*-
 * 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 org.apache.sling.query.impl.iterator;

import static org.apache.sling.query.TestUtils.l;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import org.apache.sling.query.TestUtils;
import org.apache.sling.query.api.internal.ElementToIteratorFunction;
import org.apache.sling.query.api.internal.IteratorToIteratorFunction;
import org.apache.sling.query.api.internal.Option;
import org.apache.sling.query.impl.function.IdentityFunction;
import org.apache.sling.query.impl.function.IteratorToIteratorFunctionWrapper;
import org.apache.sling.query.impl.function.SliceFunction;
import org.junit.Assert;
import org.junit.Test;

public class SuppTest {

    @Test
    public void testIdentity() {
        test(l("a", "b", "c", "d", "e"), l("a", "b", "c", "d", "e"), new IdentityFunction<String>());
    }

    @Test
    public void testNoFirst() {
        test(l("a", "b", "c", "d", "e"), l(null, "b", "c", "d", "e"), new SliceFunction<String>(1));
    }

    @Test
    public void testNoSecond() {
        testExpanding(l("a", "---"), l("a"));
    }

    @Test
    public void testNoTwoFirst() {
        test(l("a", "b", "c", "d", "e"), l(null, null, "c", "d", "e"), new SliceFunction<String>(2));
    }

    @Test
    public void testNoLast() {
        test(l("a", "b", "c", "d", "e"), l("a", "b", "c", "d"), new SliceFunction<String>(0, 3));
    }

    @Test
    public void testNoTwoLast() {
        test(l("a", "b", "c", "d", "e"), l("a", "b", "c"), new SliceFunction<String>(0, 2));
    }

    @Test
    public void testJustFirst() {
        test(l("a", "b", "c", "d", "e"), l("a"), new SliceFunction<String>(0, 0));
    }

    @Test
    public void testExpandFirst() {
        testExpanding(l("+", "b", "c", "d", "e"), l("+", "b", "c", "d", "e"));
    }

    @Test
    public void testExpandMiddle() {
        testExpanding(l("a", "b", "+", "d", "e"), l("a", "b", "+", "d", "e"));
    }

    @Test
    public void testExpandLast() {
        testExpanding(l("a", "b", "c", "d", "+"), l("a", "b", "c", "d", "+"));
    }

    @Test
    public void testRemoveFirst() {
        testExpanding(l("-", "b", "c", "d", "e"), l(null, "b", "c", "d", "e"));
        testExpanding(l("---", "b", "c", "d", "e"), l(null, "b", "c", "d", "e"));
    }

    @Test
    public void testRemoveMiddle() {
        testExpanding(l("a", "b", "-", "d", "e"), l("a", "b", null, "d", "e"));
        testExpanding(l("a", "b", "---", "d", "e"), l("a", "b", null, "d", "e"));
    }

    @Test
    public void testRemoveLast() {
        testExpanding(l("a", "b", "c", "d", "-"), l("a", "b", "c", "d"));
        testExpanding(l("a", "b", "c", "d", "---"), l("a", "b", "c", "d"));
    }

    private static void testExpanding(List<String> input, List<String> output) {
        test(input, output, EXPANDING_FUNCTION);
    }

    private static <T> void test(List<T> input, List<T> output, IteratorToIteratorFunction<T> function) {
        List<Option<T>> optionInput = TestUtils.optionList(input);
        List<Option<T>> expectedOutput = TestUtils.optionList(output);
        Iterator<Option<T>> actualOutputIterator = new SuppIterator<T>(optionInput, function);
        List<Option<T>> actualOutput = TestUtils.iteratorToList(actualOutputIterator);
        Assert.assertEquals(expectedOutput, actualOutput);
    }

    private static final IteratorToIteratorFunctionWrapper<String> EXPANDING_FUNCTION = new IteratorToIteratorFunctionWrapper<String>(
            new ElementToIteratorFunction<String>() {
                @Override
                public Iterator<String> apply(String input) {
                    if ("+".equals(input)) {
                        return Arrays.asList("a", "b", "c").iterator();
                    } else if ("-".equals(input)) {
                        return Arrays.<String>asList().iterator();
                    } else if ("---".equals(input)) {
                        return Arrays.<String>asList(null, null, null).iterator();
                    } else {
                        return Arrays.asList(input).iterator();
                    }
                }
            });
}