/**
 *******************************************************************************
 * Copyright (C) 2001-2003, 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: 2003/06/03 18:49:31 $
 * $Revision: 1.10 $
 *
 *******************************************************************************
 */
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.LocaleUtility;
import com.ibm.icu.impl.ICULocaleService;
import com.ibm.icu.text.Collator;

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.Set;
import java.util.SortedMap;

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;
	}
    }
    /**
     * Convenience override of getDisplayNames(Locale, Comparator, String) that
     * uses the default collator for the locale as the comparator to
     * sort the display names, and null for the matchID.
     */
    public static SortedMap getDisplayNames(ICUService service, Locale locale) {
        Collator col = Collator.getInstance(locale);
        return service.getDisplayNames(locale, col, null);
    }
    private static final Random r = new Random(); // this is a multi thread test, can't 'unrandomize' 

    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 {
	private final String name;
	protected ICUService service;
	private final long delay;
	protected final TestLog log;

	public TestThread(String name, ICUService service, long delay, TestLog log) {
	    this.name = name + " ";
	    this.service = service;
	    this.delay = delay;
	    this.log = new DelegatingLog(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);
	    }
	}

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

	public void warnln(String msg) {
	    if (logging()) {
		log.infoln(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);
	    log.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);
		log.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);
		log.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);
		log.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 = getDisplayNames(service,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);
		log.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 (o != null) {
		log.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);
            log.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());
    }
}
