/*
 * 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
        // behavior 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);
            }
        }
    }
}
