/*
 * Copyright (C) 2015 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 org.junit.Assert.*;
import static org.junit.Assume.*;
import static org.mockito.Mockito.*;

import android.net.wifi.ScanResult;
import android.net.wifi.WifiScanner;
import android.net.wifi.WifiScanner.ScanData;
import android.net.wifi.WifiSsid;

import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeDiagnosingMatcher;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * Utilities for testing Wifi Scanning
 */
public class ScanTestUtil {

    public static void setupMockChannels(WifiNative wifiNative, int[] channels24, int[] channels5,
            int[] channelsDfs) throws Exception {
        when(wifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_24_GHZ))
                .thenReturn(channels24);
        when(wifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ))
                .thenReturn(channels5);
        when(wifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY))
                .thenReturn(channelsDfs);
    }

    public static WifiScanner.ScanSettings createRequest(WifiScanner.ChannelSpec[] channels,
            int period, int batch, int bssidsPerScan, int reportEvents) {
        WifiScanner.ScanSettings request = new WifiScanner.ScanSettings();
        request.band = WifiScanner.WIFI_BAND_UNSPECIFIED;
        request.channels = channels;
        request.periodInMs = period;
        request.numBssidsPerScan = bssidsPerScan;
        request.maxScansToCache = batch;
        request.reportEvents = reportEvents;
        return request;
    }

    public static WifiScanner.ScanSettings createRequest(int band, int period, int batch,
            int bssidsPerScan, int reportEvents) {
        return createRequest(band, period, 0, 0, batch, bssidsPerScan, reportEvents);
    }

    /**
     * Create an exponential back off scan request if maxPeriod != period && maxPeriod != 0.
     */
    public static WifiScanner.ScanSettings createRequest(int band, int period, int maxPeriod,
            int stepCount, int batch, int bssidsPerScan, int reportEvents) {
        WifiScanner.ScanSettings request = new WifiScanner.ScanSettings();
        request.band = band;
        request.channels = null;
        request.periodInMs = period;
        request.maxPeriodInMs = maxPeriod;
        request.stepCount = stepCount;
        request.numBssidsPerScan = bssidsPerScan;
        request.maxScansToCache = batch;
        request.reportEvents = reportEvents;
        return request;
    }

    /**
     * Builder to create WifiNative.ScanSettings objects for testing
     */
    public static class NativeScanSettingsBuilder {
        private final WifiNative.ScanSettings mSettings = new WifiNative.ScanSettings();
        public NativeScanSettingsBuilder() {
            mSettings.buckets = new WifiNative.BucketSettings[0];
            mSettings.num_buckets = 0;
            mSettings.report_threshold_percent = 100;
        }

        public NativeScanSettingsBuilder withBasePeriod(int basePeriod) {
            mSettings.base_period_ms = basePeriod;
            return this;
        }
        public NativeScanSettingsBuilder withMaxApPerScan(int maxAp) {
            mSettings.max_ap_per_scan = maxAp;
            return this;
        }
        public NativeScanSettingsBuilder withMaxScansToCache(int maxScans) {
            mSettings.report_threshold_num_scans = maxScans;
            return this;
        }
        public NativeScanSettingsBuilder withMaxPercentToCache(int percent) {
            mSettings.report_threshold_percent = percent;
            return this;
        }

        /**
         * Add the provided hidden network SSIDs to scan request.
         * @param networkSSIDs List of hidden network SSIDs
         * @return builder object
         */
        public NativeScanSettingsBuilder withHiddenNetworkSSIDs(String[] networkSSIDs) {
            mSettings.hiddenNetworks = new WifiNative.HiddenNetwork[networkSSIDs.length];
            for (int i = 0; i < networkSSIDs.length; i++) {
                mSettings.hiddenNetworks[i] = new WifiNative.HiddenNetwork();
                mSettings.hiddenNetworks[i].ssid = networkSSIDs[i];
            }
            return this;
        }

        public NativeScanSettingsBuilder addBucketWithBand(
                int period, int reportEvents, int band) {
            WifiNative.BucketSettings bucket = new WifiNative.BucketSettings();
            bucket.bucket = mSettings.num_buckets;
            bucket.band = band;
            bucket.period_ms = period;
            bucket.report_events = reportEvents;
            return addBucket(bucket);
        }

        public NativeScanSettingsBuilder addBucketWithChannels(
                int period, int reportEvents, WifiScanner.ChannelSpec... channels) {
            int[] channelFreqs = new int[channels.length];
            for (int i = 0; i < channels.length; ++i) {
                channelFreqs[i] = channels[i].frequency;
            }
            return addBucketWithChannels(period, reportEvents, channelFreqs);
        }

        public NativeScanSettingsBuilder addBucketWithChannels(
                int period, int reportEvents, int... channels) {
            WifiNative.BucketSettings bucket = new WifiNative.BucketSettings();
            bucket.bucket = mSettings.num_buckets;
            bucket.band = WifiScanner.WIFI_BAND_UNSPECIFIED;
            bucket.num_channels = channels.length;
            bucket.channels = channelsToNativeSettings(channels);
            bucket.period_ms = period;
            bucket.report_events = reportEvents;
            return addBucket(bucket);
        }

        public NativeScanSettingsBuilder addBucket(WifiNative.BucketSettings bucket) {
            mSettings.buckets = Arrays.copyOf(mSettings.buckets, mSettings.num_buckets + 1);
            mSettings.buckets[mSettings.num_buckets] = bucket;
            mSettings.num_buckets = mSettings.num_buckets + 1;
            return this;
        }

        public WifiNative.ScanSettings build() {
            return mSettings;
        }
    }

    /**
     * Compute the expected native scan settings that are expected for the given
     * WifiScanner.ScanSettings.
     */
    public static WifiNative.ScanSettings computeSingleScanNativeSettings(
            WifiScanner.ScanSettings requestSettings) {
        int reportEvents = requestSettings.reportEvents | WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN;
        NativeScanSettingsBuilder builder = new NativeScanSettingsBuilder()
                .withBasePeriod(0)
                .withMaxApPerScan(0)
                .withMaxPercentToCache(0)
                .withMaxScansToCache(0);
        if (requestSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
            builder.addBucketWithChannels(0, reportEvents, requestSettings.channels);
        } else {
            builder.addBucketWithBand(0, reportEvents, requestSettings.band);
        }

        return builder.build();
    }

    /**
     * Compute the expected native scan settings that are expected for the given channels.
     */
    public static WifiNative.ScanSettings createSingleScanNativeSettingsForChannels(
            int reportEvents, WifiScanner.ChannelSpec... channels) {
        int actualReportEvents = reportEvents | WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN;
        return new NativeScanSettingsBuilder()
                .withBasePeriod(0)
                .withMaxApPerScan(0)
                .withMaxPercentToCache(0)
                .withMaxScansToCache(0)
                .addBucketWithChannels(0, actualReportEvents, channels)
                .build();
    }

    public static Set<Integer> createFreqSet(int... elements) {
        Set<Integer> set = new HashSet<>();
        for (int e : elements) {
            set.add(e);
        }
        return set;
    }

    public static ScanResult createScanResult(int freq) {
        return new ScanResult(WifiSsid.createFromAsciiEncoded("AN SSID"), "00:00:00:00:00:00", 0L,
                -1, null, "", 0, freq, 0);
    }

    private static ScanData createScanData(int[] freqs, int bucketsScanned) {
        ScanResult[] results = new ScanResult[freqs.length];
        for (int i = 0; i < freqs.length; ++i) {
            results[i] = createScanResult(freqs[i]);
        }
        return new ScanData(0, 0, bucketsScanned, false, results);
    }

    public static ScanData[] createScanDatas(int[][] freqs, int[] bucketsScanned) {
        assumeTrue(freqs.length == bucketsScanned.length);
        ScanData[] data = new ScanData[freqs.length];
        for (int i = 0; i < freqs.length; ++i) {
            data[i] = createScanData(freqs[i], bucketsScanned[i]);
        }
        return data;
    }

    public static ScanData[] createScanDatas(int[][] freqs) {
        return createScanDatas(freqs, new int[freqs.length] /* defaults all 0 */);
    }

    private static void assertScanResultEquals(
            String prefix, ScanResult expected, ScanResult actual) {
        assertEquals(prefix + "SSID", expected.SSID, actual.SSID);
        assertEquals(prefix + "wifiSsid", expected.wifiSsid.toString(), actual.wifiSsid.toString());
        assertEquals(prefix + "BSSID", expected.BSSID, actual.BSSID);
        assertEquals(prefix + "capabilities", expected.capabilities, actual.capabilities);
        assertEquals(prefix + "level", expected.level, actual.level);
        assertEquals(prefix + "frequency", expected.frequency, actual.frequency);
        assertEquals(prefix + "timestamp", expected.timestamp, actual.timestamp);
        assertEquals(prefix + "seen", expected.seen, actual.seen);
    }

    private static void assertScanResultsEquals(String prefix, ScanResult[] expected,
            ScanResult[] actual) {
        assertNotNull(prefix + "expected ScanResults was null", expected);
        assertNotNull(prefix + "actual ScanResults was null", actual);
        assertEquals(prefix + "results.length", expected.length, actual.length);
        for (int j = 0; j < expected.length; ++j) {
            ScanResult expectedResult = expected[j];
            ScanResult actualResult = actual[j];
            assertScanResultEquals(prefix + "results[" + j + "]", actualResult, expectedResult);
        }
    }

    /**
     * Asserts if the provided scan results are the same.
     */
    public static void assertScanResultEquals(ScanResult expected, ScanResult actual) {
        assertScanResultEquals("", expected, actual);
    }

    /**
     * Asserts if the provided scan result arrays are the same.
     */
    public static void assertScanResultsEquals(ScanResult[] expected, ScanResult[] actual) {
        assertScanResultsEquals("", expected, actual);
    }

    private static void assertScanDataEquals(String prefix, ScanData expected, ScanData actual) {
        assertNotNull(prefix + "expected ScanData was null", expected);
        assertNotNull(prefix + "actual ScanData was null", actual);
        assertEquals(prefix + "id", expected.getId(), actual.getId());
        assertEquals(prefix + "flags", expected.getFlags(), actual.getFlags());
        assertEquals(prefix + "all channels", expected.isAllChannelsScanned(),
                actual.isAllChannelsScanned());
        assertScanResultsEquals(prefix, expected.getResults(), actual.getResults());
    }

    public static void assertScanDataEquals(ScanData expected, ScanData actual) {
        assertScanDataEquals("", expected, actual);
    }

    public static void assertScanDatasEquals(String prefix, ScanData[] expected, ScanData[] actual) {
        assertNotNull("expected " + prefix + "ScanData[] was null", expected);
        assertNotNull("actaul " + prefix + "ScanData[] was null", actual);
        assertEquals(prefix + "ScanData.length", expected.length, actual.length);
        for (int i = 0; i < expected.length; ++i) {
            assertScanDataEquals(prefix + "ScanData[" + i + "].", expected[i], actual[i]);
        }
    }

    public static void assertScanDatasEquals(ScanData[] expected, ScanData[] actual) {
        assertScanDatasEquals("", expected, actual);
    }

    public static WifiScanner.ChannelSpec[] channelsToSpec(int... channels) {
        WifiScanner.ChannelSpec[] channelSpecs = new WifiScanner.ChannelSpec[channels.length];
        for (int i = 0; i < channels.length; ++i) {
            channelSpecs[i] = new WifiScanner.ChannelSpec(channels[i]);
        }
        return channelSpecs;
    }

    public static void assertNativeScanSettingsEquals(WifiNative.ScanSettings expected,
            WifiNative.ScanSettings actual) {
        assertEquals("bssids per scan", expected.max_ap_per_scan, actual.max_ap_per_scan);
        assertEquals("scans to cache", expected.report_threshold_num_scans,
                actual.report_threshold_num_scans);
        assertEquals("percent to cache", expected.report_threshold_percent,
                actual.report_threshold_percent);
        assertEquals("base period", expected.base_period_ms, actual.base_period_ms);

        assertEquals("number of buckets", expected.num_buckets, actual.num_buckets);
        assertNotNull("buckets was null", actual.buckets);
        for (int i = 0; i < expected.buckets.length; ++i) {
            assertNotNull("buckets[" + i + "] was null", actual.buckets[i]);
            assertEquals("buckets[" + i + "].period",
                    expected.buckets[i].period_ms, actual.buckets[i].period_ms);
            assertEquals("buckets[" + i + "].reportEvents",
                    expected.buckets[i].report_events, actual.buckets[i].report_events);

            assertEquals("buckets[" + i + "].band",
                    expected.buckets[i].band, actual.buckets[i].band);
            if (expected.buckets[i].band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
                Set<Integer> expectedChannels = new HashSet<>();
                for (WifiNative.ChannelSettings channel : expected.buckets[i].channels) {
                    expectedChannels.add(channel.frequency);
                }
                Set<Integer> actualChannels = new HashSet<>();
                for (WifiNative.ChannelSettings channel : actual.buckets[i].channels) {
                    actualChannels.add(channel.frequency);
                }
                assertEquals("channels", expectedChannels, actualChannels);
            } else {
                // since num_channels and channels are ignored when band is not
                // WifiScanner.WIFI_BAND_UNSPECIFIED just assert that there are no channels
                // the band equality was already checked above
                assertEquals("buckets[" + i + "].num_channels not 0", 0,
                        actual.buckets[i].num_channels);
                assertTrue("buckets[" + i + "].channels not null or empty",
                        actual.buckets[i].channels == null
                        || actual.buckets[i].channels.length == 0);
            }
        }
    }

    /**
     * Asserts if the provided pno settings are the same.
     */
    public static void assertNativePnoSettingsEquals(WifiNative.PnoSettings expected,
            WifiNative.PnoSettings actual) {
        assertNotNull("expected was null", expected);
        assertNotNull("actaul was null", actual);
        assertEquals("min5GHzRssi", expected.min5GHzRssi, actual.min5GHzRssi);
        assertEquals("min24GHzRssi", expected.min24GHzRssi, actual.min24GHzRssi);
        assertEquals("initialScoreMax", expected.initialScoreMax, actual.initialScoreMax);
        assertEquals("currentConnectionBonus", expected.currentConnectionBonus,
                actual.currentConnectionBonus);
        assertEquals("sameNetworkBonus", expected.sameNetworkBonus, actual.sameNetworkBonus);
        assertEquals("secureBonus", expected.secureBonus, actual.secureBonus);
        assertEquals("band5GHzBonus", expected.band5GHzBonus, actual.band5GHzBonus);
        assertEquals("isConnected", expected.isConnected, actual.isConnected);
        assertNotNull("expected networkList was null", expected.networkList);
        assertNotNull("actual networkList was null", actual.networkList);
        assertEquals("networkList.length", expected.networkList.length, actual.networkList.length);
        for (int i = 0; i < expected.networkList.length; i++) {
            assertEquals("networkList[" + i + "].ssid",
                    expected.networkList[i].ssid, actual.networkList[i].ssid);
            assertEquals("networkList[" + i + "].flags",
                    expected.networkList[i].flags, actual.networkList[i].flags);
            assertEquals("networkList[" + i + "].auth_bit_field",
                    expected.networkList[i].auth_bit_field, actual.networkList[i].auth_bit_field);
        }
    }

    /**
     * Convert a list of channel frequencies to an array of equivalent WifiNative.ChannelSettings
     */
    public static WifiNative.ChannelSettings[] channelsToNativeSettings(int... channels) {
        WifiNative.ChannelSettings[] channelSpecs = new WifiNative.ChannelSettings[channels.length];
        for (int i = 0; i < channels.length; ++i) {
            channelSpecs[i] = new WifiNative.ChannelSettings();
            channelSpecs[i].frequency = channels[i];
        }
        return channelSpecs;
    }

    /**
     * Matcher to check that a BucketSettings has the given band
     */
    public static Matcher<WifiNative.BucketSettings> bandIs(final int expectedBand) {
        return new TypeSafeDiagnosingMatcher<WifiNative.BucketSettings>() {
            @Override
            public boolean matchesSafely(WifiNative.BucketSettings bucketSettings,
                    Description mismatchDescription) {
                if (bucketSettings.band != expectedBand) {
                    mismatchDescription
                            .appendText("did not have expected band ").appendValue(expectedBand)
                            .appendText(", was ").appendValue(bucketSettings.band);
                    return false;
                } else {
                    return true;
                }
            }

            @Override
            public void describeTo(final Description description) {
                description.appendText("bucket band is ").appendValue(expectedBand);
            }
        };
    }

    /**
     * Matcher to check that a BucketSettings has exactly the given channels
     */
    public static Matcher<WifiNative.BucketSettings> channelsAre(final int... expectedChannels) {
        return new TypeSafeDiagnosingMatcher<WifiNative.BucketSettings>() {
            @Override
            public boolean matchesSafely(WifiNative.BucketSettings bucketSettings,
                    Description mismatchDescription) {
                if (bucketSettings.band != WifiScanner.WIFI_BAND_UNSPECIFIED) {
                    mismatchDescription.appendText("did not have expected unspecified band, was ")
                            .appendValue(bucketSettings.band);
                    return false;
                } else if (bucketSettings.num_channels != expectedChannels.length) {
                    mismatchDescription
                            .appendText("did not have expected num_channels ")
                            .appendValue(expectedChannels.length)
                            .appendText(", was ").appendValue(bucketSettings.num_channels);
                    return false;
                } else if (bucketSettings.channels == null) {
                    mismatchDescription.appendText("had null channels array");
                    return false;
                } else if (bucketSettings.channels.length != expectedChannels.length) {
                    mismatchDescription
                            .appendText("did not have channels array length matching excepted ")
                            .appendValue(expectedChannels.length)
                            .appendText(", was ").appendValue(bucketSettings.channels.length);
                    return false;
                } else {
                    Set<Integer> foundChannelsSet = new HashSet<>();
                    for (int i = 0; i < bucketSettings.channels.length; ++i) {
                        foundChannelsSet.add(bucketSettings.channels[i].frequency);
                    }
                    Set<Integer> expectedChannelsSet = new HashSet<>();
                    for (int i = 0; i < expectedChannels.length; ++i) {
                        expectedChannelsSet.add(expectedChannels[i]);
                    }

                    if (!foundChannelsSet.containsAll(expectedChannelsSet)
                            || foundChannelsSet.size() != expectedChannelsSet.size()) {
                        Set<Integer> extraChannelsSet = new HashSet<>(foundChannelsSet);
                        extraChannelsSet.removeAll(expectedChannelsSet);
                        expectedChannelsSet.removeAll(foundChannelsSet);
                        mismatchDescription
                                .appendText("does not contain expected channels ")
                                .appendValue(expectedChannelsSet);
                        if (extraChannelsSet.size() > 0) {
                            mismatchDescription
                                    .appendText(", but contains extra channels ")
                                    .appendValue(extraChannelsSet);
                        }
                        return false;
                    } else {
                        return true;
                    }
                }
            }

            @Override
            public void describeTo(final Description description) {
                description.appendText("bucket channels are ").appendValue(expectedChannels);
            }
        };
    }
}
