/*
 * 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.converters;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.text.ParsePosition;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

import org.apache.commons.beanutils2.ConversionException;

/**
 * {@link org.apache.commons.beanutils2.Converter} implementation that handles conversion
 * to and from <b>java.lang.Number</b> objects.
 * <p>
 * This implementation handles conversion for the following
 * {@code java.lang.Number} types.
 * <ul>
 *     <li>{@code java.lang.Byte}</li>
 *     <li>{@code java.lang.Short}</li>
 *     <li>{@code java.lang.Integer}</li>
 *     <li>{@code java.lang.Long}</li>
 *     <li>{@code java.lang.Float}</li>
 *     <li>{@code java.lang.Double}</li>
 *     <li>{@code java.math.BigDecimal}</li>
 *     <li>{@code java.math.BigInteger}</li>
 * </ul>
 *
 * <h3>String Conversions (to and from)</h3>
 * This class provides a number of ways in which number
 * conversions to/from Strings can be achieved:
 * <ul>
 *    <li>Using the default format for the default Locale, configure using:
 *        <ul>
 *          <li>{@code setUseLocaleFormat(true)}</li>
 *        </ul>
 *    </li>
 *    <li>Using the default format for a specified Locale, configure using:
 *        <ul>
 *          <li>{@code setLocale(Locale)}</li>
 *        </ul>
 *    </li>
 *    <li>Using a specified pattern for the default Locale, configure using:
 *        <ul>
 *          <li>{@code setPattern(String)}</li>
 *        </ul>
 *    </li>
 *    <li>Using a specified pattern for a specified Locale, configure using:
 *        <ul>
 *          <li>{@code setPattern(String)}</li>
 *          <li>{@code setLocale(Locale)}</li>
 *        </ul>
 *    </li>
 *    <li>If none of the above are configured the
 *        {@code toNumber(String)} method is used to convert
 *        from String to Number and the Number's
 *        {@code toString()} method used to convert from
 *        Number to String.</li>
 * </ul>
 *
 * <p>
 * <strong>N.B.</strong>Patterns can only be specified using the <i>standard</i>
 * pattern characters and NOT in <i>localized</i> form (see {@code java.text.DecimalFormat}).
 * For example to cater for number styles used in Germany such as {@code 0.000,00} the pattern
 * is specified in the normal form {@code 0,000.00</code> and the locale set to <code>Locale.GERMANY}.
 *
 * @since 1.8.0
 */
public abstract class NumberConverter extends AbstractConverter {

    private static final Integer ZERO = Integer.valueOf(0);
    private static final Integer ONE  = Integer.valueOf(1);

    private String pattern;
    private final boolean allowDecimals;
    private boolean useLocaleFormat;
    private Locale locale;

    

    /**
     * Construct a <b>java.lang.Number</b> <i>Converter</i>
     * that throws a {@code ConversionException} if a error occurs.
     *
     * @param allowDecimals Indicates whether decimals are allowed
     */
    public NumberConverter(final boolean allowDecimals) {
        super();
        this.allowDecimals = allowDecimals;
    }

    /**
     * Construct a {@code java.lang.Number} <i>Converter</i> that returns
     * a default value if an error occurs.
     *
     * @param allowDecimals Indicates whether decimals are allowed
     * @param defaultValue The default value to be returned
     */
    public NumberConverter(final boolean allowDecimals, final Object defaultValue) {
        super();
        this.allowDecimals = allowDecimals;
        setDefaultValue(defaultValue);
    }

    

    /**
     * Return whether decimals are allowed in the number.
     *
     * @return Whether decimals are allowed in the number
     */
    public boolean isAllowDecimals() {
        return allowDecimals;
    }

    /**
     * Set whether a format should be used to convert
     * the Number.
     *
     * @param useLocaleFormat {@code true} if a number format
     * should be used.
     */
    public void setUseLocaleFormat(final boolean useLocaleFormat) {
        this.useLocaleFormat = useLocaleFormat;
    }

    /**
     * Return the number format pattern used to convert
     * Numbers to/from a {@code java.lang.String}
     * (or {@code null} if none specified).
     * <p>
     * See {@code java.text.DecimalFormat} for details
     * of how to specify the pattern.
     *
     * @return The format pattern.
     */
    public String getPattern() {
        return pattern;
    }

    /**
     * Set a number format pattern to use to convert
     * Numbers to/from a {@code java.lang.String}.
     * <p>
     * See {@code java.text.DecimalFormat} for details
     * of how to specify the pattern.
     *
     * @param pattern The format pattern.
     */
    public void setPattern(final String pattern) {
        this.pattern = pattern;
        setUseLocaleFormat(true);
    }

    /**
     * Return the Locale for the <i>Converter</i>
     * (or {@code null} if none specified).
     *
     * @return The locale to use for conversion
     */
    public Locale getLocale() {
        return locale;
    }

    /**
     * Set the Locale for the <i>Converter</i>.
     *
     * @param locale The locale to use for conversion
     */
    public void setLocale(final Locale locale) {
        this.locale = locale;
        setUseLocaleFormat(true);
    }

    

    /**
     * Convert an input Number object into a String.
     *
     * @param value The input value to be converted
     * @return the converted String value.
     * @throws Throwable if an error occurs converting to a String
     */
    @Override
    protected String convertToString(final Object value) throws Throwable {

        String result = null;
        if (useLocaleFormat && value instanceof Number) {
            final NumberFormat format = getFormat();
            format.setGroupingUsed(false);
            result = format.format(value);
            if (log().isDebugEnabled()) {
                log().debug("    Converted  to String using format '" + result + "'");
            }

        } else {
            result = value.toString();
            if (log().isDebugEnabled()) {
                log().debug("    Converted  to String using toString() '" + result + "'");
            }
        }
        return result;

    }

    /**
     * Convert the input object into a Number object of the
     * specified type.
     *
     * @param <T> Target type of the conversion.
     * @param targetType Data type to which this value should be converted.
     * @param value The input value to be converted.
     * @return The converted value.
     * @throws Throwable if an error occurs converting to the specified type
     */
    @Override
    protected <T> T convertToType(final Class<T> targetType, final Object value) throws Throwable {

        final Class<?> sourceType = value.getClass();
        // Handle Number
        if (value instanceof Number) {
            return toNumber(sourceType, targetType, (Number)value);
        }

        // Handle Boolean
        if (value instanceof Boolean) {
            return toNumber(sourceType, targetType, ((Boolean)value).booleanValue() ? ONE : ZERO);
        }

        // Handle Date --> Long
        if (value instanceof Date && Long.class.equals(targetType)) {
            return targetType.cast(Long.valueOf(((Date)value).getTime()));
        }

        // Handle Calendar --> Long
        if (value instanceof Calendar  && Long.class.equals(targetType)) {
            return targetType.cast(Long.valueOf(((Calendar)value).getTime().getTime()));
        }

        // Convert all other types to String & handle
        final String stringValue = value.toString().trim();
        if (stringValue.length() == 0) {
            return handleMissing(targetType);
        }

        // Convert/Parse a String
        Number number = null;
        if (useLocaleFormat) {
            final NumberFormat format = getFormat();
            number = parse(sourceType, targetType, stringValue, format);
        } else {
            if (log().isDebugEnabled()) {
                log().debug("    No NumberFormat, using default conversion");
            }
            number = toNumber(sourceType, targetType, stringValue);
        }

        // Ensure the correct number type is returned
        return toNumber(sourceType, targetType, number);

    }

    /**
     * Convert any Number object to the specified type for this
     * <i>Converter</i>.
     * <p>
     * This method handles conversion to the following types:
     * <ul>
     *     <li>{@code java.lang.Byte}</li>
     *     <li>{@code java.lang.Short}</li>
     *     <li>{@code java.lang.Integer}</li>
     *     <li>{@code java.lang.Long}</li>
     *     <li>{@code java.lang.Float}</li>
     *     <li>{@code java.lang.Double}</li>
     *     <li>{@code java.math.BigDecimal}</li>
     *     <li>{@code java.math.BigInteger}</li>
     * </ul>
     * @param sourceType The type being converted from
     * @param targetType The Number type to convert to
     * @param value The Number to convert.
     *
     * @return The converted value.
     */
    private <T> T toNumber(final Class<?> sourceType, final Class<T> targetType, final Number value) {

        // Correct Number type already
        if (targetType.equals(value.getClass())) {
            return targetType.cast(value);
        }

        // Byte
        if (targetType.equals(Byte.class)) {
            final long longValue = value.longValue();
            if (longValue > Byte.MAX_VALUE) {
                throw new ConversionException(toString(sourceType) + " value '" + value
                        + "' is too large for " + toString(targetType));
            }
            if (longValue < Byte.MIN_VALUE) {
                throw new ConversionException(toString(sourceType) + " value '" + value
                        + "' is too small " + toString(targetType));
            }
            return targetType.cast(Byte.valueOf(value.byteValue()));
        }

        // Short
        if (targetType.equals(Short.class)) {
            final long longValue = value.longValue();
            if (longValue > Short.MAX_VALUE) {
                throw new ConversionException(toString(sourceType) + " value '" + value
                        + "' is too large for " + toString(targetType));
            }
            if (longValue < Short.MIN_VALUE) {
                throw new ConversionException(toString(sourceType) + " value '" + value
                        + "' is too small " + toString(targetType));
            }
            return targetType.cast(Short.valueOf(value.shortValue()));
        }

        // Integer
        if (targetType.equals(Integer.class)) {
            final long longValue = value.longValue();
            if (longValue > Integer.MAX_VALUE) {
                throw new ConversionException(toString(sourceType) + " value '" + value
                        + "' is too large for " + toString(targetType));
            }
            if (longValue < Integer.MIN_VALUE) {
                throw new ConversionException(toString(sourceType) + " value '" + value
                        + "' is too small " + toString(targetType));
            }
            return targetType.cast(Integer.valueOf(value.intValue()));
        }

        // Long
        if (targetType.equals(Long.class)) {
            return targetType.cast(Long.valueOf(value.longValue()));
        }

        // Float
        if (targetType.equals(Float.class)) {
            if (value.doubleValue() > Float.MAX_VALUE) {
                throw new ConversionException(toString(sourceType) + " value '" + value
                        + "' is too large for " + toString(targetType));
            }
            return targetType.cast(Float.valueOf(value.floatValue()));
        }

        // Double
        if (targetType.equals(Double.class)) {
            return targetType.cast(Double.valueOf(value.doubleValue()));
        }

        // BigDecimal
        if (targetType.equals(BigDecimal.class)) {
            if (value instanceof Float || value instanceof Double) {
                return targetType.cast(new BigDecimal(value.toString()));
            } else if (value instanceof BigInteger) {
                return targetType.cast(new BigDecimal((BigInteger)value));
            } else if (value instanceof BigDecimal) {
                return targetType.cast(new BigDecimal(value.toString()));
            } else {
                return targetType.cast(BigDecimal.valueOf(value.longValue()));
            }
        }

        // BigInteger
        if (targetType.equals(BigInteger.class)) {
            if (value instanceof BigDecimal) {
                return targetType.cast(((BigDecimal)value).toBigInteger());
            }
            return targetType.cast(BigInteger.valueOf(value.longValue()));
        }

        final String msg = toString(getClass()) + " cannot handle conversion to '"
                   + toString(targetType) + "'";
        if (log().isWarnEnabled()) {
            log().warn("    " + msg);
        }
        throw new ConversionException(msg);

    }

    /**
     * Default String to Number conversion.
     * <p>
     * This method handles conversion from a String to the following types:
     * <ul>
     *     <li>{@code java.lang.Byte}</li>
     *     <li>{@code java.lang.Short}</li>
     *     <li>{@code java.lang.Integer}</li>
     *     <li>{@code java.lang.Long}</li>
     *     <li>{@code java.lang.Float}</li>
     *     <li>{@code java.lang.Double}</li>
     *     <li>{@code java.math.BigDecimal}</li>
     *     <li>{@code java.math.BigInteger}</li>
     * </ul>
     * @param sourceType The type being converted from
     * @param targetType The Number type to convert to
     * @param value The String value to convert.
     *
     * @return The converted Number value.
     */
    private Number toNumber(final Class<?> sourceType, final Class<?> targetType, final String value) {

        // Byte
        if (targetType.equals(Byte.class)) {
            return Byte.valueOf(value);
        }

        // Short
        if (targetType.equals(Short.class)) {
            return Short.valueOf(value);
        }

        // Integer
        if (targetType.equals(Integer.class)) {
            return Integer.valueOf(value);
        }

        // Long
        if (targetType.equals(Long.class)) {
            return Long.valueOf(value);
        }

        // Float
        if (targetType.equals(Float.class)) {
            return Float.valueOf(value);
        }

        // Double
        if (targetType.equals(Double.class)) {
            return Double.valueOf(value);
        }

        // BigDecimal
        if (targetType.equals(BigDecimal.class)) {
            return new BigDecimal(value);
        }

        // BigInteger
        if (targetType.equals(BigInteger.class)) {
            return new BigInteger(value);
        }

        final String msg = toString(getClass()) + " cannot handle conversion from '" +
                     toString(sourceType) + "' to '" + toString(targetType) + "'";
        if (log().isWarnEnabled()) {
            log().warn("    " + msg);
        }
        throw new ConversionException(msg);
    }

    /**
     * Provide a String representation of this number converter.
     *
     * @return A String representation of this number converter
     */
    @Override
    public String toString() {
        final StringBuilder buffer = new StringBuilder();
        buffer.append(toString(getClass()));
        buffer.append("[UseDefault=");
        buffer.append(isUseDefault());
        buffer.append(", UseLocaleFormat=");
        buffer.append(useLocaleFormat);
        if (pattern != null) {
            buffer.append(", Pattern=");
            buffer.append(pattern);
        }
        if (locale != null) {
            buffer.append(", Locale=");
            buffer.append(locale);
        }
        buffer.append(']');
        return buffer.toString();
    }

    /**
     * Return a NumberFormat to use for Conversion.
     *
     * @return The NumberFormat.
     */
    private NumberFormat getFormat() {
        NumberFormat format = null;
        if (pattern != null) {
            if (locale == null) {
                if (log().isDebugEnabled()) {
                    log().debug("    Using pattern '" + pattern + "'");
                }
                format = new DecimalFormat(pattern);
            } else {
                if (log().isDebugEnabled()) {
                    log().debug("    Using pattern '" + pattern + "'" +
                              " with Locale[" + locale + "]");
                }
                final DecimalFormatSymbols symbols = new DecimalFormatSymbols(locale);
                format = new DecimalFormat(pattern, symbols);
            }
        } else {
            if (locale == null) {
                if (log().isDebugEnabled()) {
                    log().debug("    Using default Locale format");
                }
                format = NumberFormat.getInstance();
            } else {
                if (log().isDebugEnabled()) {
                    log().debug("    Using Locale[" + locale + "] format");
                }
                format = NumberFormat.getInstance(locale);
            }
        }
        if (!allowDecimals) {
            format.setParseIntegerOnly(true);
        }
        return format;
    }

    /**
     * Convert a String into a {@code Number} object.
     * @param sourceType the source type of the conversion
     * @param targetType The type to convert the value to
     * @param value The String date value.
     * @param format The NumberFormat to parse the String value.
     *
     * @return The converted Number object.
     * @throws ConversionException if the String cannot be converted.
     */
    private Number parse(final Class<?> sourceType, final Class<?> targetType, final String value, final NumberFormat format) {
        final ParsePosition pos = new ParsePosition(0);
        final Number parsedNumber = format.parse(value, pos);
        if (pos.getErrorIndex() >= 0 || pos.getIndex() != value.length() || parsedNumber == null) {
            String msg = "Error converting from '" + toString(sourceType) + "' to '" + toString(targetType) + "'";
            if (format instanceof DecimalFormat) {
                msg += " using pattern '" + ((DecimalFormat)format).toPattern() + "'";
            }
            if (locale != null) {
                msg += " for locale=[" + locale + "]";
            }
            if (log().isDebugEnabled()) {
                log().debug("    " + msg);
            }
            throw new ConversionException(msg);
        }
        return parsedNumber;
    }

}
