/**
 *******************************************************************************
 * Copyright (C) 2001-2007, 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 idForDisplay, ULocale locale) {
            return (visible && idForDisplay.equals(this.id)) ? "(" + locale.toString() + ") " + idForDisplay : 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());
    }
}
