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

import java.math.BigDecimal;
import java.nio.ByteBuffer;
import java.util.Date;
import java.util.function.Function;

/**
 * This file is copied verbatim from Apache Lucene NumericUtils.java
 * Only the double/float to sortable long/int conversions are retained.
 */
public final class NumericUtil {

    private static final long FULL_LONG = Long.MIN_VALUE;
    private static final int FULL_INT = Integer.MIN_VALUE;
    private static final byte FULL_BYTE = Byte.MIN_VALUE;

    private NumericUtil() {
    }

    /**
     * Converts a <code>double</code> value to a sortable signed
     * <code>long</code>. The value is converted by getting their IEEE 754
     * floating-point &quot;double format&quot; bit layout and then some bits
     * are swapped, to be able to compare the result as long. By this the
     * precision is not reduced, but the value can be easily used as a long. The
     * sort order (including {@link Double#NaN}) is defined by
     * {@link Double#compareTo}; {@code NaN} is greater than positive infinity.
     * @param value input double value
     * @return output sortable long value
     * @see #sortableLongToDouble
     */
    public static long doubleToSortableLong(double value) {
        return sortableDoubleBits(Double.doubleToLongBits(value));
    }

    /**
     * Converts a sortable <code>long</code> back to a <code>double</code>.
     * @param value input double value
     * @return output sortable long value
     * @see #doubleToSortableLong
     */
    public static double sortableLongToDouble(long value) {
        return Double.longBitsToDouble(sortableDoubleBits(value));
    }

    /**
     * Converts a <code>float</code> value to a sortable signed
     * <code>int</code>. The value is converted by getting their IEEE 754
     * floating-point &quot;float format&quot; bit layout and then some bits are
     * swapped, to be able to compare the result as int. By this the precision
     * is not reduced, but the value can be easily used as an int. The sort order
     * (including {@link Float#NaN}) is defined by {@link Float#compareTo};
     * {@code NaN} is greater than positive infinity.
     * @param value input float value
     * @return output sortable int value
     * @see #sortableIntToFloat
     */
    public static int floatToSortableInt(float value) {
        return sortableFloatBits(Float.floatToIntBits(value));
    }

    /**
     * Converts a sortable <code>int</code> back to a <code>float</code>.
     * @param value input int value
     * @return output sortable float value
     * @see #floatToSortableInt
     */
    public static float sortableIntToFloat(int value) {
        return Float.intBitsToFloat(sortableFloatBits(value));
    }

    /**
     * Converts IEEE 754 representation of a double to sortable order (or back
     * to the original)
     * @param bits The long format of a double value
     * @return The sortable long value
     */
    public static long sortableDoubleBits(long bits) {
        return bits ^ ((bits >> 63) & 0x7fffffffffffffffL);
    }

    /**
     * Converts IEEE 754 representation of a float to sortable order (or back to
     * the original)
     * @param bits The int format of a float value
     * @return The sortable int value
     */
    public static int sortableFloatBits(int bits) {
        /*
         * Convert to its inverse digits if negative else keep the origin
         * NOTE: (bits >> 31) is 0x00000000 if bits >= 0
         *       (bits >> 31) is 0xFFFFFFFF if bits < 0
         */
        return bits ^ ((bits >> 31) & 0x7fffffff);
    }

    public static long numberToSortableLong(Number number) {
        if (number instanceof Double) {
            return doubleToSortableLong(number.doubleValue());
        } else if (number instanceof Float) {
            return floatToSortableInt(number.floatValue());
        } else if (number instanceof Long || number instanceof Integer ||
                   number instanceof Short || number instanceof Byte) {
            return number.longValue();
        } else if (number instanceof BigDecimal) {
            BigDecimal bd = (BigDecimal) number;
            boolean intNumber = bd.stripTrailingZeros().scale() <= 0;
            return intNumber ? bd.longValueExact() :
                   doubleToSortableLong(bd.doubleValue());
        }

        // TODO: support other number types
        throw unsupportedNumberType(number);
    }

    public static Number sortableLongToNumber(long value, Class<?> clazz) {
        assert NumericUtil.isNumber(clazz);

        if (clazz == Double.class) {
            return sortableLongToDouble(value);
        } else if (clazz == Float.class) {
            return sortableIntToFloat((int) value);
        } else if (clazz == Long.class) {
            return value;
        } else if (clazz == Integer.class) {
            return (int) value;
        } else if (clazz == Short.class) {
            return (short) value;
        } else if (clazz == Byte.class) {
            return (byte) value;
        }

        // TODO: support other number types
        throw unsupportedNumberType(clazz);
    }

    public static byte[] numberToSortableBytes(Number number) {
        if (number instanceof Long) {
            return longToSortableBytes(number.longValue());
        } else if (number instanceof Double) {
            long value = doubleToSortableLong(number.doubleValue());
            return longToSortableBytes(value);
        } else if (number instanceof Float) {
            int value = floatToSortableInt(number.floatValue());
            return intToSortableBytes(value);
        } else if (number instanceof Integer || number instanceof Short) {
            return intToSortableBytes(number.intValue());
        } else if (number instanceof Byte) {
            return byteToSortableBytes(number.byteValue());
        }

        // TODO: support other number types
        throw unsupportedNumberType(number);
    }

    public static Number sortableBytesToNumber(byte[] bytes, Class<?> clazz) {
        assert NumericUtil.isNumber(clazz);

        if (clazz == Long.class) {
            return sortableBytesToLong(bytes);
        } else if (clazz == Double.class) {
            return sortableLongToDouble(sortableBytesToLong(bytes));
        } else if (clazz == Float.class) {
            return sortableIntToFloat(sortableBytesToInt(bytes));
        } else if (clazz == Integer.class) {
            return sortableBytesToInt(bytes);
        } else if (clazz == Short.class) {
            return (short) sortableBytesToInt(bytes);
        } else if (clazz == Byte.class) {
            return sortableBytesToByte(bytes);
        }

        // TODO: support other number types
        throw unsupportedNumberType(clazz);
    }

    public static Number minValueOf(Class<?> clazz) {
        E.checkArgumentNotNull(clazz, "The clazz can't be null");

        if (Long.class.isAssignableFrom(clazz) ||
            Double.class.isAssignableFrom(clazz)) {
            return Long.MIN_VALUE;
        }
        if (Integer.class.isAssignableFrom(clazz) ||
            Short.class.isAssignableFrom(clazz) ||
            Float.class.isAssignableFrom(clazz)) {
            return Integer.MIN_VALUE;
        }
        if (Byte.class.isAssignableFrom(clazz)) {
            return Byte.MIN_VALUE;
        }

        // TODO: support other number types
        throw unsupportedNumberType(clazz);
    }

    public static Number maxValueOf(Class<?> clazz) {
        E.checkArgumentNotNull(clazz, "The clazz can't be null");

        if (Long.class.isAssignableFrom(clazz) ||
            Double.class.isAssignableFrom(clazz)) {
            return Long.MAX_VALUE;
        }
        if (Integer.class.isAssignableFrom(clazz) ||
            Float.class.isAssignableFrom(clazz) ||
            Short.class.isAssignableFrom(clazz)) {
            return Integer.MAX_VALUE;
        }
        if (Byte.class.isAssignableFrom(clazz)) {
            return Byte.MAX_VALUE;
        }

        // TODO: support other number types
        throw unsupportedNumberType(clazz);
    }

    public static byte[] longToSortableBytes(long value) {
        return longToBytes(value + FULL_LONG);
    }

    public static long sortableBytesToLong(byte[] bytes) {
        return bytesToLong(bytes) - FULL_LONG;
    }

    public static byte[] intToSortableBytes(int value) {
        return intToBytes(value + FULL_INT);
    }

    public static int sortableBytesToInt(byte[] bytes) {
        return bytesToInt(bytes) - FULL_INT;
    }

    public static byte[] byteToSortableBytes(byte value) {
        value += FULL_BYTE;
        return new byte[]{value};
    }

    public static byte sortableBytesToByte(byte[] bytes) {
        assert bytes.length == 1;
        byte value = bytes[0];
        value -= FULL_BYTE;
        return value;
    }

    public static byte[] longToBytes(long value) {
        ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
        buffer.putLong(value);
        return buffer.array();
    }

    public static long bytesToLong(byte[] bytes) {
        assert bytes.length == Long.BYTES;
        return ByteBuffer.wrap(bytes).getLong();
    }

    public static byte[] intToBytes(int value) {
        ByteBuffer buffer = ByteBuffer.allocate(Integer.BYTES);
        buffer.putInt(value);
        return buffer.array();
    }

    public static int bytesToInt(byte[] bytes) {
        assert bytes.length == Integer.BYTES;
        return ByteBuffer.wrap(bytes).getInt();
    }

    public static boolean isNumber(Object value) {
        if (value == null) {
            return false;
        }
        return isNumber(value.getClass());
    }

    public static boolean isNumber(Class<?> clazz) {
        if (clazz.isPrimitive()) {
            if (clazz == int.class || clazz == long.class ||
                clazz == float.class || clazz == double.class ||
                clazz == short.class || clazz == byte.class) {
                return true;
            }
            return false;
        }
        return Number.class.isAssignableFrom(clazz);
    }

    public static Number convertToNumber(Object value) {
        if (value == null) {
            return null;
        }

        Number number;
        if (isNumber(value)) {
            number = (Number) value;
        } else {
            if (value instanceof Date) {
                number = ((Date) value).getTime();
            } else {
                // TODO: add some more types to convert
                number = new BigDecimal(value.toString());
            }
        }
        return number;
    }

    /**
     * Compare object with a number, the object should be a number,
     * or it can be converted to a BigDecimal
     * @param first   might be number or string
     * @param second  must be number
     * @return  0 if first is numerically equal to second;
     *          a negative int if first is numerically less than second;
     *          a positive int if first is numerically greater than second.
     */
    public static int compareNumber(Object first, Number second) {
        if (first == null) {
            E.checkArgument(first != null,
                            "The first parameter can't be null");
        }
        if (second == null) {
            E.checkArgument(second != null,
                            "The second parameter can't be null");
        }

        if (first instanceof Number && first instanceof Comparable &&
            first.getClass().equals(second.getClass())) {
            @SuppressWarnings("unchecked")
            Comparable<Number> cmpFirst = (Comparable<Number>) first;
            return cmpFirst.compareTo(second);
        }

        Function<Object, BigDecimal> toBig = (number) -> {
            try {
                return new BigDecimal(number.toString());
            } catch (NumberFormatException e) {
                throw new IllegalArgumentException(String.format(
                          "Can't compare between '%s' and '%s', " +
                          "they must be numbers", first, second));
            }
        };

        BigDecimal n1 = toBig.apply(first);
        BigDecimal n2 = toBig.apply(second);

        return n1.compareTo(n2);
    }

    private static IllegalArgumentException unsupportedNumberType(Class<?> c) {
        return new IllegalArgumentException(String.format(
                   "Unsupported number type: %s", c.getSimpleName()));
    }

    private static IllegalArgumentException unsupportedNumberType(Number num) {
        return new IllegalArgumentException(String.format(
                   "Unsupported number type: %s(%s)",
                   num.getClass().getSimpleName(), num));
    }
}
