// Copyright 2007, 2013 The Apache Software Foundation
//
// Licensed 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.tapestry5.test;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * Provides access to random data that can be used when populating a test database with "reasonable" data. The majority
 * of this is access to random words from an american english dictionary, which can be strung together to form names,
 * sentences and paragraphs.
 */
public final class RandomDataSource
{
    private static final Logger LOGGER = LoggerFactory.getLogger(RandomDataSource.class);

    private final Random random = new Random(System.currentTimeMillis());

    private final static List<String> words = new ArrayList<String>();

    private static void loadWords()
    {
        if (words.isEmpty())
        {

            for (int i = 0; i < 4; i++)
                readWords("english." + i);

            for (int i = 0; i < 3; i++)
                readWords("american." + i);

            LOGGER.info(String.format("Dictionary contains %,d words.", words.size()));
        }
    }

    private static void readWords(String name)
    {
        LOGGER.info("Reading {} ...", name);

        int count = 0;

        InputStream is = RandomDataSource.class.getResourceAsStream(name);

        if (is == null) throw new RuntimeException(String.format("File '%s' not found.", name));

        try
        {
            BufferedInputStream bis = new BufferedInputStream(is);
            InputStreamReader isr = new InputStreamReader(bis);
            LineNumberReader r = new LineNumberReader(isr);

            while (true)
            {
                String word = r.readLine();

                if (word == null) break;

                count++;
                words.add(word);
            }

            r.close();
        } catch (IOException ex)
        {
            throw new RuntimeException(String.format("Error reading '%s': %s", name + ex.getMessage()), ex);
        }

        LOGGER.info(String.format("... %,d words", count));
    }

    public boolean maybe(int percent)
    {
        assert percent > 0 && percent <= 100;

        return random.nextInt(100) < percent;
    }

    public int random(int min, int max)
    {
        assert min <= max;

        return random.nextInt(max - min + 1) + min;
    }

    /**
     * Returns a random word frm the dictionary. These words are usually all lowercase.
     */
    public String word()
    {
        loadWords();

        int index = random.nextInt(words.size());

        return words.get(index);
    }

    /**
     * Returns a random word, capitalized. Useful when create random names.
     */
    public String capitalizedWord()
    {
        String word = word();

        char[] chars = word.toCharArray();

        chars[0] = Character.toUpperCase(chars[0]);

        return new String(chars);
    }

    /**
     * Returns a word that is "safe" for use in an email address.
     */
    public String safeWord()
    {
        String word = word();

        int x = word.indexOf('\'');

        return x < 0 ? word : word.substring(0, x);
    }

    /**
     * Returns a random value from the list of values supplied.
     */
    public <T> T oneOf(T... values)
    {
        assert values.length > 0;

        int index = random.nextInt(values.length);

        return values[index];
    }

    /**
     * Returns a random enum value, given the enum type.
     */
    public <T extends Enum> T oneOf(Class<T> enumClass)
    {
        return oneOf(enumClass.getEnumConstants());
    }

    /**
     * Creates a space-separated list of random words. If in sentence form, then the first word is capitalized, and a
     * period is appended.
     *
     * @param minWords
     *         minimun number of words in the list
     * @param maxWords
     *         maximum number of words in the list
     * @param asSentence
     *         if true, the output is "dressed up" as a non-sensical sentence
     * @return the word list / sentence
     */
    public String wordList(int minWords, int maxWords, boolean asSentence)
    {
        assert minWords <= maxWords;
        assert minWords > 0;

        StringBuilder builder = new StringBuilder();

        int count = random(minWords, maxWords);

        for (int i = 0; i < count; i++)
        {

            if (i > 0) builder.append(' ');

            if (i == 0 && asSentence)
                builder.append(capitalizedWord());
            else
                builder.append(word());
        }

        if (asSentence) builder.append('.');

        return builder.toString();
    }

    /**
     * Strings together a random number of word lists (in sentence form) to create something that looks like a
     * paragraph.
     *
     * @param minSentences
     *         per paragraph
     * @param maxSentences
     *         per paragraph
     * @param minWords
     *         per sentence
     * @param maxWords
     *         per sentence
     * @return the random paragraph
     */
    public String paragraph(int minSentences, int maxSentences, int minWords, int maxWords)
    {
        assert minSentences < maxSentences;
        assert minSentences > 0;

        int count = random(minSentences, maxSentences);

        StringBuilder builder = new StringBuilder();

        for (int i = 0; i < count; i++)
        {
            if (i > 0) builder.append(' ');

            builder.append(wordList(minWords, maxWords, true));
        }

        return builder.toString();
    }
}
