// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
 *******************************************************************************
 * Copyright (C) 2002-2014, International Business Machines Corporation and         *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */

package com.ibm.icu.dev.test.collator;

import java.util.Locale;
import java.util.Random;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

import com.ibm.icu.dev.test.TestFmwk;
import com.ibm.icu.text.CollationKey;
import com.ibm.icu.text.Collator;
import com.ibm.icu.text.RuleBasedCollator;


/**
 *
 * CollationCreationMethodTest checks to ensure that the collators act the same whether they are created by choosing a
 * locale and loading the data from file, or by using rules.
 *
 * @author Brian Rower - IBM - August 2008
 *
 */
@RunWith(JUnit4.class)
public class CollationCreationMethodTest extends TestFmwk
{
    @Test
    public void TestRuleVsLocaleCreationMonkey()
    {
        //create a RBC from a collator reader by reading in a locale collation file
        //also create one simply from a rules string (which should be
        //pulled from the locale collation file)
        //and then do crazy monkey testing on it to make sure they are the same.
        int x,y,z;
        Random r = createRandom();
        String randString1;
        CollationKey key1;
        CollationKey key2;


        Locale[] locales = Collator.getAvailableLocales();

        RuleBasedCollator localeCollator;
        RuleBasedCollator ruleCollator;

        for(z = 0; z < 60; z++)
        {
            x = r.nextInt(locales.length);
            Locale locale = locales[x];

            try
            {
                //this is making the assumption that the only type of collator that will be made is RBC
                localeCollator = (RuleBasedCollator)Collator.getInstance(locale);
                logln("Rules for " + locale + " are: " + localeCollator.getRules());
                ruleCollator = new RuleBasedCollator(localeCollator.getRules());
            }
            catch (Exception e)
            {
                warnln("ERROR: in creation of collator of locale " + locale.getDisplayName() + ": " + e);
                return;
            }

            //do it several times for each collator
            int n = 3;
            for(y = 0; y < n; y++)
            {

                randString1 = generateNewString(r);

                key1 = localeCollator.getCollationKey(randString1);
                key2 = ruleCollator.getCollationKey(randString1);

                report(locale.getDisplayName(), randString1, key1, key2);
            }
        }
    }

    private String generateNewString(Random r)
    {
        int maxCodePoints = 40;
        byte[] c = new byte[r.nextInt(maxCodePoints)*2]; //two bytes for each code point
        int x;
        int z;
        String s = "";

        for(x = 0; x < c.length/2; x = x + 2) //once around for each UTF-16 character
        {
            z = r.nextInt(0x7fff); //the code point...

            c[x + 1] = (byte)z;
            c[x] = (byte)(z >>> 4);
        }
        try
        {
            s = new String(c, "UTF-16BE");
        }
        catch(Exception e)
        {
            warnln("Error creating random strings");
        }
        return s;
    }

    private void report(String localeName, String string1, CollationKey k1, CollationKey k2)
    {
        if (!k1.equals(k2))
        {
            StringBuilder msg = new StringBuilder();
            msg.append("With ").append(localeName).append(" collator\n and input string: ").append(string1).append('\n');
            msg.append(" failed to produce identical keys on both collators\n");
            msg.append("  localeCollator key: ").append(CollationTest.prettify(k1)).append('\n');
            msg.append("  ruleCollator   key: ").append(CollationTest.prettify(k2)).append('\n');
            errln(msg.toString());
        }
    }
}
