/*
 * Copyright (C) 2020 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.SuppressLint;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.ArraySet;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
import java.util.Set;

/**
 * Contains the full state of the IMS feature tags associated with a SipDelegate and managed by the
 * ImsService.
 * @hide
 */
@SystemApi
public final class DelegateRegistrationState implements Parcelable {

    /**
     * This feature tag has been deregistered for an unknown reason. Outgoing out-of-dialog SIP
     * messages associated with feature tags that are not registered will fail.
     */
    public static final int DEREGISTERED_REASON_UNKNOWN = 0;

    /**
     * This feature tag has been deregistered because it is not provisioned to be used on this radio
     * access technology or PDN. Outgoing out-of-dialog SIP messages associated with feature tags
     * that are not registered will fail.
     * <p>
     * There may be new incoming SIP dialog requests on a feature that that is not provisioned. It
     * is still expected that the SipDelegateConnection responds to the request.
     */
    public static final int DEREGISTERED_REASON_NOT_PROVISIONED = 1;

    /**
     * This feature tag has been deregistered because IMS has been deregistered. All outgoing SIP
     * messages will fail until IMS registration occurs.
     */
    public static final int DEREGISTERED_REASON_NOT_REGISTERED = 2;

    /**
     * This feature tag is being deregistered because the PDN that the IMS registration is on is
     *changing.
     * All open SIP dialogs need to be closed before the PDN change can proceed using
     * {@link SipDelegateConnection#closeDialog(String)}.
     */
    public static final int DEREGISTERING_REASON_PDN_CHANGE = 3;

    /**
     * This feature tag is being deregistered due to a provisioning change. This can be triggered by
     * many things, such as a provisioning change triggered by the carrier network, a radio access
     * technology change by the modem causing a different set of feature tags to be provisioned, or
     * a user triggered hange, such as data being enabled/disabled.
     * <p>
     * All open SIP dialogs associated with the new deprovisioned feature tag need to be closed
     * using {@link SipDelegateConnection#closeDialog(String)} before the IMS registration
     * modification can proceed.
     */
    public static final int DEREGISTERING_REASON_PROVISIONING_CHANGE = 4;

    /**
     * This feature tag is deregistering because the SipDelegate associated with this feature tag
     * needs to change its supported feature set.
     * <p>
     * All open SIP Dialogs associated with this feature tag must be  closed
     * using {@link SipDelegateConnection#closeDialog(String)} before this operation can proceed.
     */
    public static final int DEREGISTERING_REASON_FEATURE_TAGS_CHANGING = 5;

    /**
     * This feature tag is deregistering because the SipDelegate is in the process of being
     * destroyed.
     * <p>
     * All open SIP Dialogs associated with this feature tag must be closed
     * using {@link SipDelegateConnection#closeDialog(String)} before this operation can proceed.
     */
    public static final int DEREGISTERING_REASON_DESTROY_PENDING = 6;

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = "DEREGISTERED_REASON_", value = {
            DEREGISTERED_REASON_UNKNOWN,
            DEREGISTERED_REASON_NOT_PROVISIONED,
            DEREGISTERED_REASON_NOT_REGISTERED
    })
    public @interface DeregisteredReason {}


    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = "DEREGISTERING_REASON_", value = {
            DEREGISTERING_REASON_PDN_CHANGE,
            DEREGISTERING_REASON_PROVISIONING_CHANGE,
            DEREGISTERING_REASON_FEATURE_TAGS_CHANGING,
            DEREGISTERING_REASON_DESTROY_PENDING
    })
    public @interface DeregisteringReason {}

    private ArraySet<String> mRegisteredTags = new ArraySet<>();
    private final ArraySet<FeatureTagState> mDeregisteringTags = new ArraySet<>();
    private final ArraySet<FeatureTagState> mDeregisteredTags = new ArraySet<>();

    /**
     * Builder used to create new instances of {@link DelegateRegistrationState}.
     */
    public static final class Builder {

        private final DelegateRegistrationState mState;

        /* Create a new instance of {@link Builder} */
        public Builder() {
            mState = new DelegateRegistrationState();
        }

        /**
         * Add a feature tag that is currently included in the current network IMS Registration.
         * @param featureTag The IMS media feature tag included in the current IMS registration.
         * @return The in-progress Builder instance for RegistrationState.
         */
        public @NonNull Builder addRegisteredFeatureTag(@NonNull String featureTag) {
            mState.mRegisteredTags.add(featureTag);
            return this;
        }

        /**
         * Add a list of feature tags that are currently included in the current network IMS
         * Registration.
         * @param featureTags The IMS media feature tags included in the current IMS registration.
         * @return The in-progress Builder instance for RegistrationState.
         */
        @SuppressLint("MissingGetterMatchingBuilder")
        public @NonNull Builder addRegisteredFeatureTags(@NonNull Set<String> featureTags) {
            mState.mRegisteredTags.addAll(featureTags);
            return this;
        }

        /**
         * Add a feature tag that is in the current network IMS Registration, but is in the progress
         * of being deregistered and requires action from the RCS application before the IMS
         * registration can be modified.
         *
         * See {@link DeregisteringReason} for more information regarding what is required by the
         * RCS application to proceed.
         *
         * @param featureTag The media feature tag that has limited or no availability due to its
         *         current deregistering state.
         * @param reason The reason why the media feature tag has moved to the deregistering state.
         *         The availability of the feature tag depends on the {@link DeregisteringReason}.
         * @return The in-progress Builder instance for RegistrationState.
         */
        public @NonNull Builder addDeregisteringFeatureTag(@NonNull String featureTag,
                @DeregisteringReason int reason) {
            mState.mDeregisteringTags.add(new FeatureTagState(featureTag, reason));
            return this;
        }

        /**
         * Add a feature tag that is currently not included in the network RCS registration. See
         * {@link DeregisteredReason} for more information regarding the reason for why the feature
         * tag is not registered.
         * @param featureTag The media feature tag that is not registered.
         * @param reason The reason why the media feature tag has been deregistered.
         * @return The in-progress Builder instance for RegistrationState.
         */
        public @NonNull Builder addDeregisteredFeatureTag(@NonNull String featureTag,
                @DeregisteredReason int reason) {
            mState.mDeregisteredTags.add(new FeatureTagState(featureTag, reason));
            return this;
        }

        /**
         * @return the finalized instance.
         */
        public @NonNull DelegateRegistrationState build() {
            return mState;
        }
    }

    /**
     * The builder should be used to construct a new instance of this class.
     */
    private DelegateRegistrationState() {}

    /**
     * Used for unparcelling only.
     */
    private DelegateRegistrationState(Parcel source) {
        mRegisteredTags = (ArraySet<String>) source.readArraySet(null);
        readStateFromParcel(source, mDeregisteringTags);
        readStateFromParcel(source, mDeregisteredTags);
    }

    /**
     * Get the feature tags that this SipDelegate is associated with that are currently part of the
     * network IMS registration. SIP Messages both in and out of a SIP Dialog may be sent and
     * received using these feature tags.
     * @return A Set of feature tags that the SipDelegate has associated with that are included in
     * the network IMS registration.
     */
    public @NonNull Set<String> getRegisteredFeatureTags() {
        return new ArraySet<>(mRegisteredTags);
    }

    /**
     * Get the feature tags that this SipDelegate is associated with that are currently part of the
     * network IMS registration but are in the process of being deregistered.
     * <p>
     * Any incoming SIP messages associated with a feature tag included in this list will still be
     * delivered. Outgoing SIP messages that are still in-dialog will be delivered to the
     * SipDelegate, but outgoing out-of-dialog SIP messages with  a feature tag that is included in
     * this list will fail.
     * <p>
     * The SipDelegate will stay in this state for a limited period of time while it waits for the
     * RCS application to perform a specific action. More details on the actions that can cause this
     * state as well as the expected response are included in the reason codes and can be found in
     * {@link DeregisteringReason}.
     * @return A Set of feature tags that the SipDelegate has associated with that are included in
     * the network IMS registration but are in the process of deregistering.
     */
    public @NonNull Set<FeatureTagState> getDeregisteringFeatureTags() {
        return new ArraySet<>(mDeregisteringTags);
    }

    /**
     * Get the list of feature tags that are associated with this SipDelegate but are not currently
     * included in the network IMS registration.
     * <p>
     * See {@link DeregisteredReason} codes for more information related to the reasons why this may
     * occur.
     * <p>
     * Due to network race conditions, there may still be onditions where an incoming out-of-dialog
     * SIP message is delivered for a feature tag that is considered deregistered. Due to this
     * condition, in-dialog outgoing SIP messages for deregistered feature tags will still be
     * allowed as long as they are in response to a dialog started by a remote party. Any outgoing
     * out-of-dialog SIP messages associated with feature tags included in this list will fail to be
     * sent.
     * @return A list of feature tags that the SipDelegate has associated with that not included in
     * the network IMS registration.
     */
    public @NonNull Set<FeatureTagState> getDeregisteredFeatureTags() {
        return new ArraySet<>(mDeregisteredTags);
    }


    public static final @NonNull Creator<DelegateRegistrationState> CREATOR =
            new Creator<DelegateRegistrationState>() {
        @Override
        public DelegateRegistrationState createFromParcel(Parcel source) {
            return new DelegateRegistrationState(source);
        }

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

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

    @Override
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        dest.writeArraySet(mRegisteredTags);
        writeStateToParcel(dest, mDeregisteringTags);
        writeStateToParcel(dest, mDeregisteredTags);
    }

    private void writeStateToParcel(Parcel dest, Set<FeatureTagState> state) {
        dest.writeInt(state.size());
        for (FeatureTagState s : state) {
            dest.writeString(s.getFeatureTag());
            dest.writeInt(s.getState());
        }
    }

    private void readStateFromParcel(Parcel source, Set<FeatureTagState> emptyState) {
        int len = source.readInt();
        for (int i = 0; i < len; i++) {
            String ft = source.readString();
            int reason = source.readInt();

            emptyState.add(new FeatureTagState(ft, reason));
        }
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        DelegateRegistrationState that = (DelegateRegistrationState) o;
        return mRegisteredTags.equals(that.mRegisteredTags)
                && mDeregisteringTags.equals(that.mDeregisteringTags)
                && mDeregisteredTags.equals(that.mDeregisteredTags);
    }

    @Override
    public int hashCode() {
        return Objects.hash(mRegisteredTags, mDeregisteringTags, mDeregisteredTags);
    }

    @Override
    public String toString() {
        return "DelegateRegistrationState{ registered={" + mRegisteredTags
                + "}, deregistering={" + mDeregisteringTags + "}, deregistered={"
                + mDeregisteredTags + "}}";
    }
}
