/* UtilLib - Copyright (c) 2005-2023 Vincent Calame - Exemole
 * Logiciel libre donné sous triple licence :
 * 1) selon les termes de la CeCILL V2
 * 2) selon les termes de l’EUPL V.1.1
 * 3) selon les termes de la GNU GPLv3
 * Voir le fichier licences.txt
 */


package net.mapeadores.util.primitives;

import java.util.AbstractList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.RandomAccess;


/**
 *
 * @author Vincent Calame
 */
public class PrimUtils {

    public final static List<Integer> EMPTY_LIST = Collections.emptyList();

    static long MASK_INT2 = 0x00000000FFFFFFFFL;

    /**
     * Creates a new instance of PrimUtils
     */
    private PrimUtils() {
    }

    public static long toLong(int int1, int int2) {
        long long1 = (long) int1;
        long long2 = (long) int2;
        long1 = long1 << 32;
        long2 = long2 & MASK_INT2;
        return long1 | long2;
    }

    public static Long toLongObject(int int1, int int2) {
        return toLong(int1, int2);
    }

    public static int getInt1(long l) {
        return (int) (l >>> 32);
    }

    public static int getInt2(long l) {
        return (int) l;
    }

    public static boolean equalsInt1(long l, int i) {
        return (getInt1(l) == i);
    }

    public static boolean equalsInt2(long l, int i) {
        return (getInt2(l) == i);
    }

    public static int[] toIntArray(List<Integer> integerList) {
        int size = integerList.size();
        int[] result = new int[size];
        for (int i = 0; i < size; i++) {
            result[i] = integerList.get(i);
        }
        return result;
    }

    public static Integer[] toArray(Collection<Integer> integers) {
        return integers.toArray(new Integer[integers.size()]);
    }

    public static List<Integer> wrap(Integer[] array) {
        return new IntegerList(array);
    }

    public static List<Integer> wrap(int[] array) {
        return new PrimIntegerList(array);
    }

    public static void convertInt(int value, byte[] bytes) {
        bytes[0] = (byte) (0xff & (value >> 24));
        bytes[1] = (byte) (0xff & (value >> 16));
        bytes[2] = (byte) (0xff & (value >> 8));
        bytes[3] = (byte) (0xff & value);
    }

    public static void convertInt(int value, byte[] bytes, int start) {
        bytes[start] = (byte) (0xff & (value >> 24));
        bytes[start + 1] = (byte) (0xff & (value >> 16));
        bytes[start + 2] = (byte) (0xff & (value >> 8));
        bytes[start + 3] = (byte) (0xff & value);
    }

    public static void convertLong(long value, byte[] bytes) {
        bytes[0] = (byte) (0xff & (value >> 56));
        bytes[1] = (byte) (0xff & (value >> 48));
        bytes[2] = (byte) (0xff & (value >> 40));
        bytes[3] = (byte) (0xff & (value >> 32));
        bytes[4] = (byte) (0xff & (value >> 24));
        bytes[5] = (byte) (0xff & (value >> 16));
        bytes[6] = (byte) (0xff & (value >> 8));
        bytes[7] = (byte) (0xff & value);
    }

    public static void convertLong(long value, byte[] bytes, int start) {
        bytes[start] = (byte) (0xff & (value >> 56));
        bytes[start + 1] = (byte) (0xff & (value >> 48));
        bytes[start + 2] = (byte) (0xff & (value >> 40));
        bytes[start + 3] = (byte) (0xff & (value >> 32));
        bytes[start + 4] = (byte) (0xff & (value >> 24));
        bytes[start + 5] = (byte) (0xff & (value >> 16));
        bytes[start + 6] = (byte) (0xff & (value >> 8));
        bytes[start + 7] = (byte) (0xff & value);
    }

    public static void convertChar(char value, byte[] bytes) {
        bytes[0] = (byte) (0xff & (value >> 8));
        bytes[1] = (byte) (0xff & value);
    }

    public static void convertChar(char value, byte[] bytes, int start) {
        bytes[start] = (byte) (0xff & (value >> 8));
        bytes[start + 1] = (byte) (0xff & value);
    }

    public static char toChar(byte[] bytes) {
        return (char) ((bytes[0] << 8)
                | (bytes[1] & 0xff));
    }

    public static char toChar(byte[] bytes, int start) {
        return (char) ((bytes[start] << 8)
                | (bytes[start + 1] & 0xff));
    }

    public static short toShort(byte[] bytes, int start) {
        return (short) ((bytes[start] << 8)
                | (bytes[start + 1] & 0xff));
    }

    public static int toInt(byte[] bytes) {
        return (((bytes[0] & 0xff) << 24)
                | ((bytes[1] & 0xff) << 16)
                | ((bytes[2] & 0xff) << 8)
                | (bytes[3] & 0xff));
    }

    public static int toInt(byte[] bytes, int start) {
        return (((bytes[start] & 0xff) << 24)
                | ((bytes[start + 1] & 0xff) << 16)
                | ((bytes[start + 2] & 0xff) << 8)
                | (bytes[start + 3] & 0xff));
    }

    public static long toLong(byte[] bytes) {
        return (((long) (bytes[0] & 0xff) << 56)
                | ((long) (bytes[1] & 0xff) << 48)
                | ((long) (bytes[2] & 0xff) << 40)
                | ((long) (bytes[3] & 0xff) << 32)
                | ((long) (bytes[4] & 0xff) << 24)
                | ((long) (bytes[5] & 0xff) << 16)
                | ((long) (bytes[6] & 0xff) << 8)
                | ((long) (bytes[7] & 0xff)));
    }

    public static long toLong(byte[] bytes, int start) {
        return (((long) (bytes[start] & 0xff) << 56)
                | ((long) (bytes[start + 1] & 0xff) << 48)
                | ((long) (bytes[start + 2] & 0xff) << 40)
                | ((long) (bytes[start + 3] & 0xff) << 32)
                | ((long) (bytes[start + 4] & 0xff) << 24)
                | ((long) (bytes[start + 5] & 0xff) << 16)
                | ((long) (bytes[start + 6] & 0xff) << 8)
                | ((long) (bytes[start + 7] & 0xff)));
    }


    private static class IntegerList extends AbstractList<Integer> implements RandomAccess {

        private final Integer[] array;

        private IntegerList(Integer[] array) {
            this.array = array;
        }

        @Override
        public int size() {
            return array.length;
        }

        @Override
        public Integer get(int index) {
            return array[index];
        }

    }


    private static class PrimIntegerList extends AbstractList<Integer> implements RandomAccess {

        private final int[] array;

        private PrimIntegerList(int[] array) {
            this.array = array;
        }

        @Override
        public int size() {
            return array.length;
        }

        @Override
        public Integer get(int index) {
            return array[index];
        }

    }


}
