// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html#License
/**
*******************************************************************************
* Copyright (C) 2003-2016, International Business Machines Corporation and
* others. All Rights Reserved.
*******************************************************************************
*/

package com.ibm.icu.text;

import java.util.Locale;
import java.util.MissingResourceException;
import java.util.Set;

import com.ibm.icu.impl.ICUData;
import com.ibm.icu.impl.ICULocaleService;
import com.ibm.icu.impl.ICULocaleService.LocaleKeyFactory;
import com.ibm.icu.impl.ICUResourceBundle;
import com.ibm.icu.impl.ICUService;
import com.ibm.icu.impl.ICUService.Factory;
import com.ibm.icu.impl.coll.CollationLoader;
import com.ibm.icu.impl.coll.CollationTailoring;
import com.ibm.icu.text.Collator.CollatorFactory;
import com.ibm.icu.util.ICUCloneNotSupportedException;
import com.ibm.icu.util.Output;
import com.ibm.icu.util.ULocale;

final class CollatorServiceShim extends Collator.ServiceShim {

    @Override
    Collator getInstance(ULocale locale) {
    // use service cache, it's faster than instantiation
//          if (service.isDefault()) {
//              return new RuleBasedCollator(locale);
//          }
        try {
            ULocale[] actualLoc = new ULocale[1];
            Collator coll = (Collator)service.get(locale, actualLoc);
            if (coll == null) {
                ///CLOVER:OFF
                //Can't really change coll after it's been initialized
                throw new MissingResourceException("Could not locate Collator data", "", "");
                ///CLOVER:ON
            }
            return (Collator) coll.clone();
        }
        catch (CloneNotSupportedException e) {
        ///CLOVER:OFF
            throw new ICUCloneNotSupportedException(e);
        ///CLOVER:ON
        }
    }

    @Override
    Object registerInstance(Collator collator, ULocale locale) {
        // Set the collator locales while registering so that getInstance()
        // need not guess whether the collator's locales are already set properly
        // (as they are by the data loader).
        collator.setLocale(locale, locale);
        return service.registerObject(collator, locale);
    }

    @Override
    Object registerFactory(CollatorFactory f) {
        class CFactory extends LocaleKeyFactory {
            CollatorFactory delegate;

            CFactory(CollatorFactory fctry) {
                super(fctry.visible());
                this.delegate = fctry;
            }

            @Override
            public Object handleCreate(ULocale loc, int kind, ICUService srvc) {
                Object coll = delegate.createCollator(loc);
                return coll;
            }

            @Override
            public String getDisplayName(String id, ULocale displayLocale) {
                ULocale objectLocale = new ULocale(id);
                return delegate.getDisplayName(objectLocale, displayLocale);
            }

            @Override
            public Set<String> getSupportedIDs() {
                return delegate.getSupportedLocaleIDs();
            }
        }

        return service.registerFactory(new CFactory(f));
    }

    @Override
    boolean unregister(Object registryKey) {
        return service.unregisterFactory((Factory)registryKey);
    }

    @Override
    Locale[] getAvailableLocales() {
        // TODO rewrite this to just wrap getAvailableULocales later
        Locale[] result;
        if (service.isDefault()) {
            result = ICUResourceBundle.getAvailableLocales(ICUData.ICU_COLLATION_BASE_NAME,
                    ICUResourceBundle.ICU_DATA_CLASS_LOADER);
        } else {
            result = service.getAvailableLocales();
        }
        return result;
    }

    @Override
    ULocale[] getAvailableULocales() {
        ULocale[] result;
        if (service.isDefault()) {
            result = ICUResourceBundle.getAvailableULocales(ICUData.ICU_COLLATION_BASE_NAME,
                    ICUResourceBundle.ICU_DATA_CLASS_LOADER);
        } else {
            result = service.getAvailableULocales();
        }
        return result;
    }

    @Override
    String getDisplayName(ULocale objectLocale, ULocale displayLocale) {
        String id = objectLocale.getName();
        return service.getDisplayName(id, displayLocale);
    }

    private static class CService extends ICULocaleService {
        CService() {
            super("Collator");

            class CollatorFactory extends ICUResourceBundleFactory {
                CollatorFactory() {
                    super(ICUData.ICU_COLLATION_BASE_NAME);
                }

                @Override
                protected Object handleCreate(ULocale uloc, int kind, ICUService srvc) {
                    return makeInstance(uloc);
                }
            }

            this.registerFactory(new CollatorFactory());
            markDefault();
        }

        /**
         * makeInstance() returns an appropriate Collator for any locale.
         * It falls back to root if there is no specific data.
         *
         * <p>Without this override, the service code would fall back to the default locale
         * which is not desirable for an algorithm with a good Unicode default,
         * like collation.
         */
        @Override
        public String validateFallbackLocale() {
            return "";
        }

        ///CLOVER:OFF
        // The following method can not be reached by testing
        @Override
        protected Object handleDefault(Key key, String[] actualIDReturn) {
            if (actualIDReturn != null) {
                actualIDReturn[0] = "root";
            }
            try {
                return makeInstance(ULocale.ROOT);
            }
            catch (MissingResourceException e) {
                return null;
            }
        }
        ///CLOVER:ON
    }

    // Ported from C++ Collator::makeInstance().
    private static final Collator makeInstance(ULocale desiredLocale) {
        Output<ULocale> validLocale = new Output<ULocale>(ULocale.ROOT);
        CollationTailoring t =
            CollationLoader.loadTailoring(desiredLocale, validLocale);
        return new RuleBasedCollator(t, validLocale.value);
    }

    private static ICULocaleService service = new CService();
}
