/*
 * Copyright (C) 2018 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;

import android.annotation.IntDef;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.TelephonyManager.NetworkType;

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

/**
 * @hide
 */
public final class PhysicalChannelConfig implements Parcelable {

    // TODO(b/72993578) consolidate these enums in a central location.
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({CONNECTION_PRIMARY_SERVING, CONNECTION_SECONDARY_SERVING, CONNECTION_UNKNOWN})
    public @interface ConnectionStatus {}

    /**
     * UE has connection to cell for signalling and possibly data (3GPP 36.331, 25.331).
     */
    public static final int CONNECTION_PRIMARY_SERVING = 1;

    /**
     * UE has connection to cell for data (3GPP 36.331, 25.331).
     */
    public static final int CONNECTION_SECONDARY_SERVING = 2;

    /** Connection status is unknown. */
    public static final int CONNECTION_UNKNOWN = Integer.MAX_VALUE;

    /**
     * Connection status of the cell.
     *
     * <p>One of {@link #CONNECTION_PRIMARY_SERVING}, {@link #CONNECTION_SECONDARY_SERVING}.
     */
    @ConnectionStatus
    private int mCellConnectionStatus;

    /**
     * Cell bandwidth, in kHz.
     */
    private int mCellBandwidthDownlinkKhz;

    /**
     * The radio technology for this physical channel.
     */
    @NetworkType
    private int mRat;

    /**
     * The rough frequency range for this physical channel.
     */
    @ServiceState.FrequencyRange
    private int mFrequencyRange;

    /**
     * The absolute radio frequency channel number, {@link Integer#MAX_VALUE} if unknown.
     */
    private int mChannelNumber;

    /**
     * A list of data calls mapped to this physical channel. An empty list means the physical
     * channel has no data call mapped to it.
     */
    private int[] mContextIds;

    /**
     * The physical cell identifier for this cell - PCI, PSC, {@link Integer#MAX_VALUE} if known.
     */
    private int mPhysicalCellId;

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mCellConnectionStatus);
        dest.writeInt(mCellBandwidthDownlinkKhz);
        dest.writeInt(mRat);
        dest.writeInt(mChannelNumber);
        dest.writeInt(mFrequencyRange);
        dest.writeIntArray(mContextIds);
        dest.writeInt(mPhysicalCellId);
    }

    /**
     * @return Cell bandwidth, in kHz
     */
    public int getCellBandwidthDownlink() {
        return mCellBandwidthDownlinkKhz;
    }

    /**
     * Get the list of data call ids mapped to this physical channel. This list is sorted into
     * ascending numerical order. Each id in this list must match the id in
     * {@link com.android.internal.telephony.dataconnection.DataConnection}. An empty list means the
     * physical channel has no data call mapped to it.
     *
     * @return an integer list indicates the data call ids.
     */
    public int[] getContextIds() {
        return mContextIds;
    }

    /**
     * @return the rough frequency range for this physical channel.
     * @see {@link ServiceState#FREQUENCY_RANGE_LOW}
     * @see {@link ServiceState#FREQUENCY_RANGE_MID}
     * @see {@link ServiceState#FREQUENCY_RANGE_HIGH}
     * @see {@link ServiceState#FREQUENCY_RANGE_MMWAVE}
     */
    @ServiceState.FrequencyRange
    public int getFrequencyRange() {
        return mFrequencyRange;
    }

    /**
     * @return the absolute radio frequency channel number for this physical channel,
     * {@link Integer#MAX_VALUE} if unknown.
     */
    public int getChannelNumber() {
        return mChannelNumber;
    }

    /**
     * In UTRAN, this value is primary scrambling code. The range is [0, 511].
     * Reference: 3GPP TS 25.213 section 5.2.2.
     *
     * In EUTRAN, this value is physical layer cell identity. The range is [0, 503].
     * Reference: 3GPP TS 36.211 section 6.11.
     *
     * In 5G RAN, this value is physical layer cell identity. The range is [0, 1008].
     * Reference: 3GPP TS 38.211 section 7.4.2.1.
     *
     * @return the physical cell identifier for this cell, {@link Integer#MAX_VALUE} if unknown.
     */
    public int getPhysicalCellId() {
        return mPhysicalCellId;
    }

    /**The radio technology for this physical channel. */
    @NetworkType
    public int getRat() {
        return mRat;
    }

    /**
     * Gets the connection status of the cell.
     *
     * @see #CONNECTION_PRIMARY_SERVING
     * @see #CONNECTION_SECONDARY_SERVING
     * @see #CONNECTION_UNKNOWN
     *
     * @return Connection status of the cell
     */
    @ConnectionStatus
    public int getConnectionStatus() {
        return mCellConnectionStatus;
    }

    /** @return String representation of the connection status */
    private String getConnectionStatusString() {
        switch(mCellConnectionStatus) {
            case CONNECTION_PRIMARY_SERVING:
                return "PrimaryServing";
            case CONNECTION_SECONDARY_SERVING:
                return "SecondaryServing";
            case CONNECTION_UNKNOWN:
                return "Unknown";
            default:
                return "Invalid(" + mCellConnectionStatus + ")";
        }
    }

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

        if (!(o instanceof PhysicalChannelConfig)) {
            return false;
        }

        PhysicalChannelConfig config = (PhysicalChannelConfig) o;
        return mCellConnectionStatus == config.mCellConnectionStatus
                && mCellBandwidthDownlinkKhz == config.mCellBandwidthDownlinkKhz
                && mRat == config.mRat
                && mFrequencyRange == config.mFrequencyRange
                && mChannelNumber == config.mChannelNumber
                && mPhysicalCellId == config.mPhysicalCellId
                && Arrays.equals(mContextIds, config.mContextIds);
    }

    @Override
    public int hashCode() {
        return Objects.hash(
                mCellConnectionStatus, mCellBandwidthDownlinkKhz, mRat, mFrequencyRange,
                mChannelNumber, mPhysicalCellId, mContextIds);
    }

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

            public PhysicalChannelConfig[] newArray(int size) {
                return new PhysicalChannelConfig[size];
            }
        };

    @Override
    public String toString() {
        return new StringBuilder()
                .append("{mConnectionStatus=")
                .append(getConnectionStatusString())
                .append(",mCellBandwidthDownlinkKhz=")
                .append(mCellBandwidthDownlinkKhz)
                .append(",mRat=")
                .append(mRat)
                .append(",mFrequencyRange=")
                .append(mFrequencyRange)
                .append(",mChannelNumber=")
                .append(mChannelNumber)
                .append(",mContextIds=")
                .append(mContextIds.toString())
                .append(",mPhysicalCellId=")
                .append(mPhysicalCellId)
                .append("}")
                .toString();
    }

    private PhysicalChannelConfig(Parcel in) {
        mCellConnectionStatus = in.readInt();
        mCellBandwidthDownlinkKhz = in.readInt();
        mRat = in.readInt();
        mChannelNumber = in.readInt();
        mFrequencyRange = in.readInt();
        mContextIds = in.createIntArray();
        mPhysicalCellId = in.readInt();
    }

    private PhysicalChannelConfig(Builder builder) {
        mCellConnectionStatus = builder.mCellConnectionStatus;
        mCellBandwidthDownlinkKhz = builder.mCellBandwidthDownlinkKhz;
        mRat = builder.mRat;
        mChannelNumber = builder.mChannelNumber;
        mFrequencyRange = builder.mFrequencyRange;
        mContextIds = builder.mContextIds;
        mPhysicalCellId = builder.mPhysicalCellId;
    }

    /** The builder of {@code PhysicalChannelConfig}. */
    public static final class Builder {
        private int mRat;
        private int mFrequencyRange;
        private int mChannelNumber;
        private int mCellBandwidthDownlinkKhz;
        private int mCellConnectionStatus;
        private int[] mContextIds;
        private int mPhysicalCellId;

        /** @hide */
        public Builder() {
            mRat = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
            mFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN;
            mChannelNumber = Integer.MAX_VALUE;
            mCellBandwidthDownlinkKhz = 0;
            mCellConnectionStatus = CONNECTION_UNKNOWN;
            mContextIds = new int[0];
            mPhysicalCellId = Integer.MAX_VALUE;
        }

        /** @hide */
        public PhysicalChannelConfig build() {
            return new PhysicalChannelConfig(this);
        }

        /** @hide */
        public Builder setRat(int rat) {
            this.mRat = rat;
            return this;
        }

        /** @hide */
        public Builder setFrequencyRange(int frequencyRange) {
            this.mFrequencyRange = frequencyRange;
            return this;
        }

        /** @hide */
        public Builder setChannelNumber(int channelNumber) {
            this.mChannelNumber = channelNumber;
            return this;
        }

        /** @hide */
        public Builder setCellBandwidthDownlinkKhz(int cellBandwidthDownlinkKhz) {
            this.mCellBandwidthDownlinkKhz = cellBandwidthDownlinkKhz;
            return this;
        }

        /** @hide */
        public Builder setCellConnectionStatus(int connectionStatus) {
            this.mCellConnectionStatus = connectionStatus;
            return this;
        }

        /** @hide */
        public Builder setContextIds(int[] contextIds) {
            if (contextIds != null) Arrays.sort(contextIds);
            this.mContextIds = contextIds;
            return this;
        }

        /** @hide */
        public Builder setPhysicalCellId(int physicalCellId) {
            this.mPhysicalCellId = physicalCellId;
            return this;
        }
    }
}
