/**
 *******************************************************************************
 * Copyright (C) 2001-2002, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 *
 * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/dev/test/util/ICUServiceThreadTest.java,v $
 * $Date: 2002/08/13 22:10:20 $
 * $Revision: 1.4 $
 *
 *******************************************************************************
 */
package com.ibm.icu.dev.test.util;

import com.ibm.icu.dev.test.TestFmwk;
import com.ibm.icu.dev.test.TestLog;
import com.ibm.icu.impl.ICUService;
import com.ibm.icu.impl.ICUService.Factory;
import com.ibm.icu.impl.ICUService.SimpleFactory;
import com.ibm.icu.impl.ICUService.Key;
import com.ibm.icu.impl.LocaleUtility;
import com.ibm.icu.impl.ICULocaleData;
import com.ibm.icu.impl.ICULocaleService;
import com.ibm.icu.impl.ICULocaleService.LocaleKey;
import com.ibm.icu.impl.ICULocaleService.MultipleKeyFactory;
import com.ibm.icu.impl.ICULocaleService.ICUResourceBundleFactory;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.TreeSet;

public class ICUServiceThreadTest extends TestFmwk
{    
    private static final boolean PRINTSTATS = false;

    public static void main(String[] args) throws Exception {
	ICUServiceThreadTest test = new ICUServiceThreadTest();
	test.run(args);

	// get
	// getvisibleids
	// getdisplayname(locale)
	// factories
	
	// registerFactory
	// unregisterFactory

	// 1) concurrent access
	// 2) access while factories change
	// 3) iteration while factories change
	// 4) concurrent conflicting access
    }

    private static final String[] countries = {
	"ab", "bc", "cd", "de", "ef", "fg", "gh", "ji", "ij", "jk"
    };
    private static final String[] languages = {
	"", "ZY", "YX", "XW", "WV", "VU", "UT", "TS", "SR", "RQ", "QP"
    };
    private static final String[] variants = {
	"", "", "", "GOLD", "SILVER", "BRONZE"
    };

    private static class TestFactory extends SimpleFactory {
	TestFactory(String id) {
	    super(LocaleUtility.getLocaleFromName(id), id, true);
	}

	public String getDisplayName(String id, Locale locale) {
	    return (visible && id.equals(this.id)) ? "(" + locale.toString() + ") " + id : null;
	}

	public String toString() {
	    return "Factory_" + id;
	}
    }

    private static final Random r = new Random();

    private static String getCLV() {
	String c = countries[r.nextInt(countries.length)];
	String l = languages[r.nextInt(languages.length)];
	String v = variants[r.nextInt(variants.length)];
	return new Locale(c, l, v).toString();
    }

    private static boolean WAIT = true;
    private static boolean GO = false;
    private static long TIME = 5000;

    public static void runThreads() {
	runThreads(TIME);
    }

    public static void runThreads(long time) {
	try {
	    GO = true;
	    WAIT = false;

	    Thread.sleep(time);

	    WAIT = true;
	    GO = false;

	    Thread.sleep(300);
	}
	catch (InterruptedException e) {
	}
    }

    static class TestThread extends Thread implements TestLog {
	private final String name;
	protected ICUService service;
	private final long delay;
	private final TestLog log;

	public TestThread(String name, ICUService service, long delay, TestLog log) {
	    this.name = name + " ";
	    this.service = service;
	    this.delay = delay;
	    this.log = log;
	    this.setDaemon(true);
	}

	public void run() {
	    while (WAIT) {
		Thread.yield();
	    }

	    try {
		while (GO) {
		    iterate();
		    if (delay > 0) {
			Thread.sleep(delay);
		    }
		}
	    }
	    catch (InterruptedException e) {
	    }
	}

	protected void iterate() {
	}

	public boolean logging() {
	    return log != null;
	}

	public void log(String msg) {
	    if (logging()) {
		log.log(name + msg);
	    }
	}

	public void logln(String msg) {
	    if (logging()) {
		log.logln(name + msg);
	    }
	}

	public void err(String msg) {
	    if (logging()) {
		log.err(name + msg);
	    }
	}

	public void errln(String msg) {
	    if (logging()) {
		log.errln(name + msg);
	    }
	}
    }

    static class RegisterFactoryThread extends TestThread {
	RegisterFactoryThread(String name, ICUService service, long delay, TestLog log) {
	    super("REG " + name, service, delay, log);
	}

	protected void iterate() {
	    Factory f = new TestFactory(getCLV());
	    service.registerFactory(f);
	    logln(f.toString());
	}
    }

    static class UnregisterFactoryThread extends TestThread {
	private Random r;
	List factories;

	UnregisterFactoryThread(String name, ICUService service, long delay, TestLog log) {
	    super("UNREG " + name, service, delay, log);
	    
	    r = new Random();
	    factories = service.factories();
	}

	public void iterate() {
	    int s = factories.size();
	    if (s == 0) {
		factories = service.factories();
	    } else {
		int n = r.nextInt(s);
		Factory f = (Factory)factories.remove(n);
		boolean success = service.unregisterFactory(f);
		if (logging()) logln("factory: " + f + (success ? " succeeded." : " *** failed."));
	    }
	}
    }

    static class UnregisterFactoryListThread extends TestThread {
	Factory[] factories;
	int n;

	UnregisterFactoryListThread(String name, ICUService service, long delay, Factory[] factories, TestLog log) {
	    super("UNREG " + name, service, delay, log);
	    
	    this.factories = factories;
	}

	public void iterate() {
	    if (n < factories.length) {
		Factory f = factories[n++];
		boolean success = service.unregisterFactory(f);
		if (logging()) logln("factory: " + f + (success ? " succeeded." : " *** failed."));
	    }
	}
    }


    static class GetVisibleThread extends TestThread {
	GetVisibleThread(String name, ICUService service, long delay, TestLog log) {
	    super("VIS " + name, service, delay, log);
	}

	protected void iterate() {
	    Set ids = service.getVisibleIDs();
	    Iterator iter = ids.iterator();
	    int n = 10;
	    while (--n >= 0 && iter.hasNext()) {
		String id = (String)iter.next();
		Object result = service.get(id);
		logln("iter: " + n + " id: " + id + " result: " + result);
	    }
	}
    }

    static class GetDisplayThread extends TestThread {
	Locale locale;

	GetDisplayThread(String name, ICUService service, long delay, Locale locale, TestLog log) {
	    super("DIS " + name, service, delay, log);

	    this.locale = locale;
	}

	protected void iterate() {
	    Map names = service.getDisplayNames(locale);
	    Iterator iter = names.entrySet().iterator();
	    int n = 10;
	    while (--n >= 0 && iter.hasNext()) {
		Entry e = (Entry)iter.next();
		String dname = (String)e.getKey();
		String id = (String)e.getValue();
		Object result = service.get(id);
		if (logging()) logln(" iter: " + n + 
				     " dname: " + dname + 
				     " id: " + id + 
				     " result: " + result);
	    }
	}
    }

    static class GetThread extends TestThread {
	private String[] actualID;

	GetThread(String name, ICUService service, long delay, TestLog log) {
	    super("GET " + name, service, delay, log);

	    actualID = new String[1];
	}

	protected void iterate() {
	    String id = getCLV();
	    Object o = service.get(id, actualID);
	    if (logging() && o != null) {
		logln(" id: " + id + " actual: " + actualID[0] + " result: " + o);
	    }
	}
    }

    static class GetListThread extends TestThread {
	private final String[] list;
	private int n;

	GetListThread(String name, ICUService service, long delay, String[] list, TestLog log) {
	    super("GETL " + name, service, delay, log);

	    this.list = list;
	}

	protected void iterate() {
	    if (--n < 0) {
		n = list.length - 1;
	    }
	    String id = list[n];
	    Object o = service.get(id);
	    if (logging()) {
		logln(" id: " + id + " result: " + o);
	    }
	}
    }

    // return a collection of unique factories, might be fewer than requested
    Collection getFactoryCollection(int requested) {
	Set locales = new HashSet();
	for (int i = 0; i < requested; ++i) {
	    locales.add(getCLV());
	}
	List factories = new ArrayList(locales.size());
	Iterator iter = locales.iterator();
	while (iter.hasNext()) {
	    factories.add(new TestFactory((String)iter.next()));
	}
	return factories;
    }

    void registerFactories(ICUService service, Collection c) {
	Iterator iter = c.iterator();
	while (iter.hasNext()) {
	    service.registerFactory((Factory)iter.next());
	}
    }

    ICUService stableService() {
	if (stableService == null) {
	    stableService = new ICULocaleService();
	    registerFactories(stableService, getFactoryCollection(50));
	}
	return stableService;
    }
    private ICUService stableService;

    // run multiple get on a stable service
    public void Test00_ConcurrentGet() {
	for(int i = 0; i < 10; ++i) {
	    new GetThread("[" + Integer.toString(i) + "]",  stableService(), 0, this).start();
	}
	runThreads();
	if (PRINTSTATS) System.out.println(stableService.stats());
    }

    // run multiple getVisibleID on a stable service
    public void Test01_ConcurrentGetVisible() {
	for(int i = 0; i < 10; ++i) {
	    new GetVisibleThread("[" + Integer.toString(i) + "]",  stableService(), 0, this).start();
	}
	runThreads();
	if (PRINTSTATS) System.out.println(stableService.stats());
    }

    // run multiple getDisplayName on a stable service
    public void Test02_ConcurrentGetDisplay() {
	String[] localeNames = {
	    "en", "es", "de", "fr", "zh", "it", "no", "sv"
	};
	for(int i = 0; i < localeNames.length; ++i) {
	    String locale = localeNames[i];
	    new GetDisplayThread("[" + locale + "]",  
				 stableService(), 
				 0,
				 LocaleUtility.getLocaleFromName(locale),
				 this).start();
	}
	runThreads();
	if (PRINTSTATS) System.out.println(stableService.stats());
    }

    // run register/unregister on a service
    public void Test03_ConcurrentRegUnreg() {
	ICUService service = new ICULocaleService();
	for (int i = 0; i < 5; ++i) {
	    new RegisterFactoryThread("[" + i + "]", service, 0, this).start();
	}
	for (int i = 0; i < 5; ++i) {
	    new UnregisterFactoryThread("[" + i + "]", service, 0, this).start();
	}
	runThreads();
	if (PRINTSTATS) System.out.println(service.stats());
    }
    
    public void Test04_WitheringService() {
	ICUService service = new ICULocaleService();

	Collection fc = getFactoryCollection(50);
	registerFactories(service, fc);

	Factory[] factories = (Factory[])fc.toArray(new Factory[fc.size()]);
	Comparator comp = new Comparator() {
		public int compare(Object lhs, Object rhs) {
		    return lhs.toString().compareTo(rhs.toString());
		}
	    };
	Arrays.sort(factories, comp);

	new GetThread("", service, 0, this).start();
	new UnregisterFactoryListThread("", service, 3, factories, this).start();

	runThreads(2000);
	if (PRINTSTATS) System.out.println(service.stats());
    }
	
    // "all hell breaks loose"
    // one register and one unregister thread, delay 500ms
    // two display threads with different locales, delay 500ms;
    // one visible id thread, delay 50ms
    // fifteen get threads, delay 0
    // run for ten seconds
    public void Test05_ConcurrentEverything() {
	ICUService service = new ICULocaleService();

	new RegisterFactoryThread("", service, 500, this).start();

	for(int i = 0; i < 15; ++i) {
	    new GetThread("[" + Integer.toString(i) + "]", service, 0, this).start();
	}

	new GetVisibleThread("",  service, 50, this).start();

	String[] localeNames = {
	    "en", "de"
	};
	for(int i = 0; i < localeNames.length; ++i) {
	    String locale = localeNames[i];
	    new GetDisplayThread("[" + locale + "]",  
				 stableService(), 
				 500,
				 LocaleUtility.getLocaleFromName(locale),
				 this).start();
	}

	new UnregisterFactoryThread("", service, 500, this).start();

	// yoweee!!!
	runThreads(10000);
	if (PRINTSTATS) System.out.println(service.stats());
    }
}
