/*
 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.tests.java.util.stream;

import org.testng.annotations.Test;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LambdaTestHelpers;
import java.util.stream.LongStream;
import java.util.stream.OpTestCase;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import java.util.stream.StreamTestDataProvider;
import java.util.stream.TestData;

import static java.util.stream.LambdaTestHelpers.*;

/**
 * SliceOpTest
 *
 * @author Brian Goetz
 */
@Test
public class SliceOpTest extends OpTestCase {

    public void testSkip() {
        assertCountSum(countTo(0).stream().skip(0), 0, 0);
        assertCountSum(countTo(0).stream().skip(4), 0, 0);
        assertCountSum(countTo(4).stream().skip(4), 0, 0);
        assertCountSum(countTo(4).stream().skip(2), 2, 7);
        assertCountSum(countTo(4).stream().skip(0), 4, 10);

        assertCountSum(countTo(0).parallelStream().skip(0), 0, 0);
        assertCountSum(countTo(0).parallelStream().skip(4), 0, 0);
        assertCountSum(countTo(4).parallelStream().skip(4), 0, 0);
        assertCountSum(countTo(4).parallelStream().skip(2), 2, 7);
        assertCountSum(countTo(4).parallelStream().skip(0), 4, 10);

        exerciseOps(Collections.emptyList(), s -> s.skip(0), Collections.emptyList());
        exerciseOps(Collections.emptyList(), s -> s.skip(10), Collections.emptyList());

        exerciseOps(countTo(1), s -> s.skip(0), countTo(1));
        exerciseOps(countTo(1), s -> s.skip(1), Collections.emptyList());
        exerciseOps(countTo(100), s -> s.skip(0), countTo(100));
        exerciseOps(countTo(100), s -> s.skip(10), range(11, 100));
        exerciseOps(countTo(100), s -> s.skip(100), Collections.emptyList());
        exerciseOps(countTo(100), s -> s.skip(200), Collections.emptyList());
    }

    public void testLimit() {
        assertCountSum(countTo(0).stream().limit(4), 0, 0);
        assertCountSum(countTo(2).stream().limit(4), 2, 3);
        assertCountSum(countTo(4).stream().limit(4), 4, 10);
        assertCountSum(countTo(8).stream().limit(4), 4, 10);

        assertCountSum(countTo(0).parallelStream().limit(4), 0, 0);
        assertCountSum(countTo(2).parallelStream().limit(4), 2, 3);
        assertCountSum(countTo(4).parallelStream().limit(4), 4, 10);
        assertCountSum(countTo(8).parallelStream().limit(4), 4, 10);

        exerciseOps(Collections.emptyList(), s -> s.limit(0), Collections.emptyList());
        exerciseOps(Collections.emptyList(), s -> s.limit(10), Collections.emptyList());
        exerciseOps(countTo(1), s -> s.limit(0), Collections.emptyList());
        exerciseOps(countTo(1), s -> s.limit(1), countTo(1));
        exerciseOps(countTo(100), s -> s.limit(0), Collections.emptyList());
        exerciseOps(countTo(100), s -> s.limit(10), countTo(10));
        exerciseOps(countTo(100), s -> s.limit(10).limit(10), countTo(10));
        exerciseOps(countTo(100), s -> s.limit(100), countTo(100));
        exerciseOps(countTo(100), s -> s.limit(100).limit(10), countTo(10));
        exerciseOps(countTo(100), s -> s.limit(200), countTo(100));
    }

    public void testSkipLimit() {
        exerciseOps(Collections.emptyList(), s -> s.skip(0).limit(0), Collections.emptyList());
        exerciseOps(Collections.emptyList(), s -> s.skip(0).limit(10), Collections.emptyList());
        exerciseOps(Collections.emptyList(), s -> s.skip(10).limit(0), Collections.emptyList());
        exerciseOps(Collections.emptyList(), s -> s.skip(10).limit(10), Collections.emptyList());

        exerciseOps(countTo(100), s -> s.skip(0).limit(100), countTo(100));
        exerciseOps(countTo(100), s -> s.skip(0).limit(10), countTo(10));
        exerciseOps(countTo(100), s -> s.skip(0).limit(0), Collections.emptyList());
        exerciseOps(countTo(100), s -> s.skip(10).limit(100), range(11, 100));
        exerciseOps(countTo(100), s -> s.skip(10).limit(10), range(11, 20));
        exerciseOps(countTo(100), s -> s.skip(10).limit(0), Collections.emptyList());
        exerciseOps(countTo(100), s -> s.skip(100).limit(100), Collections.emptyList());
        exerciseOps(countTo(100), s -> s.skip(100).limit(10), Collections.emptyList());
        exerciseOps(countTo(100), s -> s.skip(100).limit(0), Collections.emptyList());
        exerciseOps(countTo(100), s -> s.skip(200).limit(100), Collections.emptyList());
        exerciseOps(countTo(100), s -> s.skip(200).limit(10), Collections.emptyList());
        exerciseOps(countTo(100), s -> s.skip(200).limit(0), Collections.emptyList());
    }

    public void testSlice() {
        exerciseOps(Collections.emptyList(), s -> s.skip(0).limit(0), Collections.emptyList());
        exerciseOps(Collections.emptyList(), s -> s.skip(0).limit(10), Collections.emptyList());
        exerciseOps(Collections.emptyList(), s -> s.skip(10).limit(10), Collections.emptyList());
        exerciseOps(Collections.emptyList(), s -> s.skip(10).limit(20), Collections.emptyList());

        exerciseOps(countTo(100), s -> s.skip(0).limit(100), countTo(100));
        exerciseOps(countTo(100), s -> s.skip(0).limit(10), countTo(10));
        exerciseOps(countTo(100), s -> s.skip(0).limit(0), Collections.emptyList());
        exerciseOps(countTo(100), s -> s.skip(10).limit(100), range(11, 100));
        exerciseOps(countTo(100), s -> s.skip(10).limit(10), range(11, 20));
        exerciseOps(countTo(100), s -> s.skip(10).limit(0), Collections.emptyList());
        exerciseOps(countTo(100), s -> s.skip(100).limit(100), Collections.emptyList());
        exerciseOps(countTo(100), s -> s.skip(100).limit(10), Collections.emptyList());
        exerciseOps(countTo(100), s -> s.skip(100).limit(0), Collections.emptyList());
        exerciseOps(countTo(100), s -> s.skip(200).limit(100), Collections.emptyList());
        exerciseOps(countTo(100), s -> s.skip(200).limit(10), Collections.emptyList());
        exerciseOps(countTo(100), s -> s.skip(200).limit(0), Collections.emptyList());
    }

    private int sliceSize(int dataSize, int skip, int limit) {
        int size = Math.max(0, dataSize - skip);
        if (limit >= 0)
            size = Math.min(size, limit);
        return size;
    }

    private int sliceSize(int dataSize, int skip) {
        return Math.max(0, dataSize - skip);
    }

    @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class,
          groups = { "serialization-hostile" })
    public void testSkipOps(String name, TestData.OfRef<Integer> data) {
        List<Integer> skips = sizes(data.size());

        for (int s : skips) {
            setContext("skip", s);
            testSliceMulti(data,
                           sliceSize(data.size(), s),
                           st -> st.skip(s),
                           st -> st.skip(s),
                           st -> st.skip(s),
                           st -> st.skip(s));

            testSliceMulti(data,
                           sliceSize(sliceSize(data.size(), s), s/2),
                           st -> st.skip(s).skip(s / 2),
                           st -> st.skip(s).skip(s / 2),
                           st -> st.skip(s).skip(s / 2),
                           st -> st.skip(s).skip(s / 2));
        }
    }

    @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class,
          groups = { "serialization-hostile" })
    public void testSkipLimitOps(String name, TestData.OfRef<Integer> data) {
        List<Integer> skips = sizes(data.size());
        List<Integer> limits = skips;

        for (int s : skips) {
            setContext("skip", s);
            for (int l : limits) {
                setContext("limit", l);
                testSliceMulti(data,
                               sliceSize(sliceSize(data.size(), s), 0, l),
                               st -> st.skip(s).limit(l),
                               st -> st.skip(s).limit(l),
                               st -> st.skip(s).limit(l),
                               st -> st.skip(s).limit(l));
            }
        }
    }

    public void testSkipLimitOpsWithNonSplittingSpliterator() {
        class NonSplittingNotSubsizedOrderedSpliterator<T> implements Spliterator<T> {
            Spliterator<T> s;

            NonSplittingNotSubsizedOrderedSpliterator(Spliterator<T> s) {
                assert s.hasCharacteristics(Spliterator.ORDERED);
                this.s = s;
            }

            @Override
            public boolean tryAdvance(Consumer<? super T> action) {
                return s.tryAdvance(action);
            }

            @Override
            public void forEachRemaining(Consumer<? super T> action) {
                s.forEachRemaining(action);
            }

            @Override
            public Spliterator<T> trySplit() {
                return null;
            }

            @Override
            public long estimateSize() {
                return s.estimateSize();
            }

            @Override
            public int characteristics() {
                return s.characteristics() & ~(Spliterator.SUBSIZED);
            }

            @Override
            public Comparator<? super T> getComparator() {
                return s.getComparator();
            }
        }
        List<Integer> list = IntStream.range(0, 100).boxed().collect(Collectors.toList());
        TestData.OfRef<Integer> data = TestData.Factory.ofSupplier(
                "Non splitting, not SUBSIZED, ORDERED, stream",
                () -> StreamSupport.stream(new NonSplittingNotSubsizedOrderedSpliterator<>(list.spliterator()), false));

        testSkipLimitOps("testSkipLimitOpsWithNonSplittingSpliterator", data);
    }

    @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class,
          groups = { "serialization-hostile" })
    public void testLimitOps(String name, TestData.OfRef<Integer> data) {
        List<Integer> limits = sizes(data.size());

        for (int l : limits) {
            setContext("limit", l);
            testSliceMulti(data,
                           sliceSize(data.size(), 0, l),
                           st -> st.limit(l),
                           st -> st.limit(l),
                           st -> st.limit(l),
                           st -> st.limit(l));
        }

        for (int l : limits) {
            setContext("limit", l);
            testSliceMulti(data,
                           sliceSize(sliceSize(data.size(), 0, l), 0, l / 2),
                           st -> st.limit(l).limit(l / 2),
                           st -> st.limit(l).limit(l / 2),
                           st -> st.limit(l).limit(l / 2),
                           st -> st.limit(l).limit(l / 2));
        }
    }

    private ResultAsserter<Iterable<Integer>> sliceResultAsserter(Iterable<Integer> data,
                                                                  int expectedSize) {
        return (act, exp, ord, par) -> {
            if (par & !ord) {
                List<Integer> expected = new ArrayList<>();
                data.forEach(expected::add);

                List<Integer> actual = new ArrayList<>();
                act.forEach(actual::add);

                assertEquals(actual.size(), expectedSize);
                assertTrue(expected.containsAll(actual));
            }
            else {
                LambdaTestHelpers.assertContents(act, exp);
            }
        };
    }

    private void testSliceMulti(TestData.OfRef<Integer> data,
                                int expectedSize,
                                Function<Stream<Integer>, Stream<Integer>> mRef,
                                Function<IntStream, IntStream> mInt,
                                Function<LongStream, LongStream> mLong,
                                Function<DoubleStream, DoubleStream> mDouble) {

        @SuppressWarnings({ "rawtypes", "unchecked" })
        Function<Stream<Integer>, Stream<Integer>>[] ms = new Function[4];
        ms[0] = mRef;
        ms[1] = s -> mInt.apply(s.mapToInt(e -> e)).mapToObj(e -> e);
        ms[2] = s -> mLong.apply(s.mapToLong(e -> e)).mapToObj(e -> (int) e);
        ms[3] = s -> mDouble.apply(s.mapToDouble(e -> e)).mapToObj(e -> (int) e);
        testSliceMulti(data, expectedSize, ms);
    }

    @SafeVarargs
    private final void testSliceMulti(TestData.OfRef<Integer> data,
                                      int expectedSize,
                                      Function<Stream<Integer>, Stream<Integer>>... ms) {
        for (int i = 0; i < ms.length; i++) {
            setContext("mIndex", i);
            Function<Stream<Integer>, Stream<Integer>> m = ms[i];
            Collection<Integer> sr = withData(data)
                    .stream(m)
                    .resultAsserter(sliceResultAsserter(data, expectedSize))
                    .exercise();
            assertEquals(sr.size(), expectedSize);
        }
    }

    public void testLimitSort() {
        List<Integer> l = countTo(100);
        Collections.reverse(l);
        exerciseOps(l, s -> s.limit(10).sorted(Comparator.naturalOrder()));
    }

    @Test(groups = { "serialization-hostile" })
    public void testLimitShortCircuit() {
        for (int l : Arrays.asList(0, 10)) {
            setContext("l", l);
            AtomicInteger ai = new AtomicInteger();
            countTo(100).stream()
                    .peek(i -> ai.getAndIncrement())
                    .limit(l).toArray();
            // For the case of a zero limit, one element will get pushed through the sink chain
            assertEquals(ai.get(), l, "tee block was called too many times");
        }
    }

    private List<Integer> sizes(int size) {
        if (size < 4) {
            return Arrays.asList(0, 1, 2, 3, 4, 6);
        }
        else {
            return Arrays.asList(0, 1, size / 2, size - 1, size, size + 1, 2 * size);
        }
    }
}
