/*
 * Copyright (C) 2014 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.net;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;

import java.util.Objects;
import java.util.Set;

/**
 * A network identifier along with a score for the quality of that network.
 *
 * @hide
 */
@SystemApi
public class ScoredNetwork implements Parcelable {

  /**
     * Key used with the {@link #attributes} bundle to define the badging curve.
     *
     * <p>The badging curve is a {@link RssiCurve} used to map different RSSI values to {@link
     * NetworkBadging.Badging} enums.
     */
    public static final String ATTRIBUTES_KEY_BADGING_CURVE =
            "android.net.attributes.key.BADGING_CURVE";
    /**
     * Extra used with {@link #attributes} to specify whether the
     * network is believed to have a captive portal.
     * <p>
     * This data may be used, for example, to display a visual indicator
     * in a network selection list.
     * <p>
     * Note that the this extra conveys the possible presence of a
     * captive portal, not its state or the user's ability to open
     * the portal.
     * <p>
     * If no value is associated with this key then it's unknown.
     */
    public static final String ATTRIBUTES_KEY_HAS_CAPTIVE_PORTAL =
            "android.net.attributes.key.HAS_CAPTIVE_PORTAL";

    /**
     * Key used with the {@link #attributes} bundle to define the rankingScoreOffset int value.
     *
     * <p>The rankingScoreOffset is used when calculating the ranking score used to rank networks
     * against one another. See {@link #calculateRankingScore} for more information.
     */
    public static final String ATTRIBUTES_KEY_RANKING_SCORE_OFFSET =
            "android.net.attributes.key.RANKING_SCORE_OFFSET";

    /** A {@link NetworkKey} uniquely identifying this network. */
    public final NetworkKey networkKey;

    /**
     * The {@link RssiCurve} representing the scores for this network based on the RSSI.
     *
     * <p>This field is optional and may be set to null to indicate that no score is available for
     * this network at this time. Such networks, along with networks for which the scorer has not
     * responded, are always prioritized below scored networks, regardless of the score.
     */
    public final RssiCurve rssiCurve;

    /**
     * A boolean value that indicates whether or not the network is believed to be metered.
     *
     * <p>A network can be classified as metered if the user would be
     * sensitive to heavy data usage on that connection due to monetary costs,
     * data limitations or battery/performance issues. A typical example would
     * be a wifi connection where the user would be charged for usage.
     */
    public final boolean meteredHint;

    /**
     * An additional collection of optional attributes set by
     * the Network Recommendation Provider.
     *
     * @see #ATTRIBUTES_KEY_HAS_CAPTIVE_PORTAL
     * @see #ATTRIBUTES_KEY_RANKING_SCORE_OFFSET
     */
    @Nullable
    public final Bundle attributes;

    /**
     * Construct a new {@link ScoredNetwork}.
     *
     * @param networkKey the {@link NetworkKey} uniquely identifying this network.
     * @param rssiCurve the {@link RssiCurve} representing the scores for this network based on the
     *     RSSI. This field is optional, and may be skipped to represent a network which the scorer
     *     has opted not to score at this time. Passing a null value here is strongly preferred to
     *     not returning any {@link ScoredNetwork} for a given {@link NetworkKey} because it
     *     indicates to the system not to request scores for this network in the future, although
     *     the scorer may choose to issue an out-of-band update at any time.
     */
    public ScoredNetwork(NetworkKey networkKey, RssiCurve rssiCurve) {
        this(networkKey, rssiCurve, false /* meteredHint */);
    }

    /**
     * Construct a new {@link ScoredNetwork}.
     *
     * @param networkKey the {@link NetworkKey} uniquely identifying this network.
     * @param rssiCurve the {@link RssiCurve} representing the scores for this network based on the
     *     RSSI. This field is optional, and may be skipped to represent a network which the scorer
     *     has opted not to score at this time. Passing a null value here is strongly preferred to
     *     not returning any {@link ScoredNetwork} for a given {@link NetworkKey} because it
     *     indicates to the system not to request scores for this network in the future, although
     *     the scorer may choose to issue an out-of-band update at any time.
     * @param meteredHint A boolean value indicating whether or not the network is believed to be
     *     metered.
     */
    public ScoredNetwork(NetworkKey networkKey, RssiCurve rssiCurve, boolean meteredHint) {
        this(networkKey, rssiCurve, meteredHint, null /* attributes */);
    }

    /**
     * Construct a new {@link ScoredNetwork}.
     *
     * @param networkKey the {@link NetworkKey} uniquely identifying this network
     * @param rssiCurve the {@link RssiCurve} representing the scores for this network based on the
     *     RSSI. This field is optional, and may be skipped to represent a network which the scorer
     *     has opted not to score at this time. Passing a null value here is strongly preferred to
     *     not returning any {@link ScoredNetwork} for a given {@link NetworkKey} because it
     *     indicates to the system not to request scores for this network in the future, although
     *     the scorer may choose to issue an out-of-band update at any time.
     * @param meteredHint a boolean value indicating whether or not the network is believed to be
     *                    metered
     * @param attributes optional provider specific attributes
     */
    public ScoredNetwork(NetworkKey networkKey, RssiCurve rssiCurve, boolean meteredHint,
            @Nullable Bundle attributes) {
        this.networkKey = networkKey;
        this.rssiCurve = rssiCurve;
        this.meteredHint = meteredHint;
        this.attributes = attributes;
    }

    private ScoredNetwork(Parcel in) {
        networkKey = NetworkKey.CREATOR.createFromParcel(in);
        if (in.readByte() == 1) {
            rssiCurve = RssiCurve.CREATOR.createFromParcel(in);
        } else {
            rssiCurve = null;
        }
        meteredHint = (in.readByte() == 1);
        attributes = in.readBundle();
    }

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

    @Override
    public void writeToParcel(Parcel out, int flags) {
        networkKey.writeToParcel(out, flags);
        if (rssiCurve != null) {
            out.writeByte((byte) 1);
            rssiCurve.writeToParcel(out, flags);
        } else {
            out.writeByte((byte) 0);
        }
        out.writeByte((byte) (meteredHint ? 1 : 0));
        out.writeBundle(attributes);
    }

    @Override
    public boolean equals(@Nullable Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        ScoredNetwork that = (ScoredNetwork) o;

        return Objects.equals(networkKey, that.networkKey)
                && Objects.equals(rssiCurve, that.rssiCurve)
                && Objects.equals(meteredHint, that.meteredHint)
                && bundleEquals(attributes, that.attributes);
    }

    private boolean bundleEquals(Bundle bundle1, Bundle bundle2) {
        if (bundle1 == bundle2) {
            return true;
        }
        if (bundle1 == null || bundle2 == null) {
            return false;
        }
        if (bundle1.size() != bundle2.size()) {
            return false;
        }
        Set<String> keys = bundle1.keySet();
        for (String key : keys) {
            Object value1 = bundle1.get(key);
            Object value2 = bundle2.get(key);
            if (!Objects.equals(value1, value2)) {
                return false;
            }
        }
        return true;
    }

    @Override
    public int hashCode() {
        return Objects.hash(networkKey, rssiCurve, meteredHint, attributes);
    }

    @NonNull
    @Override
    public String toString() {
        StringBuilder out = new StringBuilder(
                "ScoredNetwork{" +
                "networkKey=" + networkKey +
                ", rssiCurve=" + rssiCurve +
                ", meteredHint=" + meteredHint);
        // calling isEmpty will unparcel the bundle so its contents can be converted to a string
        if (attributes != null && !attributes.isEmpty()) {
            out.append(", attributes=" + attributes);
        }
        out.append('}');
        return out.toString();
    }

    /**
     * Returns true if a ranking score can be calculated for this network.
     *
     * @hide
     */
    public boolean hasRankingScore() {
        return (rssiCurve != null)
                || (attributes != null
                        && attributes.containsKey(ATTRIBUTES_KEY_RANKING_SCORE_OFFSET));
    }

    /**
     * Returns a ranking score for a given RSSI which can be used to comparatively
     * rank networks.
     *
     * <p>The score obtained by the rssiCurve is bitshifted left by 8 bits to expand it to an
     * integer and then the offset is added. If the addition operation overflows or underflows,
     * Integer.MAX_VALUE and Integer.MIN_VALUE will be returned respectively.
     *
     * <p>{@link #hasRankingScore} should be called first to ensure this network is capable
     * of returning a ranking score.
     *
     * @throws UnsupportedOperationException if there is no RssiCurve and no rankingScoreOffset
     * for this network (hasRankingScore returns false).
     *
     * @hide
     */
    public int calculateRankingScore(int rssi) throws UnsupportedOperationException {
        if (!hasRankingScore()) {
            throw new UnsupportedOperationException(
                    "Either rssiCurve or rankingScoreOffset is required to calculate the "
                            + "ranking score");
        }

        int offset = 0;
        if (attributes != null) {
             offset += attributes.getInt(ATTRIBUTES_KEY_RANKING_SCORE_OFFSET, 0 /* default */);
        }

        int score = (rssiCurve == null) ? 0 : rssiCurve.lookupScore(rssi) << Byte.SIZE;

        try {
            return Math.addExact(score, offset);
        } catch (ArithmeticException e) {
            return (score < 0) ? Integer.MIN_VALUE : Integer.MAX_VALUE;
        }
    }

    /**
     * Return the {@link NetworkBadging.Badging} enum for this network for the given RSSI, derived from the
     * badging curve.
     *
     * <p>If no badging curve is present, {@link #BADGE_NONE} will be returned.
     *
     * @param rssi The rssi level for which the badge should be calculated
     */
    @NetworkBadging.Badging
    public int calculateBadge(int rssi) {
        if (attributes != null && attributes.containsKey(ATTRIBUTES_KEY_BADGING_CURVE)) {
            RssiCurve badgingCurve =
                    attributes.getParcelable(ATTRIBUTES_KEY_BADGING_CURVE);
            return badgingCurve.lookupScore(rssi);
        }

        return NetworkBadging.BADGING_NONE;
    }

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

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