/*
 * 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.IntDef;
import android.annotation.SystemApi;

import libcore.util.NativeAllocationRegistry;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;

/** @hide */
@SystemApi
public class HwParcel {
    private static final String TAG = "HwParcel";

    @IntDef(prefix = { "STATUS_" }, value = {
        STATUS_SUCCESS,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface Status {}

    /**
     * Success return error for a transaction. Written to parcels
     * using writeStatus.
     */
    public static final int STATUS_SUCCESS      = 0;

    private static final NativeAllocationRegistry sNativeRegistry;

    private HwParcel(boolean allocate) {
        native_setup(allocate);

        sNativeRegistry.registerNativeAllocation(
                this,
                mNativeContext);
    }

    /**
     * Creates an initialized and empty parcel.
     */
    public HwParcel() {
        native_setup(true /* allocate */);

        sNativeRegistry.registerNativeAllocation(
                this,
                mNativeContext);
    }

    /**
     * Writes an interface token into the parcel used to verify that
     * a transaction has made it to the write type of interface.
     *
     * @param interfaceName fully qualified name of interface message
     *     is being sent to.
     */
    public native final void writeInterfaceToken(String interfaceName);
    /**
     * Writes a boolean value to the end of the parcel.
     * @param val to write
     */
    public native final void writeBool(boolean val);
    /**
     * Writes a byte value to the end of the parcel.
     * @param val to write
     */
    public native final void writeInt8(byte val);
    /**
     * Writes a short value to the end of the parcel.
     * @param val to write
     */
    public native final void writeInt16(short val);
    /**
     * Writes a int value to the end of the parcel.
     * @param val to write
     */
    public native final void writeInt32(int val);
    /**
     * Writes a long value to the end of the parcel.
     * @param val to write
     */
    public native final void writeInt64(long val);
    /**
     * Writes a float value to the end of the parcel.
     * @param val to write
     */
    public native final void writeFloat(float val);
    /**
     * Writes a double value to the end of the parcel.
     * @param val to write
     */
    public native final void writeDouble(double val);
    /**
     * Writes a String value to the end of the parcel.
     *
     * Note, this will be converted to UTF-8 when it is written.
     *
     * @param val to write
     */
    public native final void writeString(String val);
    /**
     * Writes a native handle (without duplicating the underlying
     * file descriptors) to the end of the parcel.
     *
     * @param val to write
     */
    public native final void writeNativeHandle(NativeHandle val);

    /**
     * Writes an array of boolean values to the end of the parcel.
     * @param val to write
     */
    private native final void writeBoolVector(boolean[] val);
    /**
     * Writes an array of byte values to the end of the parcel.
     * @param val to write
     */
    private native final void writeInt8Vector(byte[] val);
    /**
     * Writes an array of short values to the end of the parcel.
     * @param val to write
     */
    private native final void writeInt16Vector(short[] val);
    /**
     * Writes an array of int values to the end of the parcel.
     * @param val to write
     */
    private native final void writeInt32Vector(int[] val);
    /**
     * Writes an array of long values to the end of the parcel.
     * @param val to write
     */
    private native final void writeInt64Vector(long[] val);
    /**
     * Writes an array of float values to the end of the parcel.
     * @param val to write
     */
    private native final void writeFloatVector(float[] val);
    /**
     * Writes an array of double values to the end of the parcel.
     * @param val to write
     */
    private native final void writeDoubleVector(double[] val);
    /**
     * Writes an array of String values to the end of the parcel.
     *
     * Note, these will be converted to UTF-8 as they are written.
     *
     * @param val to write
     */
    private native final void writeStringVector(String[] val);
    /**
     * Writes an array of native handles to the end of the parcel.
     * @param val array of {@link NativeHandle} objects to write
     */
    private native final void writeNativeHandleVector(NativeHandle[] val);

    /**
     * Helper method to write a list of Booleans to val.
     * @param val list to write
     */
    public final void writeBoolVector(ArrayList<Boolean> val) {
        final int n = val.size();
        boolean[] array = new boolean[n];
        for (int i = 0; i < n; ++i) {
            array[i] = val.get(i);
        }

        writeBoolVector(array);
    }

    /**
     * Helper method to write a list of Booleans to the end of the parcel.
     * @param val list to write
     */
    public final void writeInt8Vector(ArrayList<Byte> val) {
        final int n = val.size();
        byte[] array = new byte[n];
        for (int i = 0; i < n; ++i) {
            array[i] = val.get(i);
        }

        writeInt8Vector(array);
    }

    /**
     * Helper method to write a list of Shorts to the end of the parcel.
     * @param val list to write
     */
    public final void writeInt16Vector(ArrayList<Short> val) {
        final int n = val.size();
        short[] array = new short[n];
        for (int i = 0; i < n; ++i) {
            array[i] = val.get(i);
        }

        writeInt16Vector(array);
    }

    /**
     * Helper method to write a list of Integers to the end of the parcel.
     * @param val list to write
     */
    public final void writeInt32Vector(ArrayList<Integer> val) {
        final int n = val.size();
        int[] array = new int[n];
        for (int i = 0; i < n; ++i) {
            array[i] = val.get(i);
        }

        writeInt32Vector(array);
    }

    /**
     * Helper method to write a list of Longs to the end of the parcel.
     * @param val list to write
     */
    public final void writeInt64Vector(ArrayList<Long> val) {
        final int n = val.size();
        long[] array = new long[n];
        for (int i = 0; i < n; ++i) {
            array[i] = val.get(i);
        }

        writeInt64Vector(array);
    }

    /**
     * Helper method to write a list of Floats to the end of the parcel.
     * @param val list to write
     */
    public final void writeFloatVector(ArrayList<Float> val) {
        final int n = val.size();
        float[] array = new float[n];
        for (int i = 0; i < n; ++i) {
            array[i] = val.get(i);
        }

        writeFloatVector(array);
    }

    /**
     * Helper method to write a list of Doubles to the end of the parcel.
     * @param val list to write
     */
    public final void writeDoubleVector(ArrayList<Double> val) {
        final int n = val.size();
        double[] array = new double[n];
        for (int i = 0; i < n; ++i) {
            array[i] = val.get(i);
        }

        writeDoubleVector(array);
    }

    /**
     * Helper method to write a list of Strings to the end of the parcel.
     * @param val list to write
     */
    public final void writeStringVector(ArrayList<String> val) {
        writeStringVector(val.toArray(new String[val.size()]));
    }

    /**
     * Helper method to write a list of native handles to the end of the parcel.
     * @param val list of {@link NativeHandle} objects to write
     */
    public final void writeNativeHandleVector(ArrayList<NativeHandle> val) {
        writeNativeHandleVector(val.toArray(new NativeHandle[val.size()]));
    }

    /**
     * Write a hwbinder object to the end of the parcel.
     * @param binder value to write
     */
    public native final void writeStrongBinder(IHwBinder binder);

    /**
     * Checks to make sure that the interface name matches the name written by the parcel
     * sender by writeInterfaceToken
     *
     * @throws SecurityException interface doesn't match
     */
    public native final void enforceInterface(String interfaceName);

    /**
     * Reads a boolean value from the current location in the parcel.
     * @return value parsed from the parcel
     * @throws IllegalArgumentException if the parcel has no more data
     */
    public native final boolean readBool();
    /**
     * Reads a byte value from the current location in the parcel.
     * @return value parsed from the parcel
     * @throws IllegalArgumentException if the parcel has no more data
     */
    public native final byte readInt8();
    /**
     * Reads a short value from the current location in the parcel.
     * @return value parsed from the parcel
     * @throws IllegalArgumentException if the parcel has no more data
     */
    public native final short readInt16();
    /**
     * Reads a int value from the current location in the parcel.
     * @return value parsed from the parcel
     * @throws IllegalArgumentException if the parcel has no more data
     */
    public native final int readInt32();
    /**
     * Reads a long value from the current location in the parcel.
     * @return value parsed from the parcel
     * @throws IllegalArgumentException if the parcel has no more data
     */
    public native final long readInt64();
    /**
     * Reads a float value from the current location in the parcel.
     * @return value parsed from the parcel
     * @throws IllegalArgumentException if the parcel has no more data
     */
    public native final float readFloat();
    /**
     * Reads a double value from the current location in the parcel.
     * @return value parsed from the parcel
     * @throws IllegalArgumentException if the parcel has no more data
     */
    public native final double readDouble();
    /**
     * Reads a String value from the current location in the parcel.
     * @return value parsed from the parcel
     * @throws IllegalArgumentException if the parcel has no more data
     */
    public native final String readString();
    /**
     * Reads a native handle (without duplicating the underlying file
     * descriptors) from the parcel. These file descriptors will only
     * be open for the duration that the binder window is open. If they
     * are needed further, you must call {@link NativeHandle#dup()}.
     *
     * @return a {@link NativeHandle} instance parsed from the parcel
     * @throws IllegalArgumentException if the parcel has no more data
     */
    public native final NativeHandle readNativeHandle();
    /**
     * Reads an embedded native handle (without duplicating the underlying
     * file descriptors) from the parcel. These file descriptors will only
     * be open for the duration that the binder window is open. If they
     * are needed further, you must call {@link NativeHandle#dup()}. You
     * do not need to call close on the NativeHandle returned from this.
     *
     * @param parentHandle handle from which to read the embedded object
     * @param offset offset into parent
     * @return a {@link NativeHandle} instance parsed from the parcel
     * @throws IllegalArgumentException if the parcel has no more data
     */
    public native final NativeHandle readEmbeddedNativeHandle(
            long parentHandle, long offset);

    /**
     * Reads an array of boolean values from the parcel.
     * @return array of parsed values
     * @throws IllegalArgumentException if the parcel has no more data
     */
    private native final boolean[] readBoolVectorAsArray();
    /**
     * Reads an array of byte values from the parcel.
     * @return array of parsed values
     * @throws IllegalArgumentException if the parcel has no more data
     */
    private native final byte[] readInt8VectorAsArray();
    /**
     * Reads an array of short values from the parcel.
     * @return array of parsed values
     * @throws IllegalArgumentException if the parcel has no more data
     */
    private native final short[] readInt16VectorAsArray();
    /**
     * Reads an array of int values from the parcel.
     * @return array of parsed values
     * @throws IllegalArgumentException if the parcel has no more data
     */
    private native final int[] readInt32VectorAsArray();
    /**
     * Reads an array of long values from the parcel.
     * @return array of parsed values
     * @throws IllegalArgumentException if the parcel has no more data
     */
    private native final long[] readInt64VectorAsArray();
    /**
     * Reads an array of float values from the parcel.
     * @return array of parsed values
     * @throws IllegalArgumentException if the parcel has no more data
     */
    private native final float[] readFloatVectorAsArray();
    /**
     * Reads an array of double values from the parcel.
     * @return array of parsed values
     * @throws IllegalArgumentException if the parcel has no more data
     */
    private native final double[] readDoubleVectorAsArray();
    /**
     * Reads an array of String values from the parcel.
     * @return array of parsed values
     * @throws IllegalArgumentException if the parcel has no more data
     */
    private native final String[] readStringVectorAsArray();
    /**
     * Reads an array of native handles from the parcel.
     * @return array of {@link NativeHandle} objects
     * @throws IllegalArgumentException if the parcel has no more data
     */
    private native final NativeHandle[] readNativeHandleAsArray();

    /**
     * Convenience method to read a Boolean vector as an ArrayList.
     * @return array of parsed values.
     * @throws IllegalArgumentException if the parcel has no more data
     */
    public final ArrayList<Boolean> readBoolVector() {
        Boolean[] array = HwBlob.wrapArray(readBoolVectorAsArray());

        return new ArrayList<Boolean>(Arrays.asList(array));
    }

    /**
     * Convenience method to read a Byte vector as an ArrayList.
     * @return array of parsed values.
     * @throws IllegalArgumentException if the parcel has no more data
     */
    public final ArrayList<Byte> readInt8Vector() {
        Byte[] array = HwBlob.wrapArray(readInt8VectorAsArray());

        return new ArrayList<Byte>(Arrays.asList(array));
    }

    /**
     * Convenience method to read a Short vector as an ArrayList.
     * @return array of parsed values.
     * @throws IllegalArgumentException if the parcel has no more data
     */
    public final ArrayList<Short> readInt16Vector() {
        Short[] array = HwBlob.wrapArray(readInt16VectorAsArray());

        return new ArrayList<Short>(Arrays.asList(array));
    }

    /**
     * Convenience method to read a Integer vector as an ArrayList.
     * @return array of parsed values.
     * @throws IllegalArgumentException if the parcel has no more data
     */
    public final ArrayList<Integer> readInt32Vector() {
        Integer[] array = HwBlob.wrapArray(readInt32VectorAsArray());

        return new ArrayList<Integer>(Arrays.asList(array));
    }

    /**
     * Convenience method to read a Long vector as an ArrayList.
     * @return array of parsed values.
     * @throws IllegalArgumentException if the parcel has no more data
     */
    public final ArrayList<Long> readInt64Vector() {
        Long[] array = HwBlob.wrapArray(readInt64VectorAsArray());

        return new ArrayList<Long>(Arrays.asList(array));
    }

    /**
     * Convenience method to read a Float vector as an ArrayList.
     * @return array of parsed values.
     * @throws IllegalArgumentException if the parcel has no more data
     */
    public final ArrayList<Float> readFloatVector() {
        Float[] array = HwBlob.wrapArray(readFloatVectorAsArray());

        return new ArrayList<Float>(Arrays.asList(array));
    }

    /**
     * Convenience method to read a Double vector as an ArrayList.
     * @return array of parsed values.
     * @throws IllegalArgumentException if the parcel has no more data
     */
    public final ArrayList<Double> readDoubleVector() {
        Double[] array = HwBlob.wrapArray(readDoubleVectorAsArray());

        return new ArrayList<Double>(Arrays.asList(array));
    }

    /**
     * Convenience method to read a String vector as an ArrayList.
     * @return array of parsed values.
     * @throws IllegalArgumentException if the parcel has no more data
     */
    public final ArrayList<String> readStringVector() {
        return new ArrayList<String>(Arrays.asList(readStringVectorAsArray()));
    }

    /**
     * Convenience method to read a vector of native handles as an ArrayList.
     * @return array of {@link NativeHandle} objects.
     * @throws IllegalArgumentException if the parcel has no more data
     */
    public final ArrayList<NativeHandle> readNativeHandleVector() {
        return new ArrayList<NativeHandle>(Arrays.asList(readNativeHandleAsArray()));
    }

    /**
     * Reads a strong binder value from the parcel.
     * @return binder object read from parcel or null if no binder can be read
     * @throws IllegalArgumentException if the parcel has no more data
     */
    public native final IHwBinder readStrongBinder();

    /**
     * Read opaque segment of data as a blob.
     * @return blob of size expectedSize
     * @throws IllegalArgumentException if the parcel has no more data
     */
    public native final HwBlob readBuffer(long expectedSize);

    /**
     * Read a buffer written using scatter gather.
     *
     * @param expectedSize size that buffer should be
     * @param parentHandle handle from which to read the embedded buffer
     * @param offset offset into parent
     * @param nullable whether or not to allow for a null return
     * @return blob of data with size expectedSize
     * @throws NoSuchElementException if an embedded buffer is not available to read
     * @throws IllegalArgumentException if expectedSize < 0
     * @throws NullPointerException if the transaction specified the blob to be null
     *    but nullable is false
     */
    public native final HwBlob readEmbeddedBuffer(
            long expectedSize, long parentHandle, long offset,
            boolean nullable);

    /**
     * Write a buffer into the transaction.
     * @param blob blob to write into the parcel.
     */
    public native final void writeBuffer(HwBlob blob);
    /**
     * Write a status value into the blob.
     * @param status value to write
     */
    public native final void writeStatus(int status);
    /**
     * @throws IllegalArgumentException if a success vaue cannot be read
     * @throws RemoteException if success value indicates a transaction error
     */
    public native final void verifySuccess();
    /**
     * Should be called to reduce memory pressure when this object no longer needs
     * to be written to.
     */
    public native final void releaseTemporaryStorage();
    /**
     * Should be called when object is no longer needed to reduce possible memory
     * pressure if the Java GC does not get to this object in time.
     */
    public native final void release();

    /**
     * Sends the parcel to the specified destination.
     */
    public native final void send();

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

    private native final void native_setup(boolean allocate);

    static {
        long freeFunction = native_init();

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

    private long mNativeContext;
}

