/*
 * Copyright (C) 2019 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 com.android.server.wifi;

import android.Manifest.permission;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.net.NetworkKey;
import android.net.NetworkScoreManager;
import android.net.ScoredNetwork;
import android.net.wifi.ScanResult;
import android.os.Handler;
import android.os.Process;
import android.util.Log;
import android.util.LruCache;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * {@link NetworkScoreManager.NetworkScoreCallback} implementation for Wifi Networks.
 *
 * Note: This is a copy of WifiNetworkScoreCache for internal usage by the wifi stack. This extends
 * the formal API: {@link NetworkScoreManager.NetworkScoreCallback}
 */
public class WifiNetworkScoreCache extends NetworkScoreManager.NetworkScoreCallback {
    private static final String TAG = "WifiNetworkScoreCache";
    private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);

    // A Network scorer returns a score in the range [-128, +127]
    // We treat the lowest possible score as though there were no score, effectively allowing the
    // scorer to provide an RSSI threshold below which a network should not be used.
    public static final int INVALID_NETWORK_SCORE = Byte.MIN_VALUE;

    /** Default number entries to be stored in the {@link LruCache}. */
    private static final int DEFAULT_MAX_CACHE_SIZE = 100;

    // See {@link #CacheListener}.
    @Nullable
    @GuardedBy("mLock")
    private CacheListener mListener;

    private final Context mContext;
    private final Object mLock = new Object();

    // The key is of the form "<ssid>"<bssid>
    // TODO: What about SSIDs that can't be encoded as UTF-8?
    @GuardedBy("mLock")
    private final LruCache<String, ScoredNetwork> mCache;

    public WifiNetworkScoreCache(Context context) {
        this(context, null /* listener */);
    }

    /**
     * Instantiates a WifiNetworkScoreCache.
     *
     * @param context Application context
     * @param listener CacheListener for cache updates
     */
    public WifiNetworkScoreCache(Context context, @Nullable CacheListener listener) {
        this(context, listener, DEFAULT_MAX_CACHE_SIZE);
    }

    public WifiNetworkScoreCache(
            Context context, @Nullable CacheListener listener, int maxCacheSize) {
        mContext = context.getApplicationContext();
        mListener = listener;
        mCache = new LruCache<>(maxCacheSize);
    }

    @Override
    public final void onScoresUpdated(Collection<ScoredNetwork> networks) {
        if (networks == null || networks.isEmpty()) {
            return;
        }
        if (DBG) {
            Log.d(TAG, "updateScores list size=" + networks.size());
        }

        boolean changed = false;

        synchronized (mLock) {
            for (ScoredNetwork network : networks) {
                String networkKey = buildNetworkKey(network);
                if (networkKey == null) {
                    if (DBG) {
                        Log.d(TAG, "Failed to build network key for ScoredNetwork" + network);
                    }
                    continue;
                }
                mCache.put(networkKey, network);
                changed = true;
            }

            if (mListener != null && changed) {
                mListener.post(new ArrayList<>(networks));
            }
        }
    }

    @Override
    public final void onScoresInvalidated() {
        synchronized (mLock) {
            mCache.evictAll();
        }
    }

    /**
     * Returns whether there is any score info for the given ScanResult.
     *
     * This includes null-score info, so it should only be used when determining whether to request
     * scores from the network scorer.
     */
    public boolean isScoredNetwork(ScanResult result) {
        return getScoredNetwork(result) != null;
    }

    /**
     * Returns whether there is a non-null score curve for the given ScanResult.
     *
     * A null score curve has special meaning - we should never connect to an ephemeral network if
     * the score curve is null.
     */
    public boolean hasScoreCurve(ScanResult result) {
        ScoredNetwork network = getScoredNetwork(result);
        return network != null && network.rssiCurve != null;
    }

    private int getNetworkScore(ScanResult result) {
        int score = INVALID_NETWORK_SCORE;

        ScoredNetwork network = getScoredNetwork(result);
        if (network != null && network.rssiCurve != null) {
            score = network.rssiCurve.lookupScore(result.level);
            if (DBG) {
                Log.d(TAG, "getNetworkScore found scored network " + network.networkKey
                        + " score " + Integer.toString(score)
                        + " RSSI " + result.level);
            }
        }
        return score;
    }

    /**
     * Returns the ScoredNetwork metered hint for a given ScanResult.
     *
     * If there is no ScoredNetwork associated with the ScanResult then false will be returned.
     */
    public boolean getMeteredHint(ScanResult result) {
        ScoredNetwork network = getScoredNetwork(result);
        return network != null && network.meteredHint;
    }

    /**
     * Get network score for the provided ScanResult.
     */
    public int getNetworkScore(ScanResult result, boolean isActiveNetwork) {
        int score = INVALID_NETWORK_SCORE;

        ScoredNetwork network = getScoredNetwork(result);
        if (network != null && network.rssiCurve != null) {
            score = network.rssiCurve.lookupScore(result.level, isActiveNetwork);
            if (DBG) {
                Log.d(TAG, "getNetworkScore found scored network " + network.networkKey
                        + " score " + Integer.toString(score)
                        + " RSSI " + result.level
                        + " isActiveNetwork " + isActiveNetwork);
            }
        }
        return score;
    }

    @Nullable
    private ScoredNetwork getScoredNetwork(ScanResult result) {
        String key = buildNetworkKey(result);
        if (key == null) return null;

        synchronized (mLock) {
            ScoredNetwork network = mCache.get(key);
            return network;
        }
    }

    /** Returns the ScoredNetwork for the given key. */
    @Nullable
    public ScoredNetwork getScoredNetwork(NetworkKey networkKey) {
        String key = buildNetworkKey(networkKey);
        if (key == null) {
            if (DBG) {
                Log.d(TAG, "Could not build key string for Network Key: " + networkKey);
            }
            return null;
        }
        synchronized (mLock) {
            return mCache.get(key);
        }
    }

    private String buildNetworkKey(ScoredNetwork network) {
        if (network == null) {
            return null;
        }
        return buildNetworkKey(network.networkKey);
    }

    private String buildNetworkKey(NetworkKey networkKey) {
        if (networkKey == null) {
            return null;
        }
        if (networkKey.wifiKey == null) return null;
        if (networkKey.type == NetworkKey.TYPE_WIFI) {
            String key = networkKey.wifiKey.ssid;
            if (key == null) return null;
            if (networkKey.wifiKey.bssid != null) {
                key = key + networkKey.wifiKey.bssid;
            }
            return key;
        }
        return null;
    }

    private String buildNetworkKey(ScanResult result) {
        if (result == null || result.SSID == null) {
            return null;
        }
        StringBuilder key = new StringBuilder("\"");
        key.append(result.SSID);
        key.append("\"");
        if (result.BSSID != null) {
            key.append(result.BSSID);
        }
        return key.toString();
    }

    /**
     * This is directly invoked from within Wifi-Service (on it's instance of this class), hence
     * avoid making the WifiManager.getScanResults() call to avoid a deadlock.
     */
    public final void dumpWithLatestScanResults(
            FileDescriptor fd, PrintWriter writer, String[] args,
            List<ScanResult> latestScanResults) {
        mContext.enforceCallingOrSelfPermission(permission.DUMP, TAG);
        String header = String.format("WifiNetworkScoreCache (%s/%d)",
                mContext.getPackageName(), Process.myUid());
        writer.println(header);
        writer.println("  All score curves:");
        synchronized (mLock) {
            for (ScoredNetwork score : mCache.snapshot().values()) {
                writer.println("    " + score);
            }
            writer.println("  Network scores for latest ScanResults:");
            for (ScanResult scanResult : latestScanResults) {
                writer.println(
                        "    " + buildNetworkKey(scanResult) + ": " + getNetworkScore(scanResult));
            }
        }
    }

    /** Listener for updates to the cache inside WifiNetworkScoreCache. */
    public abstract static class CacheListener {
        private Handler mHandler;

        /**
         * Constructor for CacheListener.
         *
         * @param handler the Handler on which to invoke the {@link #networkCacheUpdated} method.
         *          This cannot be null.
         */
        public CacheListener(@NonNull Handler handler) {
            Preconditions.checkNotNull(handler);
            mHandler = handler;
        }

        /** Invokes the {@link #networkCacheUpdated(List<ScoredNetwork>)} method on the handler. */
        void post(List<ScoredNetwork> updatedNetworks) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    networkCacheUpdated(updatedNetworks);
                }
            });
        }

        /**
         * Invoked whenever the cache is updated.
         *
         * <p>Clearing the cache does not invoke this method.
         *
         * @param updatedNetworks the networks that were updated
         */
        public abstract void networkCacheUpdated(List<ScoredNetwork> updatedNetworks);
    }
}
