/*
 * Copyright (c) 2023, 2024, 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.
 */
import java.util.List;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Supplier;
import java.util.stream.*;
import java.util.stream.Gatherer;

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assumptions.*;

/**
 * @test
 * @summary Testing public API of Gatherer
 * @run junit GathererAPITest
 */

public class GathererAPITest {
    final static Supplier<Void> initializer = () -> (Void)null;
    final static Gatherer.Integrator<Void, Integer, Integer> integrator = (v,e,d) -> d.push(e);
    final static BinaryOperator<Void> combiner = (l,r) -> l;
    final static BiConsumer<Void,Gatherer.Downstream<? super Integer>> finisher = (v,d) -> {};

    final static Supplier<Void> nullInitializer = null;
    final static Gatherer.Integrator<Void, Integer, Integer> nullIntegrator = null;
    final static BinaryOperator<Void> nullCombiner = null;
    final static BiConsumer<Void,Gatherer.Downstream<? super Integer>> nullFinisher = null;

    private final static <T> Gatherer<T,?,T> passthrough() {
        return Gatherer.of(
                () -> (Void)null,
                Gatherer.Integrator.<Void,T,T>ofGreedy((v,e,d) -> d.push(e)),
                (l,r) -> l,
                (v,d) -> {}
        );
    }

    private final static <T,A,R> Gatherer<T,A,R> verifyGathererContract(Gatherer<T,A,R> gatherer) {
        // basics
        assertNotNull(gatherer);

        // components
        assertNotNull(gatherer.initializer());
        assertNotNull(gatherer.integrator());
        assertNotNull(gatherer.combiner());
        assertNotNull(gatherer.finisher());
        assertNotNull(gatherer.andThen(passthrough()));

        return gatherer;
    }

    private final static <T,A,R> Gatherer<T,A,R> verifyGathererStructure(
            Gatherer<T,A,R> gatherer,
            Supplier<A> expectedSupplier,
            Gatherer.Integrator<A,T,R> expectedIntegrator,
            BinaryOperator<A> expectedCombiner,
            BiConsumer<A,Gatherer.Downstream<? super R>> expectedFinisher
    ) {
        // basics
        assertNotNull(gatherer);

        // components
        assertSame(expectedSupplier, gatherer.initializer());
        assertSame(expectedIntegrator, gatherer.integrator());
        assertSame(expectedCombiner, gatherer.combiner());
        assertSame(expectedFinisher, gatherer.finisher());

        return gatherer;
    }

    @Test
    public void testGathererDefaults() {
        final Gatherer.Integrator<Void,Void,Void> expectedIntegrator =
                (a,b,c) -> false;

        class Test implements Gatherer<Void,Void,Void> {
            @Override
            public Integrator<Void, Void, Void> integrator() {
                return expectedIntegrator;
            }
        }

        var t = new Test();
        assertSame(Gatherer.<Void>defaultInitializer(), t.initializer());
        assertSame(expectedIntegrator, t.integrator());
        assertSame(Gatherer.<Void>defaultCombiner(), t.combiner());
        assertSame(Gatherer.<Void,Gatherer.Downstream<? super Void>>defaultFinisher(), t.finisher());
    }

    @Test
    public void testDownstreamDefaults() {
        class Test implements Gatherer.Downstream<Void> {
            @Override public boolean push(Void v) { return false; }
        }

        var t = new Test();
        assertEquals(false, t.isRejecting());
    }

    @Test
    public void testGathererFactoriesNPE() {
        assertThrows(NullPointerException.class,
                () -> Gatherer.of(nullInitializer, integrator, combiner, finisher));
        assertThrows(NullPointerException.class,
                () -> Gatherer.of(initializer, nullIntegrator, combiner, finisher));
        assertThrows(NullPointerException.class,
                () -> Gatherer.of(initializer, integrator, nullCombiner, finisher));
        assertThrows(NullPointerException.class,
                () -> Gatherer.of(initializer, integrator, combiner, nullFinisher));

        assertThrows(NullPointerException.class,
                () -> Gatherer.of(nullIntegrator));

        assertThrows(NullPointerException.class,
                () -> Gatherer.of(nullIntegrator, finisher));
        assertThrows(NullPointerException.class,
                () -> Gatherer.of(integrator, nullFinisher));

        assertThrows(NullPointerException.class,
                () -> Gatherer.ofSequential(nullInitializer, integrator));
        assertThrows(NullPointerException.class,
                () -> Gatherer.ofSequential(initializer, nullIntegrator));

        assertThrows(NullPointerException.class,
                () -> Gatherer.ofSequential(nullIntegrator));

        assertThrows(NullPointerException.class,
                () -> Gatherer.ofSequential(nullIntegrator, finisher));
        assertThrows(NullPointerException.class,
                () -> Gatherer.ofSequential(integrator, nullFinisher));

        assertThrows(NullPointerException.class,
                () -> Gatherer.ofSequential(nullInitializer, integrator, finisher));
        assertThrows(NullPointerException.class,
                () -> Gatherer.ofSequential(initializer, nullIntegrator, finisher));
        assertThrows(NullPointerException.class,
                () -> Gatherer.ofSequential(initializer, integrator, nullFinisher));
    }

    @Test
    public void testGathererFactoriesAPI() {
        final var defaultInitializer = Gatherer.<Void>defaultInitializer();
        final var defaultCombiner = Gatherer.<Void>defaultCombiner();
        final var defaultFinisher = Gatherer.<Void,Integer>defaultFinisher();

        var g1 = verifyGathererContract(passthrough()); // Quis custodiet ipsos custodes?
        verifyGathererContract(g1.andThen(g1));

        var g2 = verifyGathererContract(Gatherer.of(integrator));
        verifyGathererContract(g2.andThen(g2));
        assertSame(defaultInitializer, g2.initializer());
        assertSame(integrator, g2.integrator());
        assertNotSame(defaultCombiner, g2.combiner());
        assertSame(defaultFinisher, g2.finisher());

        var g3 = verifyGathererContract(Gatherer.of(integrator, finisher));
        verifyGathererContract(g3.andThen(g3));
        assertSame(integrator, g3.integrator());
        assertNotSame(defaultCombiner, g3.combiner());
        assertSame(finisher, g3.finisher());

        var g4 = verifyGathererContract(Gatherer.ofSequential(integrator));
        verifyGathererContract(g4.andThen(g4));
        verifyGathererStructure(g4, defaultInitializer, integrator, defaultCombiner, defaultFinisher);

        var g5 = verifyGathererContract(Gatherer.ofSequential(initializer, integrator));
        verifyGathererContract(g5.andThen(g5));
        verifyGathererStructure(g5, initializer, integrator, defaultCombiner, defaultFinisher);

        var g6 = verifyGathererContract(Gatherer.ofSequential(integrator, finisher));
        verifyGathererContract(g6.andThen(g6));
        verifyGathererStructure(g6, defaultInitializer, integrator, defaultCombiner, finisher);

        var g7 = verifyGathererContract(Gatherer.ofSequential(initializer, integrator, finisher));
        verifyGathererContract(g7.andThen(g7));
        verifyGathererStructure(g7, initializer, integrator, defaultCombiner, finisher);

        var g8 = verifyGathererContract(Gatherer.of(initializer, integrator, combiner, finisher));
        verifyGathererContract(g8.andThen(g8));
        verifyGathererStructure(g8, initializer, integrator, combiner, finisher);
    }

    @Test
    public void testGathererVariance() {

        // Make sure that Gatherers can pass-through type
        Gatherer<Number,?,Number> nums = Gatherer.of((unused, element, downstream) -> downstream.push(element));

        // Make sure that Gatherers can upcast the output type from the input type
        Gatherer<Number,?,Object> upcast = Gatherer.of((unused, element, downstream) -> downstream.push(element));

        // Make sure that Gatherers can consume a supertype of the Stream output
        assertEquals(List.of(1,2,3,4,5), Stream.<Integer>of(1,2,3,4,5).gather(nums).toList());

        Gatherer<Integer,?,Integer> ints = Gatherer.of((unused, element, downstream) -> downstream.push(element));

        // Make sure that Gatherers can be composed where the output is a subtype of the input type of the next
        Gatherer<Integer,?,Number> composition = ints.andThen(nums);

        // Make sure that composition works transitively, typing-wise
        Gatherer<Integer,?,Object> upcastComposition = ints.andThen(nums.andThen(upcast));

        assertEquals(List.of(1,2,3,4,5), Stream.<Integer>of(1,2,3,4,5).gather(composition).toList());
        assertEquals(List.of(1,2,3,4,5), Stream.<Integer>of(1,2,3,4,5).gather(upcastComposition).toList());
    }
}
