/**
 *******************************************************************************
 * Copyright (C) 2001-2006, 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.ICULocaleService;
import com.ibm.icu.text.Collator;
import com.ibm.icu.util.ULocale;

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.MissingResourceException;
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(new ULocale(id), id, true);
        }

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

        public String toString() {
            return "Factory_" + id;
        }
    }
    /**
     * Convenience override of getDisplayNames(ULocale, 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, ULocale locale) {
        Collator col;
        try {
            col = Collator.getInstance(locale);
        } 
        catch (MissingResourceException e) {
            // if no collator resources, we can't collate
            col = null;
        }
        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 {
        ULocale locale;

        GetDisplayThread(String name, ICUService service, long delay, ULocale 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);

                // Note: IllegalMonitorStateException is thrown by the code
                // below on IBM JRE5 for AIX 64bit.  For some reason, converting
                // int to String out of this statement resolves the issue.

                //log.logln(" iter: " + n + 
                String num = Integer.toString(n);
                log.logln(" iter: " + num + 
                          " 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,
                                 new ULocale(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,
                                 new ULocale(locale),
                                 this).start();
        }

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

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