/*
 * Copyright (C) 2019 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.telephony.ims;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.WorkerThread;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

/**
 * This is a single instance of a message sent or received over RCS.
 *
 * @hide
 */
public abstract class RcsMessage {
    /**
     * The value to indicate that this {@link RcsMessage} does not have any location information.
     */
    public static final double LOCATION_NOT_SET = Double.MIN_VALUE;

    /**
     * The status to indicate that this {@link RcsMessage}s status is not set yet.
     */
    public static final int NOT_SET = 0;

    /**
     * The status to indicate that this {@link RcsMessage} is a draft and is not in the process of
     * sending yet.
     */
    public static final int DRAFT = 1;

    /**
     * The status to indicate that this {@link RcsMessage} was successfully sent.
     */
    public static final int QUEUED = 2;

    /**
     * The status to indicate that this {@link RcsMessage} is actively being sent.
     */
    public static final int SENDING = 3;

    /**
     * The status to indicate that this {@link RcsMessage} was successfully sent.
     */
    public static final int SENT = 4;

    /**
     * The status to indicate that this {@link RcsMessage} failed to send in an attempt before, and
     * now being retried.
     */
    public static final int RETRYING = 5;

    /**
     * The status to indicate that this {@link RcsMessage} has permanently failed to send.
     */
    public static final int FAILED = 6;

    /**
     * The status to indicate that this {@link RcsMessage} was successfully received.
     */
    public static final int RECEIVED = 7;

    /**
     * The status to indicate that this {@link RcsMessage} was seen.
     */
    public static final int SEEN = 9;

    /**
     * @hide
     */
    protected final RcsControllerCall mRcsControllerCall;

    /**
     * @hide
     */
    protected final int mId;

    @IntDef({
            DRAFT, QUEUED, SENDING, SENT, RETRYING, FAILED, RECEIVED, SEEN
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface RcsMessageStatus {
    }

    RcsMessage(RcsControllerCall rcsControllerCall, int id) {
        mRcsControllerCall = rcsControllerCall;
        mId = id;
    }

    /**
     * Returns the row Id from the common message.
     *
     * @hide
     */
    public int getId() {
        return mId;
    }

    /**
     * @return Returns the subscription ID that this {@link RcsMessage} was sent from, or delivered
     * to.
     * @throws RcsMessageStoreException if the value could not be read from the storage
     * @see android.telephony.SubscriptionInfo#getSubscriptionId
     */
    public int getSubscriptionId() throws RcsMessageStoreException {
        return mRcsControllerCall.call(
                (iRcs, callingPackage) -> iRcs.getMessageSubId(mId, isIncoming(), callingPackage));
    }

    /**
     * Sets the subscription ID that this {@link RcsMessage} was sent from, or delivered to and
     * persists it into storage.
     *
     * @param subId The subscription ID to persists into storage.
     * @throws RcsMessageStoreException if the value could not be persisted into storage
     * @see android.telephony.SubscriptionInfo#getSubscriptionId
     */
    @WorkerThread
    public void setSubscriptionId(int subId) throws RcsMessageStoreException {
        mRcsControllerCall.callWithNoReturn(
                (iRcs, callingPackage) -> iRcs.setMessageSubId(mId, isIncoming(), subId,
                        callingPackage));
    }

    /**
     * Sets the status of this message and persists it into storage. Please see
     * {@link RcsFileTransferPart#setFileTransferStatus(int)} to set statuses around file transfers.
     *
     * @throws RcsMessageStoreException if the value could not be persisted into storage
     */
    @WorkerThread
    public void setStatus(@RcsMessageStatus int rcsMessageStatus) throws RcsMessageStoreException {
        mRcsControllerCall.callWithNoReturn(
                (iRcs, callingPackage) -> iRcs.setMessageStatus(mId, isIncoming(), rcsMessageStatus,
                        callingPackage));
    }

    /**
     * @return Returns the status of this message. Please see
     * {@link RcsFileTransferPart#setFileTransferStatus(int)} to set statuses around file transfers.
     * @throws RcsMessageStoreException if the value could not be read from the storage
     */
    @WorkerThread
    public @RcsMessageStatus int getStatus() throws RcsMessageStoreException {
        return mRcsControllerCall.call(
                (iRcs, callingPackage) -> iRcs.getMessageStatus(mId, isIncoming(), callingPackage));
    }

    /**
     * Sets the origination timestamp of this message and persists it into storage. Origination is
     * defined as when the sender tapped the send button.
     *
     * @param timestamp The origination timestamp value in milliseconds passed after midnight,
     *                  January 1, 1970 UTC
     * @throws RcsMessageStoreException if the value could not be persisted into storage
     */
    @WorkerThread
    public void setOriginationTimestamp(long timestamp) throws RcsMessageStoreException {
        mRcsControllerCall.callWithNoReturn(
                (iRcs, callingPackage) -> iRcs.setMessageOriginationTimestamp(mId, isIncoming(),
                        timestamp, callingPackage));
    }

    /**
     * @return Returns the origination timestamp of this message in milliseconds passed after
     * midnight, January 1, 1970 UTC. Origination is defined as when the sender tapped the send
     * button.
     * @throws RcsMessageStoreException if the value could not be read from the storage
     */
    @WorkerThread
    public long getOriginationTimestamp() throws RcsMessageStoreException {
        return mRcsControllerCall.call(
                (iRcs, callingPackage) -> iRcs.getMessageOriginationTimestamp(mId, isIncoming(),
                        callingPackage));
    }

    /**
     * Sets the globally unique RCS message identifier for this message and persists it into
     * storage. This function does not confirm that this message id is unique. Please see 4.4.5.2
     * - GSMA RCC.53 (RCS Device API 1.6 Specification
     *
     * @param rcsMessageGlobalId The globally RCS message identifier
     * @throws RcsMessageStoreException if the value could not be persisted into storage
     */
    @WorkerThread
    public void setRcsMessageId(String rcsMessageGlobalId) throws RcsMessageStoreException {
        mRcsControllerCall.callWithNoReturn(
                (iRcs, callingPackage) -> iRcs.setGlobalMessageIdForMessage(mId, isIncoming(),
                        rcsMessageGlobalId, callingPackage));
    }

    /**
     * @return Returns the globally unique RCS message identifier for this message. Please see
     * 4.4.5.2 - GSMA RCC.53 (RCS Device API 1.6 Specification
     * @throws RcsMessageStoreException if the value could not be read from the storage
     */
    @WorkerThread
    public String getRcsMessageId() throws RcsMessageStoreException {
        return mRcsControllerCall.call(
                (iRcs, callingPackage) -> iRcs.getGlobalMessageIdForMessage(mId, isIncoming(),
                        callingPackage));
    }

    /**
     * @return Returns the user visible text included in this message.
     * @throws RcsMessageStoreException if the value could not be read from the storage
     */
    @WorkerThread
    public String getText() throws RcsMessageStoreException {
        return mRcsControllerCall.call(
                (iRcs, callingPackage) -> iRcs.getTextForMessage(mId, isIncoming(),
                        callingPackage));
    }

    /**
     * Sets the user visible text for this message and persists in storage.
     *
     * @param text The text this message now has
     * @throws RcsMessageStoreException if the value could not be persisted into storage
     */
    @WorkerThread
    public void setText(String text) throws RcsMessageStoreException {
        mRcsControllerCall.callWithNoReturn(
                (iRcs, callingPackage) -> iRcs.setTextForMessage(mId, isIncoming(), text,
                        callingPackage));
    }

    /**
     * @return Returns the associated latitude for this message, or
     * {@link RcsMessage#LOCATION_NOT_SET} if it does not contain a location.
     * @throws RcsMessageStoreException if the value could not be read from the storage
     */
    @WorkerThread
    public double getLatitude() throws RcsMessageStoreException {
        return mRcsControllerCall.call(
                (iRcs, callingPackage) -> iRcs.getLatitudeForMessage(mId, isIncoming(),
                        callingPackage));
    }

    /**
     * Sets the latitude for this message and persists in storage.
     *
     * @param latitude The latitude for this location message.
     * @throws RcsMessageStoreException if the value could not be persisted into storage
     */
    @WorkerThread
    public void setLatitude(double latitude) throws RcsMessageStoreException {
        mRcsControllerCall.callWithNoReturn(
                (iRcs, callingPackage) -> iRcs.setLatitudeForMessage(mId, isIncoming(), latitude,
                        callingPackage));
    }

    /**
     * @return Returns the associated longitude for this message, or
     * {@link RcsMessage#LOCATION_NOT_SET} if it does not contain a location.
     * @throws RcsMessageStoreException if the value could not be read from the storage
     */
    @WorkerThread
    public double getLongitude() throws RcsMessageStoreException {
        return mRcsControllerCall.call(
                (iRcs, callingPackage) -> iRcs.getLongitudeForMessage(mId, isIncoming(),
                        callingPackage));
    }

    /**
     * Sets the longitude for this message and persists in storage.
     *
     * @param longitude The longitude for this location message.
     * @throws RcsMessageStoreException if the value could not be persisted into storage
     */
    @WorkerThread
    public void setLongitude(double longitude) throws RcsMessageStoreException {
        mRcsControllerCall.callWithNoReturn(
                (iRcs, callingPackage) -> iRcs.setLongitudeForMessage(mId, isIncoming(), longitude,
                        callingPackage));
    }

    /**
     * Attaches an {@link RcsFileTransferPart} to this message and persists into storage.
     *
     * @param fileTransferCreationParameters The parameters to be used to create the
     *                                       {@link RcsFileTransferPart}
     * @return A new instance of {@link RcsFileTransferPart}
     * @throws RcsMessageStoreException if the file transfer could not be persisted into storage.
     */
    @NonNull
    @WorkerThread
    public RcsFileTransferPart insertFileTransfer(
            RcsFileTransferCreationParams fileTransferCreationParameters)
            throws RcsMessageStoreException {
        return new RcsFileTransferPart(mRcsControllerCall, mRcsControllerCall.call(
                (iRcs, callingPackage) -> iRcs.storeFileTransfer(mId, isIncoming(),
                        fileTransferCreationParameters, callingPackage)));
    }

    /**
     * @return Returns all the {@link RcsFileTransferPart}s associated with this message in an
     * unmodifiable set.
     * @throws RcsMessageStoreException if the file transfers could not be read from the storage
     */
    @NonNull
    @WorkerThread
    public Set<RcsFileTransferPart> getFileTransferParts() throws RcsMessageStoreException {
        Set<RcsFileTransferPart> fileTransferParts = new HashSet<>();

        int[] fileTransferIds = mRcsControllerCall.call(
                (iRcs, callingPackage) -> iRcs.getFileTransfersAttachedToMessage(mId, isIncoming(),
                        callingPackage));

        for (int fileTransfer : fileTransferIds) {
            fileTransferParts.add(new RcsFileTransferPart(mRcsControllerCall, fileTransfer));
        }

        return Collections.unmodifiableSet(fileTransferParts);
    }

    /**
     * Removes a {@link RcsFileTransferPart} from this message, and deletes it in storage.
     *
     * @param fileTransferPart The part to delete.
     * @throws RcsMessageStoreException if the file transfer could not be removed from storage
     */
    @WorkerThread
    public void removeFileTransferPart(@NonNull RcsFileTransferPart fileTransferPart)
            throws RcsMessageStoreException {
        if (fileTransferPart == null) {
            return;
        }

        mRcsControllerCall.callWithNoReturn(
                (iRcs, callingPackage) -> iRcs.deleteFileTransfer(fileTransferPart.getId(),
                        callingPackage));
    }

    /**
     * @return Returns {@code true} if this message was received on this device, {@code false} if it
     * was sent.
     */
    public abstract boolean isIncoming();
}
