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

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;

import org.apache.commons.lang3.Validate;

/**
 * <p>
 * Generates random Unicode strings containing the specified number of code points.
 * Instances are created using a builder class, which allows the
 * callers to define the properties of the generator. See the documentation for the
 * {@link Builder} class to see available properties.
 * </p>
 * <pre>
 * // Generates a 20 code point string, using only the letters a-z
 * RandomStringGenerator generator = new RandomStringGenerator.Builder()
 *     .withinRange('a', 'z').build();
 * String randomLetters = generator.generate(20);
 * </pre>
 * <pre>
 * // Using Apache Commons RNG for randomness
 * UniformRandomProvider rng = RandomSource.create(...);
 * // Generates a 20 code point string, using only the letters a-z
 * RandomStringGenerator generator = new RandomStringGenerator.Builder()
 *     .withinRange('a', 'z')
 *     .usingRandom(rng::nextInt) // uses Java 8 syntax
 *     .build();
 * String randomLetters = generator.generate(20);
 * </pre>
 * <p>
 * {@code RandomStringBuilder} instances are immutable and thread-safe.
 * </p>
 * @since 1.1
 */
public final class RandomStringGenerator {

    /**
     * The smallest allowed code point (inclusive).
     */
    private final int minimumCodePoint;

    /**
     * The largest allowed code point (inclusive).
     */
    private final int maximumCodePoint;

    /**
     * Filters for code points.
     */
    private final Set<CharacterPredicate> inclusivePredicates;

    /**
     * The source of randomness for this generator.
     */
    private final TextRandomProvider random;

    /**
     * Constructs the generator.
     *
     * @param minimumCodePoint
     *            smallest allowed code point (inclusive)
     * @param maximumCodePoint
     *            largest allowed code point (inclusive)
     * @param inclusivePredicates
     *            filters for code points
     * @param random
     *            source of randomness
     */
    private RandomStringGenerator(int minimumCodePoint, int maximumCodePoint,
            Set<CharacterPredicate> inclusivePredicates, TextRandomProvider random) {
        this.minimumCodePoint = minimumCodePoint;
        this.maximumCodePoint = maximumCodePoint;
        this.inclusivePredicates = inclusivePredicates;
        this.random = random;
    }

    /**
     * Generates a random number within a range, using a {@link ThreadLocalRandom} instance
     * or the user-supplied source of randomness.
     *
     * @param minInclusive
     *            the minimum value allowed
     * @param maxInclusive
     *            the maximum value allowed
     * @return the random number.
     */
    private int generateRandomNumber(final int minInclusive, final int maxInclusive) {
        if (random != null) {
            return random.nextInt(maxInclusive - minInclusive + 1) + minInclusive;
        }
        return ThreadLocalRandom.current().nextInt(minInclusive, maxInclusive + 1);
    }

    /**
     * <p>
     * Generates a random string, containing the specified number of code points.
     * </p>
     * <p>Code points are randomly selected between the minimum and maximum values defined
     * in the generator.
     * Surrogate and private use characters are not returned, although the
     * resulting string may contain pairs of surrogates that together encode a
     * supplementary character.
     * </p>
     * <p>
     * Note: the number of {@code char} code units generated will exceed
     * {@code length} if the string contains supplementary characters. See the
     * {@link Character} documentation to understand how Java stores Unicode
     * values.
     * </p>
     *
     * @param length
     *            the number of code points to generate
     * @return the generated string
     * @throws IllegalArgumentException
     *             if {@code length < 0}
     */
    public String generate(final int length) {
        if (length == 0) {
            return "";
        }
        Validate.isTrue(length > 0, "Length %d is smaller than zero.", length);

        final StringBuilder builder = new StringBuilder(length);
        long remaining = length;

        do {
            int codePoint = generateRandomNumber(minimumCodePoint, maximumCodePoint);

            switch (Character.getType(codePoint)) {
            case Character.UNASSIGNED:
            case Character.PRIVATE_USE:
            case Character.SURROGATE:
                continue;
            default:
            }

            if (inclusivePredicates != null) {
                boolean matchedFilter = false;
                for (CharacterPredicate predicate : inclusivePredicates) {
                    if (predicate.test(codePoint)) {
                        matchedFilter = true;
                        break;
                    }
                }
                if (!matchedFilter) {
                    continue;
                }
            }

            builder.appendCodePoint(codePoint);
            remaining--;

        } while (remaining != 0);

        return builder.toString();
    }

    /**
     * <p>A builder for generating {@code RandomStringGenerator} instances.</p>
     * <p>The behaviour of a generator is controlled by properties set by this
     * builder. Each property has a default value, which can be overridden by
     * calling the methods defined in this class, prior to calling {@link #build()}.</p>
     *
     * <p>All the property setting methods return the {@code Builder} instance to allow for method chaining.</p>
     *
     * <p>The minimum and maximum code point values are defined using {@link #withinRange(int, int)}. The
     * default values are {@code 0} and {@link Character#MAX_CODE_POINT} respectively.</p>
     *
     * <p>The source of randomness can be set using {@link #usingRandom(TextRandomProvider)},
     * otherwise {@link ThreadLocalRandom} is used.</p>
     *
     * <p>The type of code points returned can be filtered using {@link #filteredBy(CharacterPredicate...)},
     * which defines a collection of tests that are applied to the randomly generated code points.
     * The code points will only be included in the result if they pass at least one of the tests.
     * Some commonly used predicates are provided by the {@link CharacterPredicates} enum.</p>
     *
     * <p>This class is not thread safe.</p>
     * @since 1.1
     */
    public static class Builder implements org.apache.commons.text.Builder<RandomStringGenerator> {

        /**
         * The default maximum code point allowed: {@link Character#MAX_CODE_POINT}
         * ({@value}).
         */
        public static final int DEFAULT_MAXIMUM_CODE_POINT = Character.MAX_CODE_POINT;

        /**
         * The default string length produced by this builder: {@value}.
         */
        public static final int DEFAULT_LENGTH = 0;

        /**
         * The default minimum code point allowed: {@value}.
         */
        public static final int DEFAULT_MINIMUM_CODE_POINT = 0;

        /**
         * The minimum code point allowed.
         */
        private int minimumCodePoint = DEFAULT_MINIMUM_CODE_POINT;

        /**
         * The maximum code point allowed.
         */
        private int maximumCodePoint = DEFAULT_MAXIMUM_CODE_POINT;

        /**
         * Filters for code points.
         */
        private Set<CharacterPredicate> inclusivePredicates;

        /**
         * The source of randomness.
         */
        private TextRandomProvider random;

        /**
         * <p>
         * Specifies the minimum and maximum code points allowed in the
         * generated string.
         * </p>
         *
         * @param minimumCodePoint
         *            the smallest code point allowed (inclusive)
         * @param maximumCodePoint
         *            the largest code point allowed (inclusive)
         * @return {@code this}, to allow method chaining
         * @throws IllegalArgumentException
         *             if {@code maximumCodePoint >}
         *             {@link Character#MAX_CODE_POINT}
         * @throws IllegalArgumentException
         *             if {@code minimumCodePoint < 0}
         * @throws IllegalArgumentException
         *             if {@code minimumCodePoint > maximumCodePoint}
         */
        public Builder withinRange(final int minimumCodePoint, final int maximumCodePoint) {
            Validate.isTrue(minimumCodePoint <= maximumCodePoint,
                    "Minimum code point %d is larger than maximum code point %d", minimumCodePoint, maximumCodePoint);
            Validate.isTrue(minimumCodePoint >= 0, "Minimum code point %d is negative", minimumCodePoint);
            Validate.isTrue(maximumCodePoint <= Character.MAX_CODE_POINT,
                    "Value %d is larger than Character.MAX_CODE_POINT.", maximumCodePoint);

            this.minimumCodePoint = minimumCodePoint;
            this.maximumCodePoint = maximumCodePoint;
            return this;
        }

        /**
         * <p>
         * Limits the characters in the generated string to those that match at
         * least one of the predicates supplied.
         * </p>
         *
         * <p>
         * Passing {@code null} or an empty array to this method will revert to the
         * default behaviour of allowing any character. Multiple calls to this
         * method will replace the previously stored predicates.
         * </p>
         *
         * @param predicates
         *            the predicates, may be {@code null} or empty
         * @return {@code this}, to allow method chaining
         */
        public Builder filteredBy(final CharacterPredicate... predicates) {
            if (predicates == null || predicates.length == 0) {
                inclusivePredicates = null;
                return this;
            }

            if (inclusivePredicates == null) {
                inclusivePredicates = new HashSet<>();
            } else {
                inclusivePredicates.clear();
            }

            for (CharacterPredicate predicate : predicates) {
                inclusivePredicates.add(predicate);
            }

            return this;
        }

        /**
         * <p>
         * Overrides the default source of randomness.  It is highly
         * recommended that a random number generator library like
         * <a href="http://commons.apache.org/proper/commons-rng/">Apache Commons RNG</a>
         * be used to provide the random number generation.
         * </p>
         *
         * <p>
         * When using Java 8 or later, {@link TextRandomProvider} is a
         * functional interface and need not be explicitly implemented:
         * </p>
         * <pre>
         * {@code
         * UniformRandomProvider rng = RandomSource.create(...);
         * RandomStringGenerator gen = new RandomStringGenerator.Builder()
         *     .usingRandom(rng::nextInt)
         *     // additional builder calls as needed
         *     .build();
         * }
         * </pre>
         *
         * <p>
         * Passing {@code null} to this method will revert to the default source of
         * randomness.
         * </p>
         *
         * @param random
         *            the source of randomness, may be {@code null}
         * @return {@code this}, to allow method chaining
         */
        public Builder usingRandom(final TextRandomProvider random) {
            this.random = random;
            return this;
        }

        /**
         * <p>Builds the {@code RandomStringGenerator} using the properties specified.</p>
         * @return the configured {@code RandomStringGenerator}
         */
        @Override
        public RandomStringGenerator build() {
            return new RandomStringGenerator(minimumCodePoint, maximumCodePoint, inclusivePredicates, random);
        }
    }
}
