/*
 * 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 android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * A lock to determine whether Wifi Wake can re-enable Wifi.
 *
 * <p>Wakeuplock manages a list of networks to determine whether the device's location has changed.
 */
public class WakeupLock {

    private static final String TAG = WakeupLock.class.getSimpleName();

    @VisibleForTesting
    static final int CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT = 5;
    @VisibleForTesting
    static final long MAX_LOCK_TIME_MILLIS = 10 * DateUtils.MINUTE_IN_MILLIS;

    private final WifiConfigManager mWifiConfigManager;
    private final Map<ScanResultMatchInfo, Integer> mLockedNetworks = new ArrayMap<>();
    private final WifiWakeMetrics mWifiWakeMetrics;
    private final Clock mClock;

    private boolean mVerboseLoggingEnabled;
    private long mLockTimestamp;
    private boolean mIsInitialized;
    private int mNumScans;

    public WakeupLock(WifiConfigManager wifiConfigManager, WifiWakeMetrics wifiWakeMetrics,
                      Clock clock) {
        mWifiConfigManager = wifiConfigManager;
        mWifiWakeMetrics = wifiWakeMetrics;
        mClock = clock;
    }

    /**
     * Sets the WakeupLock with the given {@link ScanResultMatchInfo} list.
     *
     * <p>This saves the wakeup lock to the store and begins the initialization process.
     *
     * @param scanResultList list of ScanResultMatchInfos to start the lock with
     */
    public void setLock(Collection<ScanResultMatchInfo> scanResultList) {
        mLockTimestamp = mClock.getElapsedSinceBootMillis();
        mIsInitialized = false;
        mNumScans = 0;

        mLockedNetworks.clear();
        for (ScanResultMatchInfo scanResultMatchInfo : scanResultList) {
            mLockedNetworks.put(scanResultMatchInfo, CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT);
        }

        Log.d(TAG, "Lock set. Number of networks: " + mLockedNetworks.size());

        mWifiConfigManager.saveToStore(false /* forceWrite */);
    }

    /**
     * Maybe sets the WakeupLock as initialized based on total scans handled.
     *
     * @param numScans total number of elapsed scans in the current WifiWake session
     */
    private void maybeSetInitializedByScans(int numScans) {
        if (mIsInitialized) {
            return;
        }
        boolean shouldBeInitialized = numScans >= CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT;
        if (shouldBeInitialized) {
            mIsInitialized = true;

            Log.d(TAG, "Lock initialized by handled scans. Scans: " + numScans);
            if (mVerboseLoggingEnabled) {
                Log.d(TAG, "State of lock: " + mLockedNetworks);
            }

            // log initialize event
            mWifiWakeMetrics.recordInitializeEvent(mNumScans, mLockedNetworks.size());
        }
    }

    /**
     * Maybe sets the WakeupLock as initialized based on elapsed time.
     *
     * @param timestampMillis current timestamp
     */
    private void maybeSetInitializedByTimeout(long timestampMillis) {
        if (mIsInitialized) {
            return;
        }
        long elapsedTime = timestampMillis - mLockTimestamp;
        boolean shouldBeInitialized = elapsedTime > MAX_LOCK_TIME_MILLIS;

        if (shouldBeInitialized) {
            mIsInitialized = true;

            Log.d(TAG, "Lock initialized by timeout. Elapsed time: " + elapsedTime);
            if (mNumScans == 0) {
                Log.w(TAG, "Lock initialized with 0 handled scans!");
            }
            if (mVerboseLoggingEnabled) {
                Log.d(TAG, "State of lock: " + mLockedNetworks);
            }

            // log initialize event
            mWifiWakeMetrics.recordInitializeEvent(mNumScans, mLockedNetworks.size());
        }
    }

    /** Returns whether the lock has been fully initialized. */
    public boolean isInitialized() {
        return mIsInitialized;
    }

    /**
     * Adds the given networks to the lock.
     *
     * <p>This is called during the initialization step.
     *
     * @param networkList The list of networks to be added
     */
    private void addToLock(Collection<ScanResultMatchInfo> networkList) {
        if (mVerboseLoggingEnabled) {
            Log.d(TAG, "Initializing lock with networks: " + networkList);
        }

        boolean hasChanged = false;

        for (ScanResultMatchInfo network : networkList) {
            if (!mLockedNetworks.containsKey(network)) {
                mLockedNetworks.put(network, CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT);
                hasChanged = true;
            }
        }

        if (hasChanged) {
            mWifiConfigManager.saveToStore(false /* forceWrite */);
        }

        // Set initialized if the lock has handled enough scans, and log the event
        maybeSetInitializedByScans(mNumScans);
    }

    /**
     * Removes networks from the lock if not present in the given {@link ScanResultMatchInfo} list.
     *
     * <p>If a network in the lock is not present in the list, reduce the number of scans
     * required to evict by one. Remove any entries in the list with 0 scans required to evict. If
     * any entries in the lock are removed, the store is updated.
     *
     * @param networkList list of present ScanResultMatchInfos to update the lock with
     */
    private void removeFromLock(Collection<ScanResultMatchInfo> networkList) {
        if (mVerboseLoggingEnabled) {
            Log.d(TAG, "Filtering lock with networks: " + networkList);
        }

        boolean hasChanged = false;
        Iterator<Map.Entry<ScanResultMatchInfo, Integer>> it =
                mLockedNetworks.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<ScanResultMatchInfo, Integer> entry = it.next();

            // if present in scan list, reset to max
            if (networkList.contains(entry.getKey())) {
                if (mVerboseLoggingEnabled) {
                    Log.d(TAG, "Found network in lock: " + entry.getKey().networkSsid);
                }
                entry.setValue(CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT);
                continue;
            }

            // decrement and remove if necessary
            entry.setValue(entry.getValue() - 1);
            if (entry.getValue() <= 0) {
                Log.d(TAG, "Removed network from lock: " + entry.getKey().networkSsid);
                it.remove();
                hasChanged = true;
            }
        }

        if (hasChanged) {
            mWifiConfigManager.saveToStore(false /* forceWrite */);
        }

        if (isUnlocked()) {
            Log.d(TAG, "Lock emptied. Recording unlock event.");
            mWifiWakeMetrics.recordUnlockEvent(mNumScans);
        }
    }

    /**
     * Updates the lock with the given {@link ScanResultMatchInfo} list.
     *
     * <p>Based on the current initialization state of the lock, either adds or removes networks
     * from the lock.
     *
     * <p>The lock is initialized after {@link #CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT}
     * scans have been handled, or after {@link #MAX_LOCK_TIME_MILLIS} milliseconds have elapsed
     * since {@link #setLock(Collection)}.
     *
     * @param networkList list of present ScanResultMatchInfos to update the lock with
     */
    public void update(Collection<ScanResultMatchInfo> networkList) {
        // update is no-op if already unlocked
        if (isUnlocked()) {
            return;
        }
        // Before checking handling the scan, we check to see whether we've exceeded the maximum
        // time allowed for initialization. If so, we set initialized and treat this scan as a
        // "removeFromLock()" instead of an "addToLock()".
        maybeSetInitializedByTimeout(mClock.getElapsedSinceBootMillis());

        mNumScans++;

        // add or remove networks based on initialized status
        if (mIsInitialized) {
            removeFromLock(networkList);
        } else {
            addToLock(networkList);
        }
    }

    /** Returns whether the WakeupLock is unlocked */
    public boolean isUnlocked() {
        return mIsInitialized && mLockedNetworks.isEmpty();
    }

    /** Returns the data source for the WakeupLock config store data. */
    public WakeupConfigStoreData.DataSource<Set<ScanResultMatchInfo>> getDataSource() {
        return new WakeupLockDataSource();
    }

    /** Dumps wakeup lock contents. */
    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        pw.println("WakeupLock: ");
        pw.println("mNumScans: " + mNumScans);
        pw.println("mIsInitialized: " + mIsInitialized);
        pw.println("Locked networks: " + mLockedNetworks.size());
        for (Map.Entry<ScanResultMatchInfo, Integer> entry : mLockedNetworks.entrySet()) {
            pw.println(entry.getKey() + ", scans to evict: " + entry.getValue());
        }
    }

    /** Set whether verbose logging is enabled. */
    public void enableVerboseLogging(boolean enabled) {
        mVerboseLoggingEnabled = enabled;
    }

    private class WakeupLockDataSource
            implements WakeupConfigStoreData.DataSource<Set<ScanResultMatchInfo>> {

        @Override
        public Set<ScanResultMatchInfo> getData() {
            return mLockedNetworks.keySet();
        }

        @Override
        public void setData(Set<ScanResultMatchInfo> data) {
            mLockedNetworks.clear();
            for (ScanResultMatchInfo network : data) {
                mLockedNetworks.put(network, CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT);
            }
            // lock is considered initialized if loaded from store
            mIsInitialized = true;
        }
    }
}
