/*
 * Copyright 2017 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.hardware.location;

import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;

import libcore.util.HexEncoding;

import java.util.Arrays;

/**
 * A class describing messages send to or from nanoapps through the Context Hub Service.
 *
 * The basis of the class is in the IContextHub.hal ContextHubMsg definition.
 *
 * @hide
 */
@SystemApi
public final class NanoAppMessage implements Parcelable {
    private static final int DEBUG_LOG_NUM_BYTES = 16;
    private long mNanoAppId;
    private int mMessageType;
    private byte[] mMessageBody;
    private boolean mIsBroadcasted;

    private NanoAppMessage(
            long nanoAppId, int messageType, byte[] messageBody, boolean broadcasted) {
        mNanoAppId = nanoAppId;
        mMessageType = messageType;
        mMessageBody = messageBody;
        mIsBroadcasted = broadcasted;
    }

    /**
     * Creates a NanoAppMessage object to send to a nanoapp.
     *
     * This factory method can be used to generate a NanoAppMessage object to be used in
     * the ContextHubClient.sendMessageToNanoApp API.
     *
     * @param targetNanoAppId the ID of the nanoapp to send the message to
     * @param messageType the nanoapp-dependent message type
     * @param messageBody the byte array message contents
     *
     * @return the NanoAppMessage object
     */
    public static NanoAppMessage createMessageToNanoApp(
            long targetNanoAppId, int messageType, byte[] messageBody) {
        return new NanoAppMessage(
                targetNanoAppId, messageType, messageBody, false /* broadcasted */);
    }

    /**
     * Creates a NanoAppMessage object sent from a nanoapp.
     *
     * This factory method is intended only to be used by the Context Hub Service when delivering
     * messages from a nanoapp to clients.
     *
     * @param sourceNanoAppId the ID of the nanoapp that the message was sent from
     * @param messageType the nanoapp-dependent message type
     * @param messageBody the byte array message contents
     * @param broadcasted {@code true} if the message was broadcasted, {@code false} otherwise
     *
     * @return the NanoAppMessage object
     */
    public static NanoAppMessage createMessageFromNanoApp(
            long sourceNanoAppId, int messageType, byte[] messageBody, boolean broadcasted) {
        return new NanoAppMessage(sourceNanoAppId, messageType, messageBody, broadcasted);
    }

    /**
     * @return the ID of the source or destination nanoapp
     */
    public long getNanoAppId() {
        return mNanoAppId;
    }

    /**
     * @return the type of the message that is nanoapp-dependent
     */
    public int getMessageType() {
        return mMessageType;
    }

    /**
     * @return the byte array contents of the message
     */
    public byte[] getMessageBody() {
        return mMessageBody;
    }

    /**
     * @return {@code true} if the message is broadcasted, {@code false} otherwise
     */
    public boolean isBroadcastMessage() {
        return mIsBroadcasted;
    }

    private NanoAppMessage(Parcel in) {
        mNanoAppId = in.readLong();
        mIsBroadcasted = (in.readInt() == 1);
        mMessageType = in.readInt();

        int msgSize = in.readInt();
        mMessageBody = new byte[msgSize];
        in.readByteArray(mMessageBody);
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeLong(mNanoAppId);
        out.writeInt(mIsBroadcasted ? 1 : 0);
        out.writeInt(mMessageType);

        out.writeInt(mMessageBody.length);
        out.writeByteArray(mMessageBody);
    }

    public static final @android.annotation.NonNull Creator<NanoAppMessage> CREATOR =
            new Creator<NanoAppMessage>() {
                @Override
                public NanoAppMessage createFromParcel(Parcel in) {
                    return new NanoAppMessage(in);
                }

                @Override
                public NanoAppMessage[] newArray(int size) {
                    return new NanoAppMessage[size];
                }
            };

    @Override
    public String toString() {
        int length = mMessageBody.length;

        String ret = "NanoAppMessage[type = " + mMessageType + ", length = " + mMessageBody.length
                + " bytes, " + (mIsBroadcasted ? "broadcast" : "unicast") + ", nanoapp = 0x"
                + Long.toHexString(mNanoAppId) + "](";
        if (length > 0) {
            ret += "data = 0x";
        }
        for (int i = 0; i < Math.min(length, DEBUG_LOG_NUM_BYTES); i++) {
            ret += HexEncoding.encodeToString(mMessageBody[i], true /* upperCase */);

            if ((i + 1) % 4 == 0) {
                ret += " ";
            }
        }
        if (length > DEBUG_LOG_NUM_BYTES) {
            ret += "...";
        }
        ret += ")";

        return ret;
    }

    @Override
    public boolean equals(@Nullable Object object) {
        if (object == this) {
            return true;
        }

        boolean isEqual = false;
        if (object instanceof NanoAppMessage) {
            NanoAppMessage other = (NanoAppMessage) object;
            isEqual = (other.getNanoAppId() == mNanoAppId)
                    && (other.getMessageType() == mMessageType)
                    && (other.isBroadcastMessage() == mIsBroadcasted)
                    && Arrays.equals(other.getMessageBody(), mMessageBody);
        }

        return isEqual;
    }
}
