/*
 * Copyright 2017 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 static com.android.server.wifi.WifiController.CMD_WIFI_TOGGLED;

import android.content.Context;
import android.database.ContentObserver;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiNetworkSuggestion;
import android.net.wifi.WifiScanner;
import android.os.Handler;
import android.os.Looper;
import android.os.Process;
import android.provider.Settings;
import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;


/**
 * WakeupController is responsible managing Auto Wifi.
 *
 * <p>It determines if and when to re-enable wifi after it has been turned off by the user.
 */
public class WakeupController {

    private static final String TAG = "WakeupController";

    private static final boolean USE_PLATFORM_WIFI_WAKE = true;

    private final Context mContext;
    private final Handler mHandler;
    private final FrameworkFacade mFrameworkFacade;
    private final ContentObserver mContentObserver;
    private final WakeupLock mWakeupLock;
    private final WakeupEvaluator mWakeupEvaluator;
    private final WakeupOnboarding mWakeupOnboarding;
    private final WifiConfigManager mWifiConfigManager;
    private final WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager;
    private final WifiInjector mWifiInjector;
    private final WakeupConfigStoreData mWakeupConfigStoreData;
    private final WifiWakeMetrics mWifiWakeMetrics;
    private final Clock mClock;

    private final WifiScanner.ScanListener mScanListener = new WifiScanner.ScanListener() {
        @Override
        public void onPeriodChanged(int periodInMs) {
            // no-op
        }

        @Override
        public void onResults(WifiScanner.ScanData[] results) {
            // We treat any full band scans (with DFS or not) as "full".
            boolean isFullBandScanResults =
                    results[0].getBandScanned() == WifiScanner.WIFI_BAND_BOTH_WITH_DFS
                            || results[0].getBandScanned() == WifiScanner.WIFI_BAND_BOTH;
            if (results.length == 1 && isFullBandScanResults) {
                handleScanResults(filterDfsScanResults(Arrays.asList(results[0].getResults())));
            }
        }

        @Override
        public void onFullResult(ScanResult fullScanResult) {
            // no-op
        }

        @Override
        public void onSuccess() {
            // no-op
        }

        @Override
        public void onFailure(int reason, String description) {
            Log.e(TAG, "ScanListener onFailure: " + reason + ": " + description);
        }
    };

    /** Whether this feature is enabled in Settings. */
    private boolean mWifiWakeupEnabled;

    /** Whether the WakeupController is currently active. */
    private boolean mIsActive = false;

    /** The number of scans that have been handled by the controller since last {@link #reset()}. */
    private int mNumScansHandled = 0;

    /** Whether Wifi verbose logging is enabled. */
    private boolean mVerboseLoggingEnabled;

    /**
     * The timestamp of when the Wifi network was last disconnected (either device disconnected
     * from the network or Wifi was turned off entirely).
     * Note: mLastDisconnectTimestampMillis and mLastDisconnectInfo must always be updated together.
     */
    private long mLastDisconnectTimestampMillis;

    /**
     * The SSID of the last Wifi network the device was connected to (either device disconnected
     * from the network or Wifi was turned off entirely).
     * Note: mLastDisconnectTimestampMillis and mLastDisconnectInfo must always be updated together.
     */
    private ScanResultMatchInfo mLastDisconnectInfo;

    public WakeupController(
            Context context,
            Looper looper,
            WakeupLock wakeupLock,
            WakeupEvaluator wakeupEvaluator,
            WakeupOnboarding wakeupOnboarding,
            WifiConfigManager wifiConfigManager,
            WifiConfigStore wifiConfigStore,
            WifiNetworkSuggestionsManager wifiNetworkSuggestionsManager,
            WifiWakeMetrics wifiWakeMetrics,
            WifiInjector wifiInjector,
            FrameworkFacade frameworkFacade,
            Clock clock) {
        mContext = context;
        mHandler = new Handler(looper);
        mWakeupLock = wakeupLock;
        mWakeupEvaluator = wakeupEvaluator;
        mWakeupOnboarding = wakeupOnboarding;
        mWifiConfigManager = wifiConfigManager;
        mWifiNetworkSuggestionsManager = wifiNetworkSuggestionsManager;
        mWifiWakeMetrics = wifiWakeMetrics;
        mFrameworkFacade = frameworkFacade;
        mWifiInjector = wifiInjector;
        mContentObserver = new ContentObserver(mHandler) {
            @Override
            public void onChange(boolean selfChange) {
                readWifiWakeupEnabledFromSettings();
                mWakeupOnboarding.setOnboarded();
            }
        };
        mFrameworkFacade.registerContentObserver(mContext, Settings.Global.getUriFor(
                Settings.Global.WIFI_WAKEUP_ENABLED), true, mContentObserver);
        readWifiWakeupEnabledFromSettings();

        // registering the store data here has the effect of reading the persisted value of the
        // data sources after system boot finishes
        mWakeupConfigStoreData = new WakeupConfigStoreData(
                new IsActiveDataSource(),
                mWakeupOnboarding.getIsOnboadedDataSource(),
                mWakeupOnboarding.getNotificationsDataSource(),
                mWakeupLock.getDataSource());
        wifiConfigStore.registerStoreData(mWakeupConfigStoreData);
        mClock = clock;
        mLastDisconnectTimestampMillis = 0;
        mLastDisconnectInfo = null;
    }

    private void readWifiWakeupEnabledFromSettings() {
        mWifiWakeupEnabled = mFrameworkFacade.getIntegerSetting(
                mContext, Settings.Global.WIFI_WAKEUP_ENABLED, 0) == 1;
        Log.d(TAG, "WifiWake " + (mWifiWakeupEnabled ? "enabled" : "disabled"));
    }

    private void setActive(boolean isActive) {
        if (mIsActive != isActive) {
            Log.d(TAG, "Setting active to " + isActive);
            mIsActive = isActive;
            mWifiConfigManager.saveToStore(false /* forceWrite */);
        }
    }

    /**
     * Saves the SSID of the last Wifi network that was disconnected. Should only be called before
     * WakeupController is active.
     */
    public void setLastDisconnectInfo(ScanResultMatchInfo scanResultMatchInfo) {
        if (mIsActive) {
            Log.e(TAG, "Unexpected setLastDisconnectInfo when WakeupController is active!");
            return;
        }
        if (scanResultMatchInfo == null) {
            Log.e(TAG, "Unexpected setLastDisconnectInfo(null)");
            return;
        }
        mLastDisconnectTimestampMillis = mClock.getElapsedSinceBootMillis();
        mLastDisconnectInfo = scanResultMatchInfo;
        if (mVerboseLoggingEnabled) {
            Log.d(TAG, "mLastDisconnectInfo set to " + scanResultMatchInfo);
        }
    }

    /**
     * If Wifi was disabled within LAST_DISCONNECT_TIMEOUT_MILLIS of losing a Wifi connection,
     * add that Wifi connection to the Wakeup Lock as if Wifi was disabled while connected to that
     * connection.
     * Often times, networks with poor signal intermittently connect and disconnect, causing the
     * user to manually turn off Wifi. If the Wifi was turned off during the disconnected phase of
     * the intermittent connection, then that connection normally would not be added to the Wakeup
     * Lock. This constant defines the timeout after disconnecting, in milliseconds, within which
     * if Wifi was disabled, the network would still be added to the wakeup lock.
     */
    @VisibleForTesting
    static final long LAST_DISCONNECT_TIMEOUT_MILLIS = 5 * 1000;

    /**
     * Starts listening for incoming scans.
     *
     * <p>Should only be called upon entering ScanMode. WakeupController registers its listener with
     * the WifiScanner. If the WakeupController is already active, then it returns early. Otherwise
     * it performs its initialization steps and sets {@link #mIsActive} to true.
     */
    public void start() {
        Log.d(TAG, "start()");
        mWifiInjector.getWifiScanner().registerScanListener(mScanListener);

        // If already active, we don't want to restart the session, so return early.
        if (mIsActive) {
            mWifiWakeMetrics.recordIgnoredStart();
            return;
        }
        setActive(true);

        // ensure feature is enabled and store data has been read before performing work
        if (isEnabled()) {
            mWakeupOnboarding.maybeShowNotification();

            List<ScanResult> scanResults =
                    filterDfsScanResults(mWifiInjector.getWifiScanner().getSingleScanResults());
            Set<ScanResultMatchInfo> matchInfos = toMatchInfos(scanResults);
            matchInfos.retainAll(getGoodSavedNetworksAndSuggestions());

            // ensure that the last disconnected network is added to the wakeup lock, since we don't
            // want to automatically reconnect to the same network that the user manually
            // disconnected from
            long now = mClock.getElapsedSinceBootMillis();
            if (mLastDisconnectInfo != null && ((now - mLastDisconnectTimestampMillis)
                    <= LAST_DISCONNECT_TIMEOUT_MILLIS)) {
                matchInfos.add(mLastDisconnectInfo);
                if (mVerboseLoggingEnabled) {
                    Log.d(TAG, "Added last connected network to lock: " + mLastDisconnectInfo);
                }
            }

            if (mVerboseLoggingEnabled) {
                Log.d(TAG, "Saved networks in most recent scan:" + matchInfos);
            }

            mWifiWakeMetrics.recordStartEvent(matchInfos.size());
            mWakeupLock.setLock(matchInfos);
            // TODO(b/77291248): request low latency scan here
        }
    }

    /**
     * Stops listening for scans.
     *
     * <p>Should only be called upon leaving ScanMode. It deregisters the listener from
     * WifiScanner.
     */
    public void stop() {
        Log.d(TAG, "stop()");
        mLastDisconnectTimestampMillis = 0;
        mLastDisconnectInfo = null;
        mWifiInjector.getWifiScanner().deregisterScanListener(mScanListener);
        mWakeupOnboarding.onStop();
    }

    /** Resets the WakeupController, setting {@link #mIsActive} to false. */
    public void reset() {
        Log.d(TAG, "reset()");
        mWifiWakeMetrics.recordResetEvent(mNumScansHandled);
        mNumScansHandled = 0;
        setActive(false);
    }

    /** Sets verbose logging flag based on verbose level. */
    public void enableVerboseLogging(int verbose) {
        mVerboseLoggingEnabled = verbose > 0;
        mWakeupLock.enableVerboseLogging(mVerboseLoggingEnabled);
    }

    /** Returns a list of ScanResults with DFS channels removed. */
    private List<ScanResult> filterDfsScanResults(Collection<ScanResult> scanResults) {
        int[] dfsChannels = mWifiInjector.getWifiNative()
                .getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY);
        if (dfsChannels == null) {
            dfsChannels = new int[0];
        }

        final Set<Integer> dfsChannelSet = Arrays.stream(dfsChannels).boxed()
                .collect(Collectors.toSet());

        return scanResults.stream()
                .filter(scanResult -> !dfsChannelSet.contains(scanResult.frequency))
                .collect(Collectors.toList());
    }

    /** Returns a filtered set of saved networks from WifiConfigManager & suggestions
     * from WifiNetworkSuggestionsManager. */
    private Set<ScanResultMatchInfo> getGoodSavedNetworksAndSuggestions() {
        List<WifiConfiguration> savedNetworks = mWifiConfigManager.getSavedNetworks(
                Process.WIFI_UID);

        Set<ScanResultMatchInfo> goodNetworks = new HashSet<>(savedNetworks.size());
        for (WifiConfiguration config : savedNetworks) {
            if (isWideAreaNetwork(config)
                    || config.hasNoInternetAccess()
                    || config.noInternetAccessExpected
                    || !config.getNetworkSelectionStatus().getHasEverConnected()) {
                continue;
            }
            goodNetworks.add(ScanResultMatchInfo.fromWifiConfiguration(config));
        }

        Set<WifiNetworkSuggestion> networkSuggestions =
                mWifiNetworkSuggestionsManager.getAllNetworkSuggestions();
        for (WifiNetworkSuggestion suggestion : networkSuggestions) {
            // TODO(b/127799111): Do we need to filter the list similar to saved networks above?
            goodNetworks.add(
                    ScanResultMatchInfo.fromWifiConfiguration(suggestion.wifiConfiguration));
        }
        return goodNetworks;
    }

    //TODO(b/69271702) implement WAN filtering
    private static boolean isWideAreaNetwork(WifiConfiguration config) {
        return false;
    }

    /**
     * Handles incoming scan results.
     *
     * <p>The controller updates the WakeupLock with the incoming scan results. If WakeupLock is not
     * yet fully initialized, it adds the current scanResults to the lock and returns. If WakeupLock
     * is initialized but not empty, the controller updates the lock with the current scan. If it is
     * both initialized and empty, it evaluates scan results for a match with saved networks. If a
     * match exists, it enables wifi.
     *
     * <p>The feature must be enabled and the store data must be loaded in order for the controller
     * to handle scan results.
     *
     * @param scanResults The scan results with which to update the controller
     */
    private void handleScanResults(Collection<ScanResult> scanResults) {
        if (!isEnabled()) {
            Log.d(TAG, "Attempted to handleScanResults while not enabled");
            return;
        }

        // only count scan as handled if isEnabled
        mNumScansHandled++;
        if (mVerboseLoggingEnabled) {
            Log.d(TAG, "Incoming scan #" + mNumScansHandled);
        }

        // need to show notification here in case user turns phone on while wifi is off
        mWakeupOnboarding.maybeShowNotification();

        // filter out unknown networks
        Set<ScanResultMatchInfo> goodNetworks = getGoodSavedNetworksAndSuggestions();
        Set<ScanResultMatchInfo> matchInfos = toMatchInfos(scanResults);
        matchInfos.retainAll(goodNetworks);

        mWakeupLock.update(matchInfos);
        if (!mWakeupLock.isUnlocked()) {
            return;
        }

        ScanResult network = mWakeupEvaluator.findViableNetwork(scanResults, goodNetworks);

        if (network != null) {
            Log.d(TAG, "Enabling wifi for network: " + network.SSID);
            enableWifi();
        }
    }

    /**
     * Converts ScanResults to ScanResultMatchInfos.
     */
    private static Set<ScanResultMatchInfo> toMatchInfos(Collection<ScanResult> scanResults) {
        return scanResults.stream()
                .map(ScanResultMatchInfo::fromScanResult)
                .collect(Collectors.toSet());
    }

    /**
     * Enables wifi.
     *
     * <p>This method ignores all checks and assumes that {@link WifiController} is currently
     * in ScanModeState.
     */
    private void enableWifi() {
        if (USE_PLATFORM_WIFI_WAKE) {
            // TODO(b/72180295): ensure that there is no race condition with WifiServiceImpl here
            if (mWifiInjector.getWifiSettingsStore().handleWifiToggled(true /* wifiEnabled */)) {
                mWifiInjector.getWifiController().sendMessage(CMD_WIFI_TOGGLED);
                mWifiWakeMetrics.recordWakeupEvent(mNumScansHandled);
            }
        }
    }

    /**
     * Whether the feature is currently enabled.
     *
     * <p>This method checks both the Settings value and the store data to ensure that it has been
     * read.
     */
    @VisibleForTesting
    boolean isEnabled() {
        return mWifiWakeupEnabled && mWakeupConfigStoreData.hasBeenRead();
    }

    /** Dumps wakeup controller state. */
    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        pw.println("Dump of WakeupController");
        pw.println("USE_PLATFORM_WIFI_WAKE: " + USE_PLATFORM_WIFI_WAKE);
        pw.println("mWifiWakeupEnabled: " + mWifiWakeupEnabled);
        pw.println("isOnboarded: " + mWakeupOnboarding.isOnboarded());
        pw.println("configStore hasBeenRead: " + mWakeupConfigStoreData.hasBeenRead());
        pw.println("mIsActive: " + mIsActive);
        pw.println("mNumScansHandled: " + mNumScansHandled);

        mWakeupLock.dump(fd, pw, args);
    }

    private class IsActiveDataSource implements WakeupConfigStoreData.DataSource<Boolean> {

        @Override
        public Boolean getData() {
            return mIsActive;
        }

        @Override
        public void setData(Boolean data) {
            mIsActive = data;
        }
    }
}
