/*
 * Copyright (c) 2021, 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.math.BigInteger;
import java.security.SecureRandom;
import java.util.concurrent.ThreadLocalRandom;
import java.util.random.RandomGenerator;
import java.util.random.RandomGenerator.ArbitrarilyJumpableGenerator;
import java.util.random.RandomGenerator.JumpableGenerator;
import java.util.random.RandomGenerator.LeapableGenerator;
import java.util.random.RandomGenerator.SplittableGenerator;
import java.util.random.RandomGenerator.StreamableGenerator;
import java.util.random.RandomGeneratorFactory;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;

/**
 * @test
 * @summary Ensure that all implementations of RandomGenerator supply required methods.
 * @bug 8248862
 * @run main RandomTestCoverage
 * @key randomness
 */


public class RandomTestCoverage {
    static void coverRandomGenerator(RandomGenerator rng) {
        boolean bool = rng.nextBoolean();
        byte[] bytes = new byte[8];
        rng.nextBytes(bytes);

        int i1 = rng.nextInt();
        int i2 = rng.nextInt(10);
        int i3 = rng.nextInt(5, 10);

        long l1 = rng.nextLong();
        long l2 = rng.nextLong(10L);
        long l3 = rng.nextLong(5L, 10L);

        float f1 = rng.nextFloat();
        float f2 = rng.nextFloat(1.0f);
        float f3 = rng.nextFloat(0.5f, 1.0f);

        double d1 = rng.nextDouble();
        double d2 = rng.nextDouble(1.0);
        double d3 = rng.nextDouble(0.5, 1.0);

        double exp = rng.nextExponential();
        double gauss1 = rng.nextGaussian();
        double gauss2 = rng.nextGaussian(0.5, 2.0);

        IntStream intStream1 = rng.ints();
        IntStream intStream2 = rng.ints(5, 10);
        IntStream intStream3 = rng.ints(5L);
        IntStream intStream4 = rng.ints(5L, 5, 10);

        LongStream longStream1 = rng.longs();
        LongStream longStream2 = rng.longs(5L, 10L);
        LongStream longStream3 = rng.longs(5L);
        LongStream longStream4 = rng.longs(5L, 5L, 10L);

        DoubleStream doubleStream1 = rng.doubles();
        DoubleStream doubleStream2 = rng.doubles(0.5, 1.0);
        DoubleStream doubleStream3 = rng.doubles(5);
        DoubleStream doubleStream4 = rng.doubles(5, 0.5, 1.0);
    }

    static void checkPredicates(RandomGeneratorFactory<RandomGenerator> factory) {
        RandomGenerator rng = factory.create();
        if (rng instanceof ArbitrarilyJumpableGenerator != factory.isArbitrarilyJumpable()) {
            throw new RuntimeException("isArbitrarilyJumpable failing");
        }
        if (rng instanceof JumpableGenerator != factory.isJumpable()) {
            throw new RuntimeException("isJumpable failing");
        }
        if (rng instanceof LeapableGenerator != factory.isLeapable()) {
            throw new RuntimeException("isLeapable failing");
        }
        if (rng instanceof SplittableGenerator != factory.isSplittable()) {
            throw new RuntimeException("isArbitrarilyJumpable failing");
        }
        if (rng instanceof StreamableGenerator != factory.isStreamable()) {
            throw new RuntimeException("isArbitrarilyJumpable failing");
        }
    }

    static void coverStreamable(StreamableGenerator rng) {
        Stream<RandomGenerator> rngs1 = rng.rngs();
        Stream<RandomGenerator> rngs2 = rng.rngs(5L);
    }

    static void coverSplittable(SplittableGenerator rng) {
        SplittableGenerator s1 = rng.split();
        SplittableGenerator s2 = rng.split(rng);
        Stream<SplittableGenerator> s3 = rng.splits();
        Stream<SplittableGenerator> s4 = rng.splits(5L);
        Stream<SplittableGenerator> s5 = rng.splits(rng);
        Stream<SplittableGenerator> s6 = rng.splits(5L, rng);
    }

    static void coverJumpable(JumpableGenerator rng) {
        JumpableGenerator j1 = rng.copy();
        rng.jump();
        RandomGenerator j2 = rng.copyAndJump();
        double d = rng.jumpDistance();
        Stream<RandomGenerator> j3 = rng.jumps();
        Stream<RandomGenerator> j4 = rng.jumps(5L);
    }

    static void coverLeapable(LeapableGenerator rng) {
        LeapableGenerator l1 = rng.copy();
        rng.leap();
        JumpableGenerator l2 = rng.copyAndLeap();
        double d = rng.leapDistance();
        Stream<JumpableGenerator> l3 = rng.leaps();
        Stream<JumpableGenerator> l4 = rng.leaps(5L);
    }

    static void coverArbitrarilyJumpable(ArbitrarilyJumpableGenerator rng) {
        ArbitrarilyJumpableGenerator a1 = rng.copy();
        rng.jump();
        rng.leap();
        rng.jump(1.2345);
        rng.jumpPowerOfTwo(4);
        RandomGenerator a2 = rng.copyAndJump();
        RandomGenerator a3 = rng.copyAndJump(1.2345);
        Stream<ArbitrarilyJumpableGenerator> a4 = rng.jumps(1.2345);
        Stream<ArbitrarilyJumpableGenerator> a5 = rng.jumps(5L, 1.2345);

    }

    static void coverOf(String name) {
        coverRandomGenerator(RandomGenerator.of(name));
        coverFactory(RandomGeneratorFactory.of(name));
    }

    static void coverFactory(RandomGeneratorFactory<RandomGenerator> factory) {
        String name = factory.name();
        String group = factory.group();
        int stateBits = factory.stateBits();
        int equidistribution = factory.equidistribution();
        BigInteger period = factory.period();
        boolean isStatistical = factory.isStatistical();
        boolean isStochastic = factory.isStochastic();
        boolean isHardware = factory.isHardware();
        boolean isArbitrarilyJumpable = factory.isArbitrarilyJumpable();
        boolean isJumpable = factory.isJumpable();
        boolean isLeapable = factory.isLeapable();
        boolean isSplittable = factory.isSplittable();

        coverRandomGenerator(factory.create());
        // test create(long)
        switch (factory.name()) {
            // SecureRandom doesn't have long constructors so we expect
            // UnsupportedOperationException
            case "SecureRandom" -> {
                try {
                    factory.create(12345L);
                    throw new AssertionError("RandomGeneratorFactory.create(long) was expected" +
                            "to throw UnsupportedOperationException for " + factory.name() + " but didn't");
                } catch (UnsupportedOperationException ignored) {
                }
            }
            default -> coverRandomGenerator(factory.create(12345L));
        }
        // test create(byte[])
        switch (factory.name()) {
            // these don't have byte[] constructors so we expect UnsupportedOperationException
            case "Random",
                 "SplittableRandom" -> {
                try {
                    factory.create(new byte[] {1, 2, 3, 4, 5, 6, 7, 8});
                    throw new AssertionError("RandomGeneratorFactory.create(byte[]) was expected" +
                            "to throw UnsupportedOperationException for " + factory.name() + " but didn't");
                } catch (UnsupportedOperationException ignored) {
                }
            }
            default -> coverRandomGenerator(factory.create(new byte[] {1, 2, 3, 4, 5, 6, 7, 8}));
        }
    }

    static void coverDefaults() {
        RandomGeneratorFactory<RandomGenerator> factory =
            RandomGeneratorFactory.getDefault();
        RandomGenerator rng = RandomGenerator.getDefault();
    }

    public static void main(String[] args) throws Throwable {
        RandomGeneratorFactory.all()
                .forEach(factory -> {
                    coverFactory(factory);
                    coverOf(factory.name());
                 });
        RandomGeneratorFactory.all()
                .filter(RandomGeneratorFactory::isStreamable)
                .forEach(factory -> {
                    coverStreamable((StreamableGenerator)factory.create());
                });
        RandomGeneratorFactory.all()
                .filter(RandomGeneratorFactory::isSplittable)
                .forEach(factory -> {
                    coverSplittable((SplittableGenerator)factory.create());
                });
        RandomGeneratorFactory.all()
                .filter(RandomGeneratorFactory::isJumpable)
                .forEach(factory -> {
                    coverJumpable((JumpableGenerator)factory.create());
                });
        RandomGeneratorFactory.all()
                .filter(RandomGeneratorFactory::isLeapable)
                .forEach(factory -> {
                    coverLeapable((LeapableGenerator)factory.create());
                });
        RandomGeneratorFactory.all()
                .filter(RandomGeneratorFactory::isArbitrarilyJumpable)
                .forEach(factory -> {
                    coverArbitrarilyJumpable((ArbitrarilyJumpableGenerator)factory.create());
                });
        RandomGeneratorFactory.all()
                .forEach(RandomTestCoverage::checkPredicates);

        coverRandomGenerator(new SecureRandom());
        coverRandomGenerator(ThreadLocalRandom.current());
        coverDefaults();
    }
}
