/*
 *******************************************************************************
 * Copyright (C) 1996-2004, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */
package com.ibm.icu.dev.test.rbbi;

import com.ibm.icu.dev.test.TestFmwk;
import com.ibm.icu.text.BreakIterator;
import java.text.CharacterIterator;
import java.util.Arrays;
import java.util.Locale;

public class BreakIteratorRegTest extends TestFmwk
{
    public static void main(String[] args) throws Exception {
        new BreakIteratorRegTest().run(args);
    }

    public void TestRegUnreg() {
	Locale thailand_locale = new Locale("th", "TH", "");
	Locale foo_locale = new Locale("fu", "FU", "FOO");
	BreakIterator jwbi = BreakIterator.getWordInstance(Locale.JAPAN);
	BreakIterator uwbi = BreakIterator.getWordInstance(Locale.US);
	BreakIterator usbi = BreakIterator.getSentenceInstance(Locale.US);
	BreakIterator twbi = BreakIterator.getWordInstance(thailand_locale);
	BreakIterator rwbi = BreakIterator.getWordInstance(new Locale("", "", ""));

	BreakIterator sbi = (BreakIterator)usbi.clone();
	// todo: this will cause the test to fail, no way to set a breakiterator to null text so can't fix yet.
	// String text = "This is some test, by golly. Boy, they don't make tests like they used to, do they?  This here test ain't worth $2.50.  Nope.";
	// sbi.setText(text);

	assertTrue(!BreakIterator.unregister(""), "unregister before register"); // coverage

	Object key0 = BreakIterator.registerInstance((BreakIterator)twbi.clone(), foo_locale, BreakIterator.KIND_WORD);
	Object key1 = BreakIterator.registerInstance(sbi, Locale.US, BreakIterator.KIND_WORD);
	Object key2 = BreakIterator.registerInstance((BreakIterator)twbi.clone(), Locale.US, BreakIterator.KIND_WORD);
	
	{
	    BreakIterator test0 = BreakIterator.getWordInstance(Locale.JAPAN);
	    BreakIterator test1 = BreakIterator.getWordInstance(Locale.US);
	    BreakIterator test2 = BreakIterator.getSentenceInstance(Locale.US);
	    BreakIterator test3 = BreakIterator.getWordInstance(thailand_locale);
	    BreakIterator test4 = BreakIterator.getWordInstance(foo_locale);

	    assertEqual(test0, jwbi, "japan word == japan word");
	    assertEqual(test1, twbi, "us word == thai word");
	    assertEqual(test2, usbi, "us sentence == us sentence");
	    assertEqual(test3, twbi, "thai word == thai word");
	    assertEqual(test4, twbi, "foo word == thai word");
	}

	Locale[] locales = BreakIterator.getAvailableLocales();
	
	assertTrue(BreakIterator.unregister(key2), "unregister us word (thai word)");
	assertTrue(!BreakIterator.unregister(key2), "unregister second time");
	boolean error = false;
	try {
	    BreakIterator.unregister(null);
	}
	catch (IllegalArgumentException e) {
	    error = true;
	}

	assertTrue(error, "unregister null");

	{
	    CharacterIterator sci = BreakIterator.getWordInstance(Locale.US).getText();
	    int len = sci.getEndIndex() - sci.getBeginIndex();
	    assertEqual(len, 0, "us word text: " + getString(sci));
	}

	assertTrue(Arrays.asList(BreakIterator.getAvailableLocales()).contains(foo_locale), "foo_locale");
	assertTrue(BreakIterator.unregister(key0), "unregister foo word (thai word)");
	assertTrue(!Arrays.asList(BreakIterator.getAvailableLocales()).contains(foo_locale), "no foo_locale");
	assertEqual(BreakIterator.getWordInstance(Locale.US), usbi, "us word == us sentence");
	
	assertTrue(BreakIterator.unregister(key1), "unregister us word (us sentence)");
	{
	    BreakIterator test0 = BreakIterator.getWordInstance(Locale.JAPAN);
	    BreakIterator test1 = BreakIterator.getWordInstance(Locale.US);
	    BreakIterator test2 = BreakIterator.getSentenceInstance(Locale.US);
	    BreakIterator test3 = BreakIterator.getWordInstance(thailand_locale);
	    BreakIterator test4 = BreakIterator.getWordInstance(foo_locale);

	    assertEqual(test0, jwbi, "japanese word break");
	    assertEqual(test1, uwbi, "us sentence-word break");
	    assertEqual(test2, usbi, "us sentence break");
	    assertEqual(test3, twbi, "thai word break");
	    assertEqual(test4, rwbi, "root word break");

	    CharacterIterator sci = test1.getText();
	    int len = sci.getEndIndex() - sci.getBeginIndex();
	    assertEqual(len, 0, "us sentence-word break text: " + getString(sci));
	}
    }

    private void assertEqual(Object lhs, Object rhs, String msg) {
	msg(msg, lhs.equals(rhs) ? LOG : ERR, true, true);
    }

    private void assertEqual(int lhs, int rhs, String msg) {
	msg(msg, lhs == rhs ? LOG : ERR, true, true);
    }

    private void assertTrue(boolean arg, String msg) {
	msg(msg, arg ? LOG : ERR, true, true);
    }

    private static String getString(CharacterIterator ci) {
	StringBuffer buf = new StringBuffer(ci.getEndIndex() - ci.getBeginIndex() + 2);
	buf.append("'");
	for (char c = ci.first(); c != CharacterIterator.DONE; c = ci.next()) {
	    buf.append(c);
	}
	buf.append("'");
	return buf.toString();
    }
}
