/*
 * 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.annotation.IntRange;
import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.Annotation.NetworkType;

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

public final class PhysicalChannelConfig implements Parcelable {
    // TODO(b/72993578) consolidate these enums in a central location.
    /** @hide */
    @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).
     *
     * @deprecated Use {@link  CellInfo#CONNECTION_PRIMARY_SERVING} instead.
     */
    @Deprecated
    public static final int CONNECTION_PRIMARY_SERVING = 1;

    /**
     * UE has connection to cell for data (3GPP 36.331, 25.331).
     *
     * @deprecated Use {@link  CellInfo#CONNECTION_SECONDARY_SERVING} instead.
     */
    @Deprecated
    public static final int CONNECTION_SECONDARY_SERVING = 2;

    /**
     * Connection status is unknown.
     *
     * @deprecated Use {@link  CellInfo#CONNECTION_UNKNOWN} instead.
     */
    @Deprecated
    public static final int CONNECTION_UNKNOWN = -1;

    /** Channel number is unknown. */
    public static final int CHANNEL_NUMBER_UNKNOWN = Integer.MAX_VALUE;

    /** Physical Cell Id is unknown. */
    public static final int PHYSICAL_CELL_ID_UNKNOWN = -1;

    /** Physical Cell Id's maximum value is 1007. */
    public static final int PHYSICAL_CELL_ID_MAXIMUM_VALUE = 1007;

    /** Cell bandwidth is unknown. */
    public static final int CELL_BANDWIDTH_UNKNOWN = 0;

    /** The frequency is unknown. */
    public static final int FREQUENCY_UNKNOWN = -1;

    /** The band is unknown. */
    public static final int BAND_UNKNOWN = 0;

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

    /**
     * Downlink cell bandwidth, in kHz.
     */
    private int mCellBandwidthDownlinkKhz;

    /**
     * Uplink cell bandwidth, in kHz.
     */
    private int mCellBandwidthUplinkKhz;

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

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

    /**
     * The frequency of Downlink.
     */
    private int mDownlinkFrequency;

    /**
     * The frequency of Uplink.
     */
    private int mUplinkFrequency;

    /**
     * Downlink Absolute Radio Frequency Channel Number
     */
    private int mDownlinkChannelNumber;

    /**
     * Uplink Absolute Radio Frequency Channel Number
     */
    private int mUplinkChannelNumber;

    /**
     * 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 #PHYSICAL_CELL_ID_UNKNOWN}
     * if unknown.
     */
    private int mPhysicalCellId;

    /**
     * This is the band which is being used.
     */
    private int mBand;

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

    @Override
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        dest.writeInt(mCellConnectionStatus);
        dest.writeInt(mCellBandwidthDownlinkKhz);
        dest.writeInt(mCellBandwidthUplinkKhz);
        dest.writeInt(mNetworkType);
        dest.writeInt(mDownlinkChannelNumber);
        dest.writeInt(mUplinkChannelNumber);
        dest.writeInt(mFrequencyRange);
        dest.writeIntArray(mContextIds);
        dest.writeInt(mPhysicalCellId);
        dest.writeInt(mBand);
    }

    /**
     * @return Downlink cell bandwidth in kHz, {@link #CELL_BANDWIDTH_UNKNOWN} if unknown.
     */
    @IntRange(from = 1)
    public int getCellBandwidthDownlinkKhz() {
        return mCellBandwidthDownlinkKhz;
    }

    /**
     * @return Uplink cell bandwidth in kHz, {@link #CELL_BANDWIDTH_UNKNOWN} if unknown.
     */
    @IntRange(from = 1)
    public int getCellBandwidthUplinkKhz() {
        return mCellBandwidthUplinkKhz;
    }

    /**
     * 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,
     * @hide
     */
    public int[] getContextIds() {
        return mContextIds;
    }

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

    /**
     * @return Downlink Absolute Radio Frequency Channel Number,
     * {@link #CHANNEL_NUMBER_UNKNOWN} if unknown.
     */
    @IntRange(from = 0)
    public int getDownlinkChannelNumber() {
        return mDownlinkChannelNumber;
    }

    /**
     * @return Uplink Absolute Radio Frequency Channel Number,
     * {@link #CHANNEL_NUMBER_UNKNOWN} if unknown.
     */
    @IntRange(from = 0)
    public int getUplinkChannelNumber() {
        return mUplinkChannelNumber;
    }

    /**
     * The valid bands are {@link AccessNetworkConstants.GeranBand},
     * {@link AccessNetworkConstants.UtranBand}, {@link AccessNetworkConstants.EutranBand} and
     * {@link AccessNetworkConstants.NgranBands}.
     *
     * @return the frequency band, {@link #BAND_UNKNOWN} if unknown. */
    @IntRange(from = 1, to = 261)
    public int getBand() {
        return mBand;
    }

    /**
     * @return The downlink frequency in kHz, {@link #FREQUENCY_UNKNOWN} if unknown.
     */
    @IntRange(from = 0)
    public int getDownlinkFrequencyKhz() {
        return mDownlinkFrequency;
    }

    /**
     * @return The uplink frequency in kHz, {@link #FREQUENCY_UNKNOWN} if unknown.
     */
    @IntRange(from = 0)
    public int getUplinkFrequencyKhz() {
        return mUplinkFrequency;
    }

    /**
     * The physical cell ID which differentiates cells using the same radio channel.
     *
     * In GERAN, this value is the BSIC. The range is [0-63].
     * Reference: 3GPP TS 3.03 section 4.2.2.
     *
     * 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, 1007].
     * Reference: 3GPP TS 38.211 section 7.4.2.1.
     *
     * @return the physical cell identifier for this cell, {@link #PHYSICAL_CELL_ID_UNKNOWN}
     * if {@link android.telephony.CellInfo#UNAVAILABLE}.
     */
    @IntRange(from = 0, to = 1007)
    public int getPhysicalCellId() {
        return mPhysicalCellId;
    }

    /**
     * @return The network type for this physical channel,
     * {@link TelephonyManager#NETWORK_TYPE_UNKNOWN} if unknown.
     */
    @NetworkType
    public int getNetworkType() {
        return mNetworkType;
    }

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

    /**
     * Return a copy of this PhysicalChannelConfig object but redact all the location info.
     * @hide
     */
    public PhysicalChannelConfig createLocationInfoSanitizedCopy() {
        return new Builder(this).setPhysicalCellId(PHYSICAL_CELL_ID_UNKNOWN).build();
    }

    /**
     * @return String representation of the connection status
     * @hide
     */
    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 + ")";
        }
    }

    private void setDownlinkFrequency() {
        switch (mNetworkType) {
            case TelephonyManager.NETWORK_TYPE_NR:
                mDownlinkFrequency = AccessNetworkUtils.getFrequencyFromNrArfcn(
                        mDownlinkChannelNumber);
                break;
            case TelephonyManager.NETWORK_TYPE_LTE:
                mDownlinkFrequency = AccessNetworkUtils.getFrequencyFromEarfcn(
                        mBand, mDownlinkChannelNumber, false);
                break;
            case TelephonyManager.NETWORK_TYPE_HSPAP:
            case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
            case TelephonyManager.NETWORK_TYPE_UMTS:
            case TelephonyManager.NETWORK_TYPE_HSDPA:
            case TelephonyManager.NETWORK_TYPE_HSUPA:
            case TelephonyManager.NETWORK_TYPE_HSPA:
                mDownlinkFrequency = AccessNetworkUtils.getFrequencyFromUarfcn(
                        mBand, mDownlinkChannelNumber, false);
                break;
            case TelephonyManager.NETWORK_TYPE_GPRS:
            case TelephonyManager.NETWORK_TYPE_EDGE:
            case TelephonyManager.NETWORK_TYPE_GSM:
                mDownlinkFrequency = AccessNetworkUtils.getFrequencyFromArfcn(
                        mBand, mDownlinkChannelNumber, false);
                break;
        }
    }

    private void setUplinkFrequency() {
        switch (mNetworkType){
            case TelephonyManager.NETWORK_TYPE_NR:
                mUplinkFrequency = AccessNetworkUtils.getFrequencyFromNrArfcn(
                        mUplinkChannelNumber);
                break;
            case TelephonyManager.NETWORK_TYPE_LTE:
                mUplinkFrequency = AccessNetworkUtils.getFrequencyFromEarfcn(
                        mBand, mUplinkChannelNumber, true);
                break;
            case TelephonyManager.NETWORK_TYPE_HSPAP:
            case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
            case TelephonyManager.NETWORK_TYPE_UMTS:
            case TelephonyManager.NETWORK_TYPE_HSDPA:
            case TelephonyManager.NETWORK_TYPE_HSUPA:
            case TelephonyManager.NETWORK_TYPE_HSPA:
                mUplinkFrequency = AccessNetworkUtils.getFrequencyFromUarfcn(
                        mBand, mUplinkChannelNumber, true);
                break;
            case TelephonyManager.NETWORK_TYPE_GPRS:
            case TelephonyManager.NETWORK_TYPE_EDGE:
            case TelephonyManager.NETWORK_TYPE_GSM:
                mUplinkFrequency = AccessNetworkUtils.getFrequencyFromArfcn(
                        mBand, mUplinkChannelNumber, true);
                break;
        }
    }

    private void setFrequencyRange() {
        if (mFrequencyRange != ServiceState.FREQUENCY_RANGE_UNKNOWN) {
            return;
        }

        switch (mNetworkType) {
            case TelephonyManager.NETWORK_TYPE_NR:
                mFrequencyRange = AccessNetworkUtils.getFrequencyRangeGroupFromNrBand(mBand);
                break;
            case TelephonyManager.NETWORK_TYPE_LTE:
                mFrequencyRange = AccessNetworkUtils.getFrequencyRangeGroupFromEutranBand(mBand);
                break;
            case TelephonyManager.NETWORK_TYPE_HSPAP:
            case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
            case TelephonyManager.NETWORK_TYPE_UMTS:
            case TelephonyManager.NETWORK_TYPE_HSDPA:
            case TelephonyManager.NETWORK_TYPE_HSUPA:
            case TelephonyManager.NETWORK_TYPE_HSPA:
                mFrequencyRange = AccessNetworkUtils.getFrequencyRangeGroupFromUtranBand(mBand);
                break;
            case TelephonyManager.NETWORK_TYPE_GPRS:
            case TelephonyManager.NETWORK_TYPE_EDGE:
            case TelephonyManager.NETWORK_TYPE_GSM:
                mFrequencyRange = AccessNetworkUtils.getFrequencyRangeGroupFromGeranBand(mBand);
                break;
            default:
                mFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN;
                break;
        }

        if (mFrequencyRange == ServiceState.FREQUENCY_RANGE_UNKNOWN) {
            mFrequencyRange = AccessNetworkUtils.getFrequencyRangeFromArfcn(
                    mDownlinkFrequency);
        }
    }

    @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
                && mCellBandwidthUplinkKhz == config.mCellBandwidthUplinkKhz
                && mNetworkType == config.mNetworkType
                && mFrequencyRange == config.mFrequencyRange
                && mDownlinkChannelNumber == config.mDownlinkChannelNumber
                && mUplinkChannelNumber == config.mUplinkChannelNumber
                && mPhysicalCellId == config.mPhysicalCellId
                && Arrays.equals(mContextIds, config.mContextIds)
                && mBand == config.mBand
                && mDownlinkFrequency == config.mDownlinkFrequency
                && mUplinkFrequency == config.mUplinkFrequency;
    }

    @Override
    public int hashCode() {
        return Objects.hash(
                mCellConnectionStatus, mCellBandwidthDownlinkKhz, mCellBandwidthUplinkKhz,
                mNetworkType, mFrequencyRange, mDownlinkChannelNumber, mUplinkChannelNumber,
                Arrays.hashCode(mContextIds), mPhysicalCellId, mBand, mDownlinkFrequency,
                mUplinkFrequency);
    }

    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(",mCellBandwidthUplinkKhz=")
                .append(mCellBandwidthUplinkKhz)
                .append(",mNetworkType=")
                .append(TelephonyManager.getNetworkTypeName(mNetworkType))
                .append(",mFrequencyRange=")
                .append(ServiceState.frequencyRangeToString(mFrequencyRange))
                .append(",mDownlinkChannelNumber=")
                .append(mDownlinkChannelNumber)
                .append(",mUplinkChannelNumber=")
                .append(mUplinkChannelNumber)
                .append(",mContextIds=")
                .append(Arrays.toString(mContextIds))
                .append(",mPhysicalCellId=")
                .append(mPhysicalCellId)
                .append(",mBand=")
                .append(mBand)
                .append(",mDownlinkFrequency=")
                .append(mDownlinkFrequency)
                .append(",mUplinkFrequency=")
                .append(mUplinkFrequency)
                .append("}")
                .toString();
    }

    private PhysicalChannelConfig(Parcel in) {
        mCellConnectionStatus = in.readInt();
        mCellBandwidthDownlinkKhz = in.readInt();
        mCellBandwidthUplinkKhz = in.readInt();
        mNetworkType = in.readInt();
        mDownlinkChannelNumber = in.readInt();
        mUplinkChannelNumber = in.readInt();
        mFrequencyRange = in.readInt();
        mContextIds = in.createIntArray();
        mPhysicalCellId = in.readInt();
        mBand = in.readInt();
        if (mBand > BAND_UNKNOWN) {
            setDownlinkFrequency();
            setUplinkFrequency();
            setFrequencyRange();
        }
    }

    private PhysicalChannelConfig(Builder builder) {
        mCellConnectionStatus = builder.mCellConnectionStatus;
        mCellBandwidthDownlinkKhz = builder.mCellBandwidthDownlinkKhz;
        mCellBandwidthUplinkKhz = builder.mCellBandwidthUplinkKhz;
        mNetworkType = builder.mNetworkType;
        mDownlinkChannelNumber = builder.mDownlinkChannelNumber;
        mUplinkChannelNumber = builder.mUplinkChannelNumber;
        mFrequencyRange = builder.mFrequencyRange;
        mContextIds = builder.mContextIds;
        mPhysicalCellId = builder.mPhysicalCellId;
        mBand = builder.mBand;
        if (mBand > BAND_UNKNOWN) {
            setDownlinkFrequency();
            setUplinkFrequency();
            setFrequencyRange();
        }
    }

    /**
     * The builder of {@code PhysicalChannelConfig}.
     * @hide
     */
    public static final class Builder {
        private int mNetworkType;
        private int mFrequencyRange;
        private int mDownlinkChannelNumber;
        private int mUplinkChannelNumber;
        private int mCellBandwidthDownlinkKhz;
        private int mCellBandwidthUplinkKhz;
        private int mCellConnectionStatus;
        private int[] mContextIds;
        private int mPhysicalCellId;
        private int mBand;

        public Builder() {
            mNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
            mFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN;
            mDownlinkChannelNumber = CHANNEL_NUMBER_UNKNOWN;
            mUplinkChannelNumber = CHANNEL_NUMBER_UNKNOWN;
            mCellBandwidthDownlinkKhz = CELL_BANDWIDTH_UNKNOWN;
            mCellBandwidthUplinkKhz = CELL_BANDWIDTH_UNKNOWN;
            mCellConnectionStatus = CONNECTION_UNKNOWN;
            mContextIds = new int[0];
            mPhysicalCellId = PHYSICAL_CELL_ID_UNKNOWN;
            mBand = BAND_UNKNOWN;
        }

        /**
         * Builder object constructed from existing PhysicalChannelConfig object.
         * @hide
         */
        public Builder(PhysicalChannelConfig config) {
            mNetworkType = config.getNetworkType();
            mFrequencyRange = config.getFrequencyRange();
            mDownlinkChannelNumber = config.getDownlinkChannelNumber();
            mUplinkChannelNumber = config.getUplinkChannelNumber();
            mCellBandwidthDownlinkKhz = config.getCellBandwidthDownlinkKhz();
            mCellBandwidthUplinkKhz = config.getCellBandwidthUplinkKhz();
            mCellConnectionStatus = config.getConnectionStatus();
            mContextIds = Arrays.copyOf(config.getContextIds(), config.getContextIds().length);
            mPhysicalCellId = config.getPhysicalCellId();
            mBand = config.getBand();
        }

        public PhysicalChannelConfig build() {
            return new PhysicalChannelConfig(this);
        }

        public @NonNull Builder setNetworkType(@NetworkType int networkType) {
            if (!TelephonyManager.isNetworkTypeValid(networkType)) {
                throw new IllegalArgumentException("Network type " + networkType + " is invalid.");
            }
            mNetworkType = networkType;
            return this;
        }

        public @NonNull Builder setFrequencyRange(int frequencyRange) {
            if (!ServiceState.isFrequencyRangeValid(frequencyRange)
                    && frequencyRange != ServiceState.FREQUENCY_RANGE_UNKNOWN) {
                throw new IllegalArgumentException("Frequency range " + frequencyRange
                        + " is invalid.");
            }
            mFrequencyRange = frequencyRange;
            return this;
        }

        public @NonNull Builder setDownlinkChannelNumber(int downlinkChannelNumber) {
            mDownlinkChannelNumber = downlinkChannelNumber;
            return this;
        }

        public @NonNull Builder setUplinkChannelNumber(int uplinkChannelNumber) {
            mUplinkChannelNumber = uplinkChannelNumber;
            return this;
        }

        public @NonNull Builder setCellBandwidthDownlinkKhz(int cellBandwidthDownlinkKhz) {
            if (cellBandwidthDownlinkKhz < CELL_BANDWIDTH_UNKNOWN) {
                throw new IllegalArgumentException("Cell downlink bandwidth(kHz) "
                        + cellBandwidthDownlinkKhz + " is invalid.");
            }
            mCellBandwidthDownlinkKhz = cellBandwidthDownlinkKhz;
            return this;
        }

        public @NonNull Builder setCellBandwidthUplinkKhz(int cellBandwidthUplinkKhz) {
            if (cellBandwidthUplinkKhz < CELL_BANDWIDTH_UNKNOWN) {
                throw new IllegalArgumentException("Cell uplink bandwidth(kHz) "
                        + cellBandwidthUplinkKhz + " is invalid.");
            }
            mCellBandwidthUplinkKhz = cellBandwidthUplinkKhz;
            return this;
        }

        public @NonNull Builder setCellConnectionStatus(int connectionStatus) {
            mCellConnectionStatus = connectionStatus;
            return this;
        }

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

        public @NonNull Builder setPhysicalCellId(int physicalCellId) {
            if (physicalCellId > PHYSICAL_CELL_ID_MAXIMUM_VALUE) {
                throw new IllegalArgumentException("Physical cell ID " + physicalCellId
                        + " is over limit.");
            }
            mPhysicalCellId = physicalCellId;
            return this;
        }

        public @NonNull Builder setBand(int band) {
            if (band <= BAND_UNKNOWN) {
                throw new IllegalArgumentException("Band " + band + " is invalid.");
            }
            mBand = band;
            return this;
        }
    }
}
