// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package io.v.v23.vom;

import io.v.v23.vdl.Kind;
import io.v.v23.vdl.VdlArray;
import io.v.v23.vdl.VdlEnum;
import io.v.v23.vdl.VdlString;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;

/**
 * ConvertUtil provides helpers to convert VDL values.
 */
final class ConvertUtil {

    // IEEE 754 represents float64 using 52 bits to represent the mantissa, with
    // an extra implied leading bit. That gives us 53 bits to store integers
    // without overflow - i.e. [0, (2^53)-1]. And since 2^53 is a small power of
    // two, it can also be stored without loss via mantissa=1 exponent=53. Thus
    // we have our max and min values. Ditto for float32, which uses 23 bits
    // with
    // an extra implied leading bit.
    private static long DOUBLE_MAX_LOSSLESS_INTEGER = (1L << 53);
    private static long DOUBLE_MIN_LOSSLESS_INTEGER = -(1L << 53);
    private static long FLOAT_MAX_LOSSLESS_INTEGER = (1L << 24);
    private static long FLOAT_MIN_LOSSLESS_INTEGER = -(1L << 24);

    static boolean hasOverflowUint(long x, long bitlen) {
        long shift = 64 - bitlen;
        return x != (x << shift) >>> shift;
    }

    static boolean hasOverflowInt(long x, long bitlen) {
        long shift = 64 - bitlen;
        return x != (x << shift) >> shift;
    }

    static boolean canConvertUintToInt(long x, long bitlen) {
        return x >= 0 && !hasOverflowInt(x, bitlen);
    }

    static boolean canConvertIntToUint(long x, long bitlen) {
        return x >= 0 && !hasOverflowUint(x, bitlen);
    }

    static boolean canConvertUintToFloat(long x, long bitlen) {
        if (x < 0)
            return false; // These values are too large for either type.
        switch ((int) bitlen) {
            case 32:
                return x <= FLOAT_MAX_LOSSLESS_INTEGER;
            default:
                return x <= DOUBLE_MAX_LOSSLESS_INTEGER;
        }
    }

    static boolean canConvertIntToFloat(long x, long bitlen) {
        switch ((int) bitlen) {
            case 32:
                return FLOAT_MIN_LOSSLESS_INTEGER <= x
                        && x <= FLOAT_MAX_LOSSLESS_INTEGER;
            default:
                return DOUBLE_MIN_LOSSLESS_INTEGER <= x
                        && x <= DOUBLE_MAX_LOSSLESS_INTEGER;
        }
    }

    static long explicitConvertFloatToUint(double x) {
        if (x < DOUBLE_MAX_LOSSLESS_INTEGER * 4) {
            return (long) x;
        } else {
            return ((long) (x / 2)) << 1;
        }
    }

    static boolean canConvertFloatToUint(double x, long bitlen) {
        if (x < 0) {
            return false;
        }
        if (x < DOUBLE_MAX_LOSSLESS_INTEGER * 4) {
            return canConvertFloatToInt(x, bitlen);
        } else {
            return canConvertFloatToInt(x / 2, bitlen);
        }
    }

    static boolean canConvertFloatToInt(double x, long bitlen) {
        long intPart = (long) x;
        double fracPart = x - intPart;
        return fracPart == 0 && x >= Long.MIN_VALUE
                && x <= Long.MAX_VALUE
                && !hasOverflowInt(intPart, bitlen);
    }

    /**
     * Converts uint values to uint, int, float or complex values only.
     * This is used to check O(n) conversion rules instead of O(n^2) for n numeric types.
     */
    private static Object convertUint(long value, ConversionTarget target)
            throws ConversionException {
        switch (target.getKind()) {
            case BYTE:
                if (!hasOverflowUint(value, 8)) {
                    return ReflectUtil.createPrimitive(target, (byte) value, Byte.TYPE);
                }
                break;
            case UINT16:
                if (!hasOverflowUint(value, 16)) {
                    return ReflectUtil.createPrimitive(target, (short) value, Short.TYPE);
                }
                break;
            case UINT32:
                if (!hasOverflowUint(value, 32)) {
                    return ReflectUtil.createPrimitive(target, (int) value, Integer.TYPE);
                }
                break;
            case UINT64:
                return ReflectUtil.createPrimitive(target, value, Long.TYPE);
            default:
                if (ConvertUtil.canConvertUintToInt(value, 64)) {
                    return convertInt(value, target);
                }
        }
        throw new ConversionException("Can't convert " + value + " to " + target.getTargetType());
    }

    /**
     * Converts int values to int, float or complex values only.
     * This is used to check O(n) conversion rules instead of O(n^2) for n numeric types.
     */
    private static Object convertInt(long value, ConversionTarget target)
            throws ConversionException {
        switch (target.getKind()) {
            case INT16:
                if (!hasOverflowInt(value, 16)) {
                    return ReflectUtil.createPrimitive(target, (short) value, Short.TYPE);
                }
                break;
            case INT32:
                if (!hasOverflowInt(value, 32)) {
                    return ReflectUtil.createPrimitive(target, (int) value, Integer.TYPE);
                }
                break;
            case INT64:
                return ReflectUtil.createPrimitive(target, value, Long.TYPE);
            case FLOAT32:
            case COMPLEX64:
                if (ConvertUtil.canConvertIntToFloat(value, 32)) {
                    return convertDouble(value, target);
                }
                break;
            default:
                if (ConvertUtil.canConvertIntToFloat(value, 64)) {
                    return convertDouble(value, target);
                }
        }
        throw new ConversionException("Can't convert " + value + " to " + target.getTargetType());
    }

    /**
     * Converts float values to float or complex values only.
     * This is used to check O(n) conversion rules instead of O(n^2) for n numeric types.
     */
    private static Object convertDouble(double value, ConversionTarget target)
            throws ConversionException {
        switch (target.getKind()) {
            case FLOAT32:
                return ReflectUtil.createPrimitive(target, (float) value, Float.TYPE);
            case FLOAT64:
                return ReflectUtil.createPrimitive(target, value, Double.TYPE);
            default:
                return convertComplex(value, 0, target);
        }
    }

    /**
     * Converts complex values to complex values only.
     * This is used to check O(n) conversion rules instead of O(n^2) for n numeric types.
     */
    private static Object convertComplex(double real, double imag, ConversionTarget target)
            throws ConversionException {
        return ReflectUtil.createComplex(target, real, imag);
    }

    /**
     * Converts from uint to number, one of uint, int, float or complex.
     */
    static Object convertFromUint(long value, ConversionTarget target) throws ConversionException {
        return convertUint(value, target);
    }

    /**
     * Converts from byte to number, one of uint, int, float or complex.
     */
    static Object convertFromByte(byte value, ConversionTarget target) throws ConversionException {
        return convertUint(value & 0xffL, target);
    }

    /**
     * Converts from int to number, one of uint, int, float or complex.
     */
    static Object convertFromInt(long value, ConversionTarget target) throws ConversionException {
        if (canConvertIntToUint(value, 64)) {
            return convertFromUint(value, target);
        } else {
            return convertInt(value, target);
        }
    }

    /**
     * Converts from float to number, one of uint, int, float or complex.
     */
    static Object convertFromDouble(double value, ConversionTarget target)
            throws ConversionException {
        switch (target.getKind()) {
            case UINT64:
                if (canConvertFloatToUint(value, 64)) {
                    return convertFromUint(explicitConvertFloatToUint(value), target);
                }
                break;
            case FLOAT32:
            case FLOAT64:
            case COMPLEX128:
            case COMPLEX64:
                break;
            default:
                if (canConvertFloatToInt(value, 64)) {
                    return convertFromInt((long) value, target);
                }
        }
        return convertDouble(value, target);
    }

    /**
     * Converts from complex to number, one of uint, int, float or complex.
     */
    static Object convertFromComplex(double real, double imag, ConversionTarget target)
            throws ConversionException {
        if (imag == 0) {
            return convertFromDouble(real, target);
        } else {
            return convertComplex(real, imag, target);
        }
    }

    /**
     * Converts from []byte to []number, [N]number, string or enum.
     */
    static Object convertFromBytes(byte[] bytes, ConversionTarget target)
            throws ConversionException {
        Class<?> targetClass = target.getTargetClass();
        if (targetClass == String.class || VdlString.class.isAssignableFrom(targetClass)) {
            return ReflectUtil.createPrimitive(target, new String(bytes), String.class);
        } else if (VdlEnum.class.isAssignableFrom(targetClass)) {
            return ReflectUtil.createEnum(target, new String(bytes));
        }
        int len = bytes.length;
        if (target.getKind() == Kind.ARRAY) {
            if (bytes.length > target.getVdlType().getLength()) {
                throw new ConversionException(bytes, target.getTargetType(),
                        "target array is too short");
            }
            len = target.getVdlType().getLength();
        }

        ConversionTarget element = new ConversionTarget(
                ReflectUtil.getElementType(target.getTargetType(), 0));
        if (targetClass.isArray() || VdlArray.class.isAssignableFrom(targetClass)) {
            Object data = Array.newInstance(element.getTargetClass(), len);
            for (int i = 0; i < bytes.length; i++) {
                ReflectUtil.setArrayValue(data, i, convertFromByte(bytes[i], element),
                        element.getTargetClass());
            }
            return ReflectUtil.createGeneric(target, data);
        } else {
            List<Object> list = new ArrayList<Object>();
            for (int i = 0; i < bytes.length; i++) {
                list.add(convertFromByte(bytes[i], element));
            }
            return ReflectUtil.createGeneric(target, list);
        }
    }
}
