/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.commons.beanutils2.locale;

import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collection;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import org.apache.commons.beanutils2.BeanUtils;
import org.apache.commons.beanutils2.WeakFastHashMap;
import org.apache.commons.beanutils2.locale.converters.BigDecimalLocaleConverter;
import org.apache.commons.beanutils2.locale.converters.BigIntegerLocaleConverter;
import org.apache.commons.beanutils2.locale.converters.ByteLocaleConverter;
import org.apache.commons.beanutils2.locale.converters.DoubleLocaleConverter;
import org.apache.commons.beanutils2.locale.converters.FloatLocaleConverter;
import org.apache.commons.beanutils2.locale.converters.IntegerLocaleConverter;
import org.apache.commons.beanutils2.locale.converters.LongLocaleConverter;
import org.apache.commons.beanutils2.locale.converters.ShortLocaleConverter;
import org.apache.commons.beanutils2.locale.converters.SqlDateLocaleConverter;
import org.apache.commons.beanutils2.locale.converters.SqlTimeLocaleConverter;
import org.apache.commons.beanutils2.locale.converters.SqlTimestampLocaleConverter;
import org.apache.commons.beanutils2.locale.converters.StringLocaleConverter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * <p>Utility methods for converting locale-sensitive String scalar values to objects of the
 * specified Class, String arrays to arrays of the specified Class and
 * object to locale-sensitive String scalar value.</p>
 *
 * <p>This class provides the implementations used by the static utility methods in
 * {@link LocaleConvertUtils}.</p>
 *
 * <p>The actual {@link LocaleConverter} instance to be used
 * can be registered for each possible destination Class. Unless you override them, standard
 * {@link LocaleConverter} instances are provided for all of the following
 * destination Classes:</p>
 * <ul>
 * <li>java.lang.BigDecimal</li>
 * <li>java.lang.BigInteger</li>
 * <li>byte and java.lang.Byte</li>
 * <li>double and java.lang.Double</li>
 * <li>float and java.lang.Float</li>
 * <li>int and java.lang.Integer</li>
 * <li>long and java.lang.Long</li>
 * <li>short and java.lang.Short</li>
 * <li>java.lang.String</li>
 * <li>java.sql.Date</li>
 * <li>java.sql.Time</li>
 * <li>java.sql.Timestamp</li>
 * </ul>
 *
 * <p>For backwards compatibility, the standard locale converters
 * for primitive types (and the corresponding wrapper classes).
 *
 * If you prefer to have another {@link LocaleConverter}
 * thrown instead, replace the standard {@link LocaleConverter} instances
 * with ones created with the one of the appropriate constructors.
 *
 * It's important that {@link LocaleConverter} should be registered for
 * the specified locale and Class (or primitive type).
 *
 * @since 1.7
 */
public class LocaleConvertUtilsBean {

    /**
     * Gets singleton instance.
     * This is the same as the instance used by the default {@link LocaleBeanUtilsBean} singleton.
     * @return the singleton instance
     */
    public static LocaleConvertUtilsBean getInstance() {
        return LocaleBeanUtilsBean.getLocaleBeanUtilsInstance().getLocaleConvertUtils();
    }

    

    /** The locale - default for conversion. */
    private Locale defaultLocale = Locale.getDefault();

    /** Indicate whether the pattern is localized or not */
    private boolean applyLocalized = false;

    /** The {@code Log} instance for this class. */
    private final Log log = LogFactory.getLog(LocaleConvertUtilsBean.class);

    /** Every entry of the mapConverters is:
     *  key = locale
     *  value = map of converters for the certain locale.
     */
    private final DelegateFastHashMap mapConverters = new DelegateFastHashMap(BeanUtils.createCache());

    

    /**
     *  Makes the state by default (deregisters all converters for all locales)
     *  and then registers default locale converters.
     */
    public LocaleConvertUtilsBean() {
        mapConverters.setFast(false);
        deregister();
        mapConverters.setFast(true);
    }

    

    /**
     * getter for defaultLocale.
     * @return the default locale
     */
    public Locale getDefaultLocale() {

        return defaultLocale;
    }

    /**
     * setter for defaultLocale.
     * @param locale the default locale
     */
    public void setDefaultLocale(final Locale locale) {

        if (locale == null) {
            defaultLocale = Locale.getDefault();
        }
        else {
            defaultLocale = locale;
        }
    }

    /**
     * getter for applyLocalized
     *
     * @return {@code true} if pattern is localized,
     * otherwise {@code false}
     */
    public boolean getApplyLocalized() {
        return applyLocalized;
    }

    /**
     * setter for applyLocalized
     *
     * @param newApplyLocalized {@code true} if pattern is localized,
     * otherwise {@code false}
     */
    public void setApplyLocalized(final boolean newApplyLocalized) {
        applyLocalized = newApplyLocalized;
    }

    

    /**
     * Convert the specified locale-sensitive value into a String.
     *
     * @param value The Value to be converted
     * @return the converted value
     *
     * @throws org.apache.commons.beanutils2.ConversionException if thrown by an
     * underlying Converter
     */
    public String convert(final Object value) {
        return convert(value, defaultLocale, null);
    }

    /**
     * Convert the specified locale-sensitive value into a String
     * using the conversion pattern.
     *
     * @param value The Value to be converted
     * @param pattern       The conversion pattern
     * @return the converted value
     *
     * @throws org.apache.commons.beanutils2.ConversionException if thrown by an
     * underlying Converter
     */
    public String convert(final Object value, final String pattern) {
        return convert(value, defaultLocale, pattern);
    }

    /**
     * Convert the specified locale-sensitive value into a String
     * using the particular conversion pattern.
     *
     * @param value The Value to be converted
     * @param locale The locale
     * @param pattern The conversion pattern
     * @return the converted value
     *
     * @throws org.apache.commons.beanutils2.ConversionException if thrown by an
     * underlying Converter
     */
    public String convert(final Object value, final Locale locale, final String pattern) {

        final LocaleConverter converter = lookup(String.class, locale);

        return converter.convert(String.class, value, pattern);
    }

    /**
     * Convert the specified value to an object of the specified class (if
     * possible).  Otherwise, return a String representation of the value.
     *
     * @param value The String scalar value to be converted
     * @param clazz The Data type to which this value should be converted.
     * @return the converted value
     *
     * @throws org.apache.commons.beanutils2.ConversionException if thrown by an
     * underlying Converter
     */
    public Object convert(final String value, final Class<?> clazz) {

        return convert(value, clazz, defaultLocale, null);
    }

    /**
     * Convert the specified value to an object of the specified class (if
     * possible) using the conversion pattern. Otherwise, return a String
     * representation of the value.
     *
     * @param value The String scalar value to be converted
     * @param clazz The Data type to which this value should be converted.
     * @param pattern The conversion pattern
     * @return the converted value
     *
     * @throws org.apache.commons.beanutils2.ConversionException if thrown by an
     * underlying Converter
     */
    public Object convert(final String value, final Class<?> clazz, final String pattern) {

        return convert(value, clazz, defaultLocale, pattern);
    }

    /**
     * Convert the specified value to an object of the specified class (if
     * possible) using the conversion pattern. Otherwise, return a String
     * representation of the value.
     *
     * @param value The String scalar value to be converted
     * @param clazz The Data type to which this value should be converted.
     * @param locale The locale
     * @param pattern The conversion pattern
     * @return the converted value
     *
     * @throws org.apache.commons.beanutils2.ConversionException if thrown by an
     * underlying Converter
     */
    public Object convert(final String value, final Class<?> clazz, final Locale locale, final String pattern) {

        if (log.isDebugEnabled()) {
            log.debug("Convert string " + value + " to class " +
                    clazz.getName() + " using " + locale +
                    " locale and " + pattern + " pattern");
        }

        Class<?> targetClass = clazz;
        LocaleConverter converter = lookup(clazz, locale);

        if (converter == null) {
            converter = lookup(String.class, locale);
            targetClass = String.class;
        }
        if (log.isTraceEnabled()) {
            log.trace("  Using converter " + converter);
        }

        return converter.convert(targetClass, value, pattern);
    }

    /**
     * Convert an array of specified values to an array of objects of the
     * specified class (if possible) using the conversion pattern.
     *
     * @param values Value to be converted (may be null)
     * @param clazz Java array or element class to be converted to
     * @param pattern The conversion pattern
     * @return the converted value
     *
     * @throws org.apache.commons.beanutils2.ConversionException if thrown by an
     * underlying Converter
     */
    public Object convert(final String[] values, final Class<?> clazz, final String pattern) {

        return convert(values, clazz, getDefaultLocale(), pattern);
    }

   /**
    * Convert an array of specified values to an array of objects of the
    * specified class (if possible) .
    *
    * @param values Value to be converted (may be null)
    * @param clazz Java array or element class to be converted to
    * @return the converted value
    *
     * @throws org.apache.commons.beanutils2.ConversionException if thrown by an
     * underlying Converter
    */
   public Object convert(final String[] values, final Class<?> clazz) {

       return convert(values, clazz, getDefaultLocale(), null);
   }

    /**
     * Convert an array of specified values to an array of objects of the
     * specified class (if possible) using the conversion pattern.
     *
     * @param values Value to be converted (may be null)
     * @param clazz Java array or element class to be converted to
     * @param locale The locale
     * @param pattern The conversion pattern
     * @return the converted value
     *
     * @throws org.apache.commons.beanutils2.ConversionException if thrown by an
     * underlying Converter
     */
    public Object convert(final String[] values, final Class<?> clazz, final Locale locale, final String pattern) {

        Class<?> type = clazz;
        if (clazz.isArray()) {
            type = clazz.getComponentType();
        }
        if (log.isDebugEnabled()) {
            log.debug("Convert String[" + values.length + "] to class " +
                    type.getName() + "[] using " + locale +
                    " locale and " + pattern + " pattern");
        }

        final Object array = Array.newInstance(type, values.length);
        for (int i = 0; i < values.length; i++) {
            Array.set(array, i, convert(values[i], type, locale, pattern));
        }

        return array;
    }

    /**
     * Register a custom {@link LocaleConverter} for the specified destination
     * {@code Class}, replacing any previously registered converter.
     *
     * @param converter The LocaleConverter to be registered
     * @param clazz The Destination class for conversions performed by this
     *  Converter
     * @param locale The locale
     */
    public void register(final LocaleConverter converter, final Class<?> clazz, final Locale locale) {

        lookup(locale).put(clazz, converter);
    }

    /**
     * Remove any registered {@link LocaleConverter}.
     */
    public void deregister() {

        final Map<Class<?>, LocaleConverter> defaultConverter = lookup(defaultLocale);

        mapConverters.setFast(false);

        mapConverters.clear();
        mapConverters.put(defaultLocale, defaultConverter);

        mapConverters.setFast(true);
    }

    /**
     * Remove any registered {@link LocaleConverter} for the specified locale
     *
     * @param locale The locale
     */
    public void deregister(final Locale locale) {

        mapConverters.remove(locale);
    }

    /**
     * Remove any registered {@link LocaleConverter} for the specified locale and Class.
     *
     * @param clazz Class for which to remove a registered Converter
     * @param locale The locale
     */
    public void deregister(final Class<?> clazz, final Locale locale) {

        lookup(locale).remove(clazz);
    }

    /**
     * Look up and return any registered {@link LocaleConverter} for the specified
     * destination class and locale; if there is no registered Converter, return
     * {@code null}.
     *
     * @param clazz Class for which to return a registered Converter
     * @param locale The Locale
     * @return The registered locale Converter, if any
     */
    public LocaleConverter lookup(final Class<?> clazz, final Locale locale) {

        final LocaleConverter converter = lookup(locale).get(clazz);

        if (log.isTraceEnabled()) {
            log.trace("LocaleConverter:" + converter);
        }

        return converter;
    }

    /**
     * Look up and return any registered map instance for the specified locale;
     * if there is no registered one, return {@code null}.
     *
     * @param locale The Locale
     * @return The map instance contains the all {@link LocaleConverter} types for
     *  the specified locale.
     */
    protected Map<Class<?>, LocaleConverter> lookup(final Locale locale) {
        Map<Class<?>, LocaleConverter> localeConverters;

        if (locale == null) {
            localeConverters = (Map<Class<?>, LocaleConverter>) mapConverters.get(defaultLocale);
        }
        else {
            localeConverters = (Map<Class<?>, LocaleConverter>) mapConverters.get(locale);

            if (localeConverters == null) {
                localeConverters = create(locale);
                mapConverters.put(locale, localeConverters);
            }
        }

        return localeConverters;
    }

    /**
     *  Create all {@link LocaleConverter} types for specified locale.
     *
     * @param locale The Locale
     * @return The map instance contains the all {@link LocaleConverter} types
     *  for the specified locale.
     */
    protected Map<Class<?>, LocaleConverter> create(final Locale locale) {

        final DelegateFastHashMap converter = new DelegateFastHashMap(BeanUtils.createCache());
        converter.setFast(false);

        converter.put(BigDecimal.class, new BigDecimalLocaleConverter(locale, applyLocalized));
        converter.put(BigInteger.class, new BigIntegerLocaleConverter(locale, applyLocalized));

        converter.put(Byte.class, new ByteLocaleConverter(locale, applyLocalized));
        converter.put(Byte.TYPE, new ByteLocaleConverter(locale, applyLocalized));

        converter.put(Double.class, new DoubleLocaleConverter(locale, applyLocalized));
        converter.put(Double.TYPE, new DoubleLocaleConverter(locale, applyLocalized));

        converter.put(Float.class, new FloatLocaleConverter(locale, applyLocalized));
        converter.put(Float.TYPE, new FloatLocaleConverter(locale, applyLocalized));

        converter.put(Integer.class, new IntegerLocaleConverter(locale, applyLocalized));
        converter.put(Integer.TYPE, new IntegerLocaleConverter(locale, applyLocalized));

        converter.put(Long.class, new LongLocaleConverter(locale, applyLocalized));
        converter.put(Long.TYPE, new LongLocaleConverter(locale, applyLocalized));

        converter.put(Short.class, new ShortLocaleConverter(locale, applyLocalized));
        converter.put(Short.TYPE, new ShortLocaleConverter(locale, applyLocalized));

        converter.put(String.class, new StringLocaleConverter(locale, applyLocalized));

        // conversion format patterns of java.sql.* types should correspond to default
        // behaviour of toString and valueOf methods of these classes
        converter.put(java.sql.Date.class, new SqlDateLocaleConverter(locale, "yyyy-MM-dd"));
        converter.put(java.sql.Time.class, new SqlTimeLocaleConverter(locale, "HH:mm:ss"));
        converter.put( java.sql.Timestamp.class,
                       new SqlTimestampLocaleConverter(locale, "yyyy-MM-dd HH:mm:ss.S")
                     );

        converter.setFast(true);

        return converter;
    }

    private static class DelegateFastHashMap implements Map {

        private final Map<Object, Object> map;

        private DelegateFastHashMap(final Map<Object, Object> map) {
            this.map = map;
        }
        @Override
        public void clear() {
            map.clear();
        }
        @Override
        public boolean containsKey(final Object key) {
            return map.containsKey(key);
        }
        @Override
        public boolean containsValue(final Object value) {
            return map.containsValue(value);
        }
        @Override
        public Set<Map.Entry<Object, Object>> entrySet() {
            return map.entrySet();
        }
        @Override
        public boolean equals(final Object o) {
            return map.equals(o);
        }
        @Override
        public Object get(final Object key) {
            return map.get(key);
        }
        @Override
        public int hashCode() {
            return map.hashCode();
        }
        @Override
        public boolean isEmpty() {
            return map.isEmpty();
        }
        @Override
        public Set<Object> keySet() {
            return map.keySet();
        }
        @Override
        public Object put(final Object key, final Object value) {
            return map.put(key, value);
        }
        // we operate on very generic types (<Object, Object>), so there is
        // no need for doing type checks
        @Override
        public void putAll(final Map m) {
            map.putAll(m);
        }
        @Override
        public Object remove(final Object key) {
            return map.remove(key);
        }
        @Override
        public int size() {
            return map.size();
        }
        @Override
        public Collection<Object> values() {
            return map.values();
        }
        public void setFast(final boolean fast) {
            if (map instanceof WeakFastHashMap) {
                ((WeakFastHashMap<?, ?>)map).setFast(fast);
            }
        }
    }
}
