/*
 * Copyright (C) 2012 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.IntRange;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.PersistableBundle;
import android.telephony.Rlog;

import java.util.Objects;

/**
 * Signal strength related information.
 */
public final class CellSignalStrengthCdma extends CellSignalStrength implements Parcelable {

    private static final String LOG_TAG = "CellSignalStrengthCdma";
    private static final boolean DBG = false;

    private int mCdmaDbm;   // This value is the RSSI value
    private int mCdmaEcio;  // This value is the Ec/Io
    private int mEvdoDbm;   // This value is the EVDO RSSI value
    private int mEvdoEcio;  // This value is the EVDO Ec/Io
    private int mEvdoSnr;   // Valid values are 0-8.  8 is the highest signal to noise ratio
    private int mLevel;

    /** @hide */
    public CellSignalStrengthCdma() {
        setDefaultValues();
    }

    /**
     * SignalStrength constructor for input from the HAL.
     *
     * Note that values received from the HAL require coersion to be compatible here. All values
     * reported through IRadio are the negative of the actual values (which results in a positive
     * input to this method.
     *
     * <p>Note that this HAL is inconsistent with UMTS-based radio techs as the value indicating
     * that a field is unreported is negative, rather than a large(r) positive number.
     * <p>Also note that to keep the public-facing methods of this class consistent with others,
     * unreported values are coerced to {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE}
     * rather than left as -1, which is a departure from SignalStrength, which is stuck with the
     * values it currently reports.
     *
     * @param cdmaDbm CDMA signal strength value or CellInfo.UNAVAILABLE if invalid.
     * @param cdmaEcio CDMA pilot/noise ratio or CellInfo.UNAVAILABLE  if invalid.
     * @param evdoDbm negative of the EvDO signal strength value or CellInfo.UNAVAILABLE if invalid.
     * @param evdoEcio negative of the EvDO pilot/noise ratio or CellInfo.UNAVAILABLE if invalid.
     * @param evdoSnr an SNR value 0..8 or CellInfo.UNVAILABLE if invalid.
     * @hide
     */
    public CellSignalStrengthCdma(int cdmaDbm, int cdmaEcio, int evdoDbm, int evdoEcio,
            int evdoSnr) {
        mCdmaDbm = inRangeOrUnavailable(cdmaDbm, -120, 0);
        mCdmaEcio = inRangeOrUnavailable(cdmaEcio, -160, 0);
        mEvdoDbm = inRangeOrUnavailable(evdoDbm, -120, 0);
        mEvdoEcio = inRangeOrUnavailable(evdoEcio, -160, 0);
        mEvdoSnr = inRangeOrUnavailable(evdoSnr, 0, 8);

        updateLevel(null, null);
    }

    /** @hide */
    public CellSignalStrengthCdma(android.hardware.radio.V1_0.CdmaSignalStrength cdma,
            android.hardware.radio.V1_0.EvdoSignalStrength evdo) {
        // Convert from HAL values as part of construction.
        this(-cdma.dbm, -cdma.ecio, -evdo.dbm, -evdo.ecio, evdo.signalNoiseRatio);
    }

    /** @hide */
    public CellSignalStrengthCdma(CellSignalStrengthCdma s) {
        copyFrom(s);
    }

    /** @hide */
    protected void copyFrom(CellSignalStrengthCdma s) {
        mCdmaDbm = s.mCdmaDbm;
        mCdmaEcio = s.mCdmaEcio;
        mEvdoDbm = s.mEvdoDbm;
        mEvdoEcio = s.mEvdoEcio;
        mEvdoSnr = s.mEvdoSnr;
        mLevel = s.mLevel;
    }

    /** @hide */
    @Override
    public CellSignalStrengthCdma copy() {
        return new CellSignalStrengthCdma(this);
    }

    /** @hide */
    @Override
    public void setDefaultValues() {
        mCdmaDbm = CellInfo.UNAVAILABLE;
        mCdmaEcio = CellInfo.UNAVAILABLE;
        mEvdoDbm = CellInfo.UNAVAILABLE;
        mEvdoEcio = CellInfo.UNAVAILABLE;
        mEvdoSnr = CellInfo.UNAVAILABLE;
        mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
    }

    /** {@inheritDoc} */
    @Override
    @IntRange(from = SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to = SIGNAL_STRENGTH_GREAT)
    public int getLevel() {
        return mLevel;
    }

    /** @hide */
    @Override
    public void updateLevel(PersistableBundle cc, ServiceState ss) {
        int cdmaLevel = getCdmaLevel();
        int evdoLevel = getEvdoLevel();
        if (evdoLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
            /* We don't know evdo, use cdma */
            mLevel = getCdmaLevel();
        } else if (cdmaLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
            /* We don't know cdma, use evdo */
            mLevel = getEvdoLevel();
        } else {
            /* We know both, use the lowest level */
            mLevel = cdmaLevel < evdoLevel ? cdmaLevel : evdoLevel;
        }
    }

    /**
     * Get the 1xRTT Level in (Android) ASU.
     *
     * There is no standard definition of ASU for CDMA; however, Android defines it as the
     * the lesser of the following two results (for 1xRTT):
     * <table>
     *     <thead><tr><th>RSSI Range (dBm)</th><th>ASU Value</th></tr><thead>
     *     <tbody>
     *         <tr><td>-75..</td><td>16</td></tr>
     *         <tr><td>-82..-76</td><td>8</td></tr>
     *         <tr><td>-90..-83</td><td>4</td></tr>
     *         <tr><td>-95..-91</td><td>2</td></tr>
     *         <tr><td>-100..-96</td><td>1</td></tr>
     *         <tr><td>..-101</td><td>99</td></tr>
     *     </tbody>
     * </table>
     * <table>
     *     <thead><tr><th>Ec/Io Range (dB)</th><th>ASU Value</th></tr><thead>
     *     <tbody>
     *         <tr><td>-90..</td><td>16</td></tr>
     *         <tr><td>-100..-91</td><td>8</td></tr>
     *         <tr><td>-115..-101</td><td>4</td></tr>
     *         <tr><td>-130..-116</td><td>2</td></tr>
     *         <tr><td>--150..-131</td><td>1</td></tr>
     *         <tr><td>..-151</td><td>99</td></tr>
     *     </tbody>
     * </table>
     * @return 1xRTT Level in Android ASU {1,2,4,8,16,99}
     */
    @Override
    public int getAsuLevel() {
        final int cdmaDbm = getCdmaDbm();
        final int cdmaEcio = getCdmaEcio();
        int cdmaAsuLevel;
        int ecioAsuLevel;

        if (cdmaDbm == CellInfo.UNAVAILABLE) cdmaAsuLevel = 99;
        else if (cdmaDbm >= -75) cdmaAsuLevel = 16;
        else if (cdmaDbm >= -82) cdmaAsuLevel = 8;
        else if (cdmaDbm >= -90) cdmaAsuLevel = 4;
        else if (cdmaDbm >= -95) cdmaAsuLevel = 2;
        else if (cdmaDbm >= -100) cdmaAsuLevel = 1;
        else cdmaAsuLevel = 99;

        // Ec/Io are in dB*10
        if (cdmaEcio == CellInfo.UNAVAILABLE) ecioAsuLevel = 99;
        else if (cdmaEcio >= -90) ecioAsuLevel = 16;
        else if (cdmaEcio >= -100) ecioAsuLevel = 8;
        else if (cdmaEcio >= -115) ecioAsuLevel = 4;
        else if (cdmaEcio >= -130) ecioAsuLevel = 2;
        else if (cdmaEcio >= -150) ecioAsuLevel = 1;
        else ecioAsuLevel = 99;

        int level = (cdmaAsuLevel < ecioAsuLevel) ? cdmaAsuLevel : ecioAsuLevel;
        if (DBG) log("getAsuLevel=" + level);
        return level;
    }

    /**
     * Get cdma as level 0..4
     */
    public int getCdmaLevel() {
        final int cdmaDbm = getCdmaDbm();
        final int cdmaEcio = getCdmaEcio();
        int levelDbm;
        int levelEcio;

        if (cdmaDbm == CellInfo.UNAVAILABLE) levelDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
        else if (cdmaDbm >= -75) levelDbm = SIGNAL_STRENGTH_GREAT;
        else if (cdmaDbm >= -85) levelDbm = SIGNAL_STRENGTH_GOOD;
        else if (cdmaDbm >= -95) levelDbm = SIGNAL_STRENGTH_MODERATE;
        else if (cdmaDbm >= -100) levelDbm = SIGNAL_STRENGTH_POOR;
        else levelDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;

        // Ec/Io are in dB*10
        if (cdmaEcio == CellInfo.UNAVAILABLE) levelEcio = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
        else if (cdmaEcio >= -90) levelEcio = SIGNAL_STRENGTH_GREAT;
        else if (cdmaEcio >= -110) levelEcio = SIGNAL_STRENGTH_GOOD;
        else if (cdmaEcio >= -130) levelEcio = SIGNAL_STRENGTH_MODERATE;
        else if (cdmaEcio >= -150) levelEcio = SIGNAL_STRENGTH_POOR;
        else levelEcio = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;

        int level = (levelDbm < levelEcio) ? levelDbm : levelEcio;
        if (DBG) log("getCdmaLevel=" + level);
        return level;
    }

    /**
     * Get Evdo as level 0..4
     */
    public int getEvdoLevel() {
        int evdoDbm = getEvdoDbm();
        int evdoSnr = getEvdoSnr();
        int levelEvdoDbm;
        int levelEvdoSnr;

        if (evdoDbm == CellInfo.UNAVAILABLE) levelEvdoDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
        else if (evdoDbm >= -65) levelEvdoDbm = SIGNAL_STRENGTH_GREAT;
        else if (evdoDbm >= -75) levelEvdoDbm = SIGNAL_STRENGTH_GOOD;
        else if (evdoDbm >= -90) levelEvdoDbm = SIGNAL_STRENGTH_MODERATE;
        else if (evdoDbm >= -105) levelEvdoDbm = SIGNAL_STRENGTH_POOR;
        else levelEvdoDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;

        if (evdoSnr == CellInfo.UNAVAILABLE) levelEvdoSnr = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
        else if (evdoSnr >= 7) levelEvdoSnr = SIGNAL_STRENGTH_GREAT;
        else if (evdoSnr >= 5) levelEvdoSnr = SIGNAL_STRENGTH_GOOD;
        else if (evdoSnr >= 3) levelEvdoSnr = SIGNAL_STRENGTH_MODERATE;
        else if (evdoSnr >= 1) levelEvdoSnr = SIGNAL_STRENGTH_POOR;
        else levelEvdoSnr = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;

        int level = (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr;
        if (DBG) log("getEvdoLevel=" + level);
        return level;
    }

    /**
     * Get the EVDO Level in (Android) ASU.
     *
     * There is no standard definition of ASU for CDMA; however, Android defines it as the
     * the lesser of the following two results (for EVDO):
     * <table>
     *     <thead><tr><th>RSSI Range (dBm)</th><th>ASU Value</th></tr><thead>
     *     <tbody>
     *         <tr><td>-65..</td><td>16</td></tr>
     *         <tr><td>-75..-66</td><td>8</td></tr>
     *         <tr><td>-85..-76</td><td>4</td></tr>
     *         <tr><td>-95..-86</td><td>2</td></tr>
     *         <tr><td>-105..-96</td><td>1</td></tr>
     *         <tr><td>..-106</td><td>99</td></tr>
     *     </tbody>
     * </table>
     * <table>
     *     <thead><tr><th>SNR Range (unitless)</th><th>ASU Value</th></tr><thead>
     *     <tbody>
     *         <tr><td>7..</td><td>16</td></tr>
     *         <tr><td>6</td><td>8</td></tr>
     *         <tr><td>5</td><td>4</td></tr>
     *         <tr><td>3..4</td><td>2</td></tr>
     *         <tr><td>1..2</td><td>1</td></tr>
     *         <tr><td>0</td><td>99</td></tr>
     *     </tbody>
     * </table>
     *
     * @return EVDO Level in Android ASU {1,2,4,8,16,99}
     *
     * @hide
     */
    public int getEvdoAsuLevel() {
        int evdoDbm = getEvdoDbm();
        int evdoSnr = getEvdoSnr();
        int levelEvdoDbm;
        int levelEvdoSnr;

        if (evdoDbm >= -65) levelEvdoDbm = 16;
        else if (evdoDbm >= -75) levelEvdoDbm = 8;
        else if (evdoDbm >= -85) levelEvdoDbm = 4;
        else if (evdoDbm >= -95) levelEvdoDbm = 2;
        else if (evdoDbm >= -105) levelEvdoDbm = 1;
        else levelEvdoDbm = 99;

        if (evdoSnr >= 7) levelEvdoSnr = 16;
        else if (evdoSnr >= 6) levelEvdoSnr = 8;
        else if (evdoSnr >= 5) levelEvdoSnr = 4;
        else if (evdoSnr >= 3) levelEvdoSnr = 2;
        else if (evdoSnr >= 1) levelEvdoSnr = 1;
        else levelEvdoSnr = 99;

        int level = (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr;
        if (DBG) log("getEvdoAsuLevel=" + level);
        return level;
    }

    /**
     * Get the signal strength as dBm
     */
    @Override
    public int getDbm() {
        int cdmaDbm = getCdmaDbm();
        int evdoDbm = getEvdoDbm();

        // Use the lower value to be conservative
        return (cdmaDbm < evdoDbm) ? cdmaDbm : evdoDbm;
    }

    /**
     * Get the CDMA RSSI value in dBm
     */
    public int getCdmaDbm() {
        return mCdmaDbm;
    }

    /** @hide */
    public void setCdmaDbm(int cdmaDbm) {
        mCdmaDbm = cdmaDbm;
    }

    /**
     * Get the CDMA Ec/Io value in dB*10
     */
    public int getCdmaEcio() {
        return mCdmaEcio;
    }

    /** @hide */
    public void setCdmaEcio(int cdmaEcio) {
        mCdmaEcio = cdmaEcio;
    }

    /**
     * Get the EVDO RSSI value in dBm
     */
    public int getEvdoDbm() {
        return mEvdoDbm;
    }

    /** @hide */
    public void setEvdoDbm(int evdoDbm) {
        mEvdoDbm = evdoDbm;
    }

    /**
     * Get the EVDO Ec/Io value in dB*10
     */
    public int getEvdoEcio() {
        return mEvdoEcio;
    }

    /** @hide */
    public void setEvdoEcio(int evdoEcio) {
        mEvdoEcio = evdoEcio;
    }

    /**
     * Get the signal to noise ratio. Valid values are 0-8. 8 is the highest.
     */
    public int getEvdoSnr() {
        return mEvdoSnr;
    }

    /** @hide */
    public void setEvdoSnr(int evdoSnr) {
        mEvdoSnr = evdoSnr;
    }

    @Override
    public int hashCode() {
        return Objects.hash(mCdmaDbm, mCdmaEcio, mEvdoDbm, mEvdoEcio, mEvdoSnr, mLevel);
    }

    private static final CellSignalStrengthCdma sInvalid = new CellSignalStrengthCdma();

    /** @hide */
    @Override
    public boolean isValid() {
        return !this.equals(sInvalid);
    }

    @Override
    public boolean equals (Object o) {
        CellSignalStrengthCdma s;
        if (!(o instanceof CellSignalStrengthCdma)) return false;
        s = (CellSignalStrengthCdma) o;

        return mCdmaDbm == s.mCdmaDbm
                && mCdmaEcio == s.mCdmaEcio
                && mEvdoDbm == s.mEvdoDbm
                && mEvdoEcio == s.mEvdoEcio
                && mEvdoSnr == s.mEvdoSnr
                && mLevel == s.mLevel;
    }

    /**
     * @return string representation.
     */
    @Override
    public String toString() {
        return "CellSignalStrengthCdma:"
                + " cdmaDbm=" + mCdmaDbm
                + " cdmaEcio=" + mCdmaEcio
                + " evdoDbm=" + mEvdoDbm
                + " evdoEcio=" + mEvdoEcio
                + " evdoSnr=" + mEvdoSnr
                + " level=" + mLevel;
    }

    /** Implement the Parcelable interface */
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        if (DBG) log("writeToParcel(Parcel, int): " + toString());
        dest.writeInt(mCdmaDbm);
        dest.writeInt(mCdmaEcio);
        dest.writeInt(mEvdoDbm);
        dest.writeInt(mEvdoEcio);
        dest.writeInt(mEvdoSnr);
        dest.writeInt(mLevel);
    }

    /**
     * Construct a SignalStrength object from the given parcel
     * where the TYPE_CDMA token is already been processed.
     */
    private CellSignalStrengthCdma(Parcel in) {
        // CdmaDbm, CdmaEcio, EvdoDbm and EvdoEcio are written into
        // the parcel as positive values.
        // Need to convert into negative values unless the value is invalid
        mCdmaDbm = in.readInt();
        mCdmaEcio = in.readInt();
        mEvdoDbm = in.readInt();
        mEvdoEcio = in.readInt();
        mEvdoSnr = in.readInt();
        mLevel = in.readInt();
        if (DBG) log("CellSignalStrengthCdma(Parcel): " + toString());
    }

    /** Implement the Parcelable interface */
    @Override
    public int describeContents() {
        return 0;
    }

    /** Implement the Parcelable interface */
    @SuppressWarnings("hiding")
    public static final @android.annotation.NonNull Parcelable.Creator<CellSignalStrengthCdma> CREATOR =
            new Parcelable.Creator<CellSignalStrengthCdma>() {
        @Override
        public CellSignalStrengthCdma createFromParcel(Parcel in) {
            return new CellSignalStrengthCdma(in);
        }

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

    /**
     * log
     */
    private static void log(String s) {
        Rlog.w(LOG_TAG, s);
    }
}
