/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed 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 android.os;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;

import libcore.util.NativeAllocationRegistry;

/**
 * Represents fixed sized allocation of marshalled data used. Helper methods
 * allow for access to the unmarshalled data in a variety of ways.
 *
 * @hide
 */
@SystemApi
@TestApi
public class HwBlob {
    private static final String TAG = "HwBlob";

    private static final NativeAllocationRegistry sNativeRegistry;

    public HwBlob(int size) {
        native_setup(size);

        sNativeRegistry.registerNativeAllocation(
                this,
                mNativeContext);
    }

    /**
     * @param offset offset to unmarshall a boolean from
     * @return the unmarshalled boolean value
     * @throws IndexOutOfBoundsException when offset is out of this HwBlob
     */
    public native final boolean getBool(long offset);
    /**
     * @param offset offset to unmarshall a byte from
     * @return the unmarshalled byte value
     * @throws IndexOutOfBoundsException when offset is out of this HwBlob
     */
    public native final byte getInt8(long offset);
    /**
     * @param offset offset to unmarshall a short from
     * @return the unmarshalled short value
     * @throws IndexOutOfBoundsException when offset is out of this HwBlob
     */
    public native final short getInt16(long offset);
    /**
     * @param offset offset to unmarshall an int from
     * @return the unmarshalled int value
     * @throws IndexOutOfBoundsException when offset is out of this HwBlob
     */
    public native final int getInt32(long offset);
    /**
     * @param offset offset to unmarshall a long from
     * @return the unmarshalled long value
     * @throws IndexOutOfBoundsException when offset is out of this HwBlob
     */
    public native final long getInt64(long offset);
    /**
     * @param offset offset to unmarshall a float from
     * @return the unmarshalled float value
     * @throws IndexOutOfBoundsException when offset is out of this HwBlob
     */
    public native final float getFloat(long offset);
    /**
     * @param offset offset to unmarshall a double from
     * @return the unmarshalled double value
     * @throws IndexOutOfBoundsException when offset is out of this HwBlob
     */
    public native final double getDouble(long offset);
    /**
     * @param offset offset to unmarshall a string from
     * @return the unmarshalled string value
     * @throws IndexOutOfBoundsException when offset is out of this HwBlob
     */
    public native final String getString(long offset);

    /**
     * Copy the blobs data starting from the given byte offset into the range, copying
     * a total of size elements.
     *
     * @param offset starting location in blob
     * @param array destination array
     * @param size total number of elements to copy
     * @throws IllegalArgumentException array.length < size
     * @throws IndexOutOfBoundsException [offset, offset + size * sizeof(jboolean)] out of the blob.
     */
    public native final void copyToBoolArray(long offset, boolean[] array, int size);
    /**
     * Copy the blobs data starting from the given byte offset into the range, copying
     * a total of size elements.
     *
     * @param offset starting location in blob
     * @param array destination array
     * @param size total number of elements to copy
     * @throws IllegalArgumentException array.length < size
     * @throws IndexOutOfBoundsException [offset, offset + size * sizeof(jbyte)] out of the blob.
     */
    public native final void copyToInt8Array(long offset, byte[] array, int size);
    /**
     * Copy the blobs data starting from the given byte offset into the range, copying
     * a total of size elements.
     *
     * @param offset starting location in blob
     * @param array destination array
     * @param size total number of elements to copy
     * @throws IllegalArgumentException array.length < size
     * @throws IndexOutOfBoundsException [offset, offset + size * sizeof(jshort)] out of the blob.
     */
    public native final void copyToInt16Array(long offset, short[] array, int size);
    /**
     * Copy the blobs data starting from the given byte offset into the range, copying
     * a total of size elements.
     *
     * @param offset starting location in blob
     * @param array destination array
     * @param size total number of elements to copy
     * @throws IllegalArgumentException array.length < size
     * @throws IndexOutOfBoundsException [offset, offset + size * sizeof(jint)] out of the blob.
     */
    public native final void copyToInt32Array(long offset, int[] array, int size);
    /**
     * Copy the blobs data starting from the given byte offset into the range, copying
     * a total of size elements.
     *
     * @param offset starting location in blob
     * @param array destination array
     * @param size total number of elements to copy
     * @throws IllegalArgumentException array.length < size
     * @throws IndexOutOfBoundsException [offset, offset + size * sizeof(jlong)] out of the blob.
     */
    public native final void copyToInt64Array(long offset, long[] array, int size);
    /**
     * Copy the blobs data starting from the given byte offset into the range, copying
     * a total of size elements.
     *
     * @param offset starting location in blob
     * @param array destination array
     * @param size total number of elements to copy
     * @throws IllegalArgumentException array.length < size
     * @throws IndexOutOfBoundsException [offset, offset + size * sizeof(jfloat)] out of the blob.
     */
    public native final void copyToFloatArray(long offset, float[] array, int size);
    /**
     * Copy the blobs data starting from the given byte offset into the range, copying
     * a total of size elements.
     *
     * @param offset starting location in blob
     * @param array destination array
     * @param size total number of elements to copy
     * @throws IllegalArgumentException array.length < size
     * @throws IndexOutOfBoundsException [offset, offset + size * sizeof(jdouble)] out of the blob.
     */
    public native final void copyToDoubleArray(long offset, double[] array, int size);

    /**
     * Writes a boolean value at an offset.
     *
     * @param offset location to write value
     * @param x value to write
     * @throws IndexOutOfBoundsException when [offset, offset + sizeof(jboolean)] is out of range
     */
    public native final void putBool(long offset, boolean x);
    /**
     * Writes a byte value at an offset.
     *
     * @param offset location to write value
     * @param x value to write
     * @throws IndexOutOfBoundsException when [offset, offset + sizeof(jbyte)] is out of range
     */
    public native final void putInt8(long offset, byte x);
    /**
     * Writes a short value at an offset.
     *
     * @param offset location to write value
     * @param x value to write
     * @throws IndexOutOfBoundsException when [offset, offset + sizeof(jshort)] is out of range
     */
    public native final void putInt16(long offset, short x);
    /**
     * Writes a int value at an offset.
     *
     * @param offset location to write value
     * @param x value to write
     * @throws IndexOutOfBoundsException when [offset, offset + sizeof(jint)] is out of range
     */
    public native final void putInt32(long offset, int x);
    /**
     * Writes a long value at an offset.
     *
     * @param offset location to write value
     * @param x value to write
     * @throws IndexOutOfBoundsException when [offset, offset + sizeof(jlong)] is out of range
     */
    public native final void putInt64(long offset, long x);
    /**
     * Writes a float value at an offset.
     *
     * @param offset location to write value
     * @param x value to write
     * @throws IndexOutOfBoundsException when [offset, offset + sizeof(jfloat)] is out of range
     */
    public native final void putFloat(long offset, float x);
    /**
     * Writes a double value at an offset.
     *
     * @param offset location to write value
     * @param x value to write
     * @throws IndexOutOfBoundsException when [offset, offset + sizeof(jdouble)] is out of range
     */
    public native final void putDouble(long offset, double x);
    /**
     * Writes a string value at an offset.
     *
     * @param offset location to write value
     * @param x value to write
     * @throws IndexOutOfBoundsException when [offset, offset + sizeof(jstring)] is out of range
     */
    public native final void putString(long offset, String x);
    /**
     * Writes a native handle (without duplicating the underlying file descriptors) at an offset.
     *
     * @param offset location to write value
     * @param x a {@link NativeHandle} instance to write
     * @throws IndexOutOfBoundsException when [offset, offset + sizeof(jobject)] is out of range
     */
    public native final void putNativeHandle(long offset, @Nullable NativeHandle x);

    /**
     * Put a boolean array contiguously at an offset in the blob.
     *
     * @param offset location to write values
     * @param x array to write
     * @throws IndexOutOfBoundsException [offset, offset + size * sizeof(jboolean)] out of the blob.
     */
    public native final void putBoolArray(long offset, boolean[] x);
    /**
     * Put a byte array contiguously at an offset in the blob.
     *
     * @param offset location to write values
     * @param x array to write
     * @throws IndexOutOfBoundsException [offset, offset + size * sizeof(jbyte)] out of the blob.
     */
    public native final void putInt8Array(long offset, byte[] x);
    /**
     * Put a short array contiguously at an offset in the blob.
     *
     * @param offset location to write values
     * @param x array to write
     * @throws IndexOutOfBoundsException [offset, offset + size * sizeof(jshort)] out of the blob.
     */
    public native final void putInt16Array(long offset, short[] x);
    /**
     * Put a int array contiguously at an offset in the blob.
     *
     * @param offset location to write values
     * @param x array to write
     * @throws IndexOutOfBoundsException [offset, offset + size * sizeof(jint)] out of the blob.
     */
    public native final void putInt32Array(long offset, int[] x);
    /**
     * Put a long array contiguously at an offset in the blob.
     *
     * @param offset location to write values
     * @param x array to write
     * @throws IndexOutOfBoundsException [offset, offset + size * sizeof(jlong)] out of the blob.
     */
    public native final void putInt64Array(long offset, long[] x);
    /**
     * Put a float array contiguously at an offset in the blob.
     *
     * @param offset location to write values
     * @param x array to write
     * @throws IndexOutOfBoundsException [offset, offset + size * sizeof(jfloat)] out of the blob.
     */
    public native final void putFloatArray(long offset, float[] x);
    /**
     * Put a double array contiguously at an offset in the blob.
     *
     * @param offset location to write values
     * @param x array to write
     * @throws IndexOutOfBoundsException [offset, offset + size * sizeof(jdouble)] out of the blob.
     */
    public native final void putDoubleArray(long offset, double[] x);

    /**
     * Write another HwBlob into this blob at the specified location.
     *
     * @param offset location to write value
     * @param blob data to write
     * @throws IndexOutOfBoundsException if [offset, offset + blob's size] outside of the range of
     *     this blob.
     */
    public native final void putBlob(long offset, HwBlob blob);

    /**
     * @return current handle of HwBlob for reference in a parcelled binder transaction
     */
    public native final long handle();

    /**
     * Convert a primitive to a wrapped array for boolean.
     *
     * @param array from array
     * @return transformed array
     */
    public static Boolean[] wrapArray(@NonNull boolean[] array) {
        final int n = array.length;
        Boolean[] wrappedArray = new Boolean[n];
        for (int i = 0; i < n; ++i) {
          wrappedArray[i] = array[i];
        }
        return wrappedArray;
    }

    /**
     * Convert a primitive to a wrapped array for long.
     *
     * @param array from array
     * @return transformed array
     */
    public static Long[] wrapArray(@NonNull long[] array) {
        final int n = array.length;
        Long[] wrappedArray = new Long[n];
        for (int i = 0; i < n; ++i) {
          wrappedArray[i] = array[i];
        }
        return wrappedArray;
    }

    /**
     * Convert a primitive to a wrapped array for byte.
     *
     * @param array from array
     * @return transformed array
     */
    public static Byte[] wrapArray(@NonNull byte[] array) {
        final int n = array.length;
        Byte[] wrappedArray = new Byte[n];
        for (int i = 0; i < n; ++i) {
          wrappedArray[i] = array[i];
        }
        return wrappedArray;
    }

    /**
     * Convert a primitive to a wrapped array for short.
     *
     * @param array from array
     * @return transformed array
     */
    public static Short[] wrapArray(@NonNull short[] array) {
        final int n = array.length;
        Short[] wrappedArray = new Short[n];
        for (int i = 0; i < n; ++i) {
          wrappedArray[i] = array[i];
        }
        return wrappedArray;
    }

    /**
     * Convert a primitive to a wrapped array for int.
     *
     * @param array from array
     * @return transformed array
     */
    public static Integer[] wrapArray(@NonNull int[] array) {
        final int n = array.length;
        Integer[] wrappedArray = new Integer[n];
        for (int i = 0; i < n; ++i) {
          wrappedArray[i] = array[i];
        }
        return wrappedArray;
    }

    /**
     * Convert a primitive to a wrapped array for float.
     *
     * @param array from array
     * @return transformed array
     */
    public static Float[] wrapArray(@NonNull float[] array) {
        final int n = array.length;
        Float[] wrappedArray = new Float[n];
        for (int i = 0; i < n; ++i) {
          wrappedArray[i] = array[i];
        }
        return wrappedArray;
    }

    /**
     * Convert a primitive to a wrapped array for double.
     *
     * @param array from array
     * @return transformed array
     */
    public static Double[] wrapArray(@NonNull double[] array) {
        final int n = array.length;
        Double[] wrappedArray = new Double[n];
        for (int i = 0; i < n; ++i) {
          wrappedArray[i] = array[i];
        }
        return wrappedArray;
    }

    // Returns address of the "freeFunction".
    private static native final long native_init();

    private native final void native_setup(int size);

    static {
        long freeFunction = native_init();

        sNativeRegistry = new NativeAllocationRegistry(
                HwBlob.class.getClassLoader(),
                freeFunction,
                128 /* size */);
    }

    private long mNativeContext;
}


