/**
 *******************************************************************************
 * Copyright (C) 2001-2004, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */
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());
    }
}
