/*
 * Copyright (C) 2022 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.systemui.statusbar.pipeline.wifi.ui.viewmodel

import androidx.test.filters.SmallTest
import com.android.settingslib.AccessibilityContentDescriptions.WIFI_CONNECTION_STRENGTH
import com.android.settingslib.AccessibilityContentDescriptions.WIFI_NO_CONNECTION
import com.android.systemui.SysuiTestCase
import com.android.systemui.common.shared.model.ContentDescription
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_FULL_ICONS
import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_NO_INTERNET_ICONS
import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_NO_NETWORK
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel
import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor
import com.android.systemui.statusbar.pipeline.wifi.shared.WifiConstants
import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiActivityModel
import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.WifiViewModel.Companion.NO_INTERNET
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.yield
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.mockito.Mock
import org.mockito.Mockito.`when` as whenever
import org.mockito.MockitoAnnotations

@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
class WifiViewModelTest : SysuiTestCase() {

    private lateinit var underTest: WifiViewModel

    @Mock private lateinit var statusBarPipelineFlags: StatusBarPipelineFlags
    @Mock private lateinit var logger: ConnectivityPipelineLogger
    @Mock private lateinit var constants: WifiConstants
    private lateinit var connectivityRepository: FakeConnectivityRepository
    private lateinit var wifiRepository: FakeWifiRepository
    private lateinit var interactor: WifiInteractor
    private lateinit var scope: CoroutineScope

    @Before
    fun setUp() {
        MockitoAnnotations.initMocks(this)
        connectivityRepository = FakeConnectivityRepository()
        wifiRepository = FakeWifiRepository()
        wifiRepository.setIsWifiEnabled(true)
        interactor = WifiInteractor(connectivityRepository, wifiRepository)
        scope = CoroutineScope(IMMEDIATE)
        createAndSetViewModel()
    }

    @After
    fun tearDown() {
        scope.cancel()
    }

    // Note on testing: [WifiViewModel] exposes 3 different instances of
    // [LocationBasedWifiViewModel]. In practice, these 3 different instances will get the exact
    // same data for icon, activity, etc. flows. So, most of these tests will test just one of the
    // instances. There are also some tests that verify all 3 instances received the same data.

    @Test
    fun wifiIcon_notEnabled_outputsNull() = runBlocking(IMMEDIATE) {
        wifiRepository.setIsWifiEnabled(false)

        // Start as non-null so we can verify we got the update
        var latest: Icon? = Icon.Resource(0, null)
        val job = underTest
            .home
            .wifiIcon
            .onEach { latest = it }
            .launchIn(this)

        wifiRepository.setWifiNetwork(WifiNetworkModel.Active(NETWORK_ID, level = 2))
        yield()

        assertThat(latest).isNull()

        job.cancel()
    }

    @Test
    fun wifiIcon_forceHidden_outputsNull() = runBlocking(IMMEDIATE) {
        connectivityRepository.setForceHiddenIcons(setOf(ConnectivitySlot.WIFI))

        // Start as non-null so we can verify we got the update
        var latest: Icon? = Icon.Resource(0, null)
        val job = underTest
            .home
            .wifiIcon
            .onEach { latest = it }
            .launchIn(this)

        wifiRepository.setWifiNetwork(WifiNetworkModel.Active(NETWORK_ID, level = 2))
        yield()

        assertThat(latest).isNull()

        job.cancel()
    }

    @Test
    fun wifiIcon_notForceHidden_outputsVisible() = runBlocking(IMMEDIATE) {
        connectivityRepository.setForceHiddenIcons(setOf())

        var latest: Icon? = null
        val job = underTest
            .home
            .wifiIcon
            .onEach { latest = it }
            .launchIn(this)

        wifiRepository.setWifiNetwork(WifiNetworkModel.Active(NETWORK_ID, level = 2))
        yield()

        assertThat(latest).isInstanceOf(Icon.Resource::class.java)

        job.cancel()
    }

    @Test
    fun wifiIcon_inactiveNetwork_outputsNoNetworkIcon() = runBlocking(IMMEDIATE) {
        var latest: Icon? = null
        val job = underTest
            .home
            .wifiIcon
            .onEach { latest = it }
            .launchIn(this)

        wifiRepository.setWifiNetwork(WifiNetworkModel.Inactive)
        yield()

        assertThat(latest).isInstanceOf(Icon.Resource::class.java)
        val icon = latest as Icon.Resource
        assertThat(icon.res).isEqualTo(WIFI_NO_NETWORK)
        assertThat(icon.contentDescription?.getAsString())
            .contains(context.getString(WIFI_NO_CONNECTION))
        assertThat(icon.contentDescription?.getAsString())
            .contains(context.getString(NO_INTERNET))

        job.cancel()
    }

    @Test
    fun wifiIcon_carrierMergedNetwork_outputsNull() = runBlocking(IMMEDIATE) {
        var latest: Icon? = Icon.Resource(0, null)
        val job = underTest
            .home
            .wifiIcon
            .onEach { latest = it }
            .launchIn(this)

        wifiRepository.setWifiNetwork(WifiNetworkModel.CarrierMerged)
        yield()

        assertThat(latest).isNull()

        job.cancel()
    }

    @Test
    fun wifiIcon_isActiveNullLevel_outputsNull() = runBlocking(IMMEDIATE) {
        var latest: Icon? = Icon.Resource(0, null)
        val job = underTest
            .home
            .wifiIcon
            .onEach { latest = it }
            .launchIn(this)

        wifiRepository.setWifiNetwork(WifiNetworkModel.Active(NETWORK_ID, level = null))
        yield()

        assertThat(latest).isNull()

        job.cancel()
    }

    @Test
    fun wifiIcon_isActiveAndValidated_level1_outputsFull1Icon() = runBlocking(IMMEDIATE) {
        var latest: Icon? = null
        val job = underTest
            .home
            .wifiIcon
            .onEach { latest = it }
            .launchIn(this)

        val level = 1
        wifiRepository.setWifiNetwork(
            WifiNetworkModel.Active(
                NETWORK_ID,
                isValidated = true,
                level,
            )
        )
        yield()

        assertThat(latest).isInstanceOf(Icon.Resource::class.java)
        val icon = latest as Icon.Resource
        assertThat(icon.res).isEqualTo(WIFI_FULL_ICONS[level])
        assertThat(icon.contentDescription?.getAsString())
            .contains(context.getString(WIFI_CONNECTION_STRENGTH[level]))
        assertThat(icon.contentDescription?.getAsString())
            .doesNotContain(context.getString(NO_INTERNET))

        job.cancel()
    }

    @Test
    fun wifiIcon_isActiveAndNotValidated_level4_outputsEmpty4Icon() = runBlocking(IMMEDIATE) {
        var latest: Icon? = null
        val job = underTest
            .home
            .wifiIcon
            .onEach { latest = it }
            .launchIn(this)

        val level = 4
        wifiRepository.setWifiNetwork(
            WifiNetworkModel.Active(
                NETWORK_ID,
                isValidated = false,
                level,
            )
        )
        yield()

        assertThat(latest).isInstanceOf(Icon.Resource::class.java)
        val icon = latest as Icon.Resource
        assertThat(icon.res).isEqualTo(WIFI_NO_INTERNET_ICONS[level])
        assertThat(icon.contentDescription?.getAsString())
            .contains(context.getString(WIFI_CONNECTION_STRENGTH[level]))
        assertThat(icon.contentDescription?.getAsString())
            .contains(context.getString(NO_INTERNET))

        job.cancel()
    }

    @Test
    fun wifiIcon_allLocationViewModelsReceiveSameData() = runBlocking(IMMEDIATE) {
        var latestHome: Icon? = null
        val jobHome = underTest
            .home
            .wifiIcon
            .onEach { latestHome = it }
            .launchIn(this)

        var latestKeyguard: Icon? = null
        val jobKeyguard = underTest
            .keyguard
            .wifiIcon
            .onEach { latestKeyguard = it }
            .launchIn(this)

        var latestQs: Icon? = null
        val jobQs = underTest
            .qs
            .wifiIcon
            .onEach { latestQs = it }
            .launchIn(this)

        wifiRepository.setWifiNetwork(
            WifiNetworkModel.Active(
                NETWORK_ID,
                isValidated = true,
                level = 1
            )
        )
        yield()

        assertThat(latestHome).isInstanceOf(Icon.Resource::class.java)
        assertThat(latestHome).isEqualTo(latestKeyguard)
        assertThat(latestKeyguard).isEqualTo(latestQs)

        jobHome.cancel()
        jobKeyguard.cancel()
        jobQs.cancel()
    }

    @Test
    fun activity_showActivityConfigFalse_outputsFalse() = runBlocking(IMMEDIATE) {
        whenever(constants.shouldShowActivityConfig).thenReturn(false)
        createAndSetViewModel()
        wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)

        var activityIn: Boolean? = null
        val activityInJob = underTest
            .home
            .isActivityInViewVisible
            .onEach { activityIn = it }
            .launchIn(this)

        var activityOut: Boolean? = null
        val activityOutJob = underTest
            .home
            .isActivityOutViewVisible
            .onEach { activityOut = it }
            .launchIn(this)

        var activityContainer: Boolean? = null
        val activityContainerJob = underTest
            .home
            .isActivityContainerVisible
            .onEach { activityContainer = it }
            .launchIn(this)

        // Verify that on launch, we receive false.
        assertThat(activityIn).isFalse()
        assertThat(activityOut).isFalse()
        assertThat(activityContainer).isFalse()

        activityInJob.cancel()
        activityOutJob.cancel()
        activityContainerJob.cancel()
    }

    @Test
    fun activity_showActivityConfigFalse_noUpdatesReceived() = runBlocking(IMMEDIATE) {
        whenever(constants.shouldShowActivityConfig).thenReturn(false)
        createAndSetViewModel()
        wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)

        var activityIn: Boolean? = null
        val activityInJob = underTest
            .home
            .isActivityInViewVisible
            .onEach { activityIn = it }
            .launchIn(this)

        var activityOut: Boolean? = null
        val activityOutJob = underTest
            .home
            .isActivityOutViewVisible
            .onEach { activityOut = it }
            .launchIn(this)

        var activityContainer: Boolean? = null
        val activityContainerJob = underTest
            .home
            .isActivityContainerVisible
            .onEach { activityContainer = it }
            .launchIn(this)

        // WHEN we update the repo to have activity
        val activity = WifiActivityModel(hasActivityIn = true, hasActivityOut = true)
        wifiRepository.setWifiActivity(activity)
        yield()

        // THEN we didn't update to the new activity (because our config is false)
        assertThat(activityIn).isFalse()
        assertThat(activityOut).isFalse()
        assertThat(activityContainer).isFalse()

        activityInJob.cancel()
        activityOutJob.cancel()
        activityContainerJob.cancel()
    }

    @Test
    fun activity_nullSsid_outputsFalse() = runBlocking(IMMEDIATE) {
        whenever(constants.shouldShowActivityConfig).thenReturn(true)
        createAndSetViewModel()

        wifiRepository.setWifiNetwork(WifiNetworkModel.Active(NETWORK_ID, ssid = null))

        var activityIn: Boolean? = null
        val activityInJob = underTest
            .home
            .isActivityInViewVisible
            .onEach { activityIn = it }
            .launchIn(this)

        var activityOut: Boolean? = null
        val activityOutJob = underTest
            .home
            .isActivityOutViewVisible
            .onEach { activityOut = it }
            .launchIn(this)

        var activityContainer: Boolean? = null
        val activityContainerJob = underTest
            .home
            .isActivityContainerVisible
            .onEach { activityContainer = it }
            .launchIn(this)

        // WHEN we update the repo to have activity
        val activity = WifiActivityModel(hasActivityIn = true, hasActivityOut = true)
        wifiRepository.setWifiActivity(activity)
        yield()

        // THEN we still output false because our network's SSID is null
        assertThat(activityIn).isFalse()
        assertThat(activityOut).isFalse()
        assertThat(activityContainer).isFalse()

        activityInJob.cancel()
        activityOutJob.cancel()
        activityContainerJob.cancel()
    }

    @Test
    fun activity_allLocationViewModelsReceiveSameData() = runBlocking(IMMEDIATE) {
        whenever(constants.shouldShowActivityConfig).thenReturn(true)
        createAndSetViewModel()
        wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)

        var latestHome: Boolean? = null
        val jobHome = underTest
            .home
            .isActivityInViewVisible
            .onEach { latestHome = it }
            .launchIn(this)

        var latestKeyguard: Boolean? = null
        val jobKeyguard = underTest
            .keyguard
            .isActivityInViewVisible
            .onEach { latestKeyguard = it }
            .launchIn(this)

        var latestQs: Boolean? = null
        val jobQs = underTest
            .qs
            .isActivityInViewVisible
            .onEach { latestQs = it }
            .launchIn(this)

        val activity = WifiActivityModel(hasActivityIn = true, hasActivityOut = true)
        wifiRepository.setWifiActivity(activity)
        yield()

        assertThat(latestHome).isTrue()
        assertThat(latestKeyguard).isTrue()
        assertThat(latestQs).isTrue()

        jobHome.cancel()
        jobKeyguard.cancel()
        jobQs.cancel()
    }

    @Test
    fun activityIn_hasActivityInTrue_outputsTrue() = runBlocking(IMMEDIATE) {
        whenever(constants.shouldShowActivityConfig).thenReturn(true)
        createAndSetViewModel()
        wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)

        var latest: Boolean? = null
        val job = underTest
            .home
            .isActivityInViewVisible
            .onEach { latest = it }
            .launchIn(this)

        val activity = WifiActivityModel(hasActivityIn = true, hasActivityOut = false)
        wifiRepository.setWifiActivity(activity)
        yield()

        assertThat(latest).isTrue()

        job.cancel()
    }

    @Test
    fun activityIn_hasActivityInFalse_outputsFalse() = runBlocking(IMMEDIATE) {
        whenever(constants.shouldShowActivityConfig).thenReturn(true)
        createAndSetViewModel()
        wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)

        var latest: Boolean? = null
        val job = underTest
            .home
            .isActivityInViewVisible
            .onEach { latest = it }
            .launchIn(this)

        val activity = WifiActivityModel(hasActivityIn = false, hasActivityOut = true)
        wifiRepository.setWifiActivity(activity)
        yield()

        assertThat(latest).isFalse()

        job.cancel()
    }

    @Test
    fun activityOut_hasActivityOutTrue_outputsTrue() = runBlocking(IMMEDIATE) {
        whenever(constants.shouldShowActivityConfig).thenReturn(true)
        createAndSetViewModel()
        wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)

        var latest: Boolean? = null
        val job = underTest
            .home
            .isActivityOutViewVisible
            .onEach { latest = it }
            .launchIn(this)

        val activity = WifiActivityModel(hasActivityIn = false, hasActivityOut = true)
        wifiRepository.setWifiActivity(activity)
        yield()

        assertThat(latest).isTrue()

        job.cancel()
    }

    @Test
    fun activityOut_hasActivityOutFalse_outputsFalse() = runBlocking(IMMEDIATE) {
        whenever(constants.shouldShowActivityConfig).thenReturn(true)
        createAndSetViewModel()
        wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)

        var latest: Boolean? = null
        val job = underTest
            .home
            .isActivityOutViewVisible
            .onEach { latest = it }
            .launchIn(this)

        val activity = WifiActivityModel(hasActivityIn = true, hasActivityOut = false)
        wifiRepository.setWifiActivity(activity)
        yield()

        assertThat(latest).isFalse()

        job.cancel()
    }

    @Test
    fun activityContainer_hasActivityInTrue_outputsTrue() = runBlocking(IMMEDIATE) {
        whenever(constants.shouldShowActivityConfig).thenReturn(true)
        createAndSetViewModel()
        wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)

        var latest: Boolean? = null
        val job = underTest
            .home
            .isActivityContainerVisible
            .onEach { latest = it }
            .launchIn(this)

        val activity = WifiActivityModel(hasActivityIn = true, hasActivityOut = false)
        wifiRepository.setWifiActivity(activity)
        yield()

        assertThat(latest).isTrue()

        job.cancel()
    }

    @Test
    fun activityContainer_hasActivityOutTrue_outputsTrue() = runBlocking(IMMEDIATE) {
        whenever(constants.shouldShowActivityConfig).thenReturn(true)
        createAndSetViewModel()
        wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)

        var latest: Boolean? = null
        val job = underTest
            .home
            .isActivityContainerVisible
            .onEach { latest = it }
            .launchIn(this)

        val activity = WifiActivityModel(hasActivityIn = false, hasActivityOut = true)
        wifiRepository.setWifiActivity(activity)
        yield()

        assertThat(latest).isTrue()

        job.cancel()
    }

    @Test
    fun activityContainer_inAndOutTrue_outputsTrue() = runBlocking(IMMEDIATE) {
        whenever(constants.shouldShowActivityConfig).thenReturn(true)
        createAndSetViewModel()
        wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)

        var latest: Boolean? = null
        val job = underTest
            .home
            .isActivityContainerVisible
            .onEach { latest = it }
            .launchIn(this)

        val activity = WifiActivityModel(hasActivityIn = true, hasActivityOut = true)
        wifiRepository.setWifiActivity(activity)
        yield()

        assertThat(latest).isTrue()

        job.cancel()
    }

    @Test
    fun activityContainer_inAndOutFalse_outputsFalse() = runBlocking(IMMEDIATE) {
        whenever(constants.shouldShowActivityConfig).thenReturn(true)
        createAndSetViewModel()
        wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)

        var latest: Boolean? = null
        val job = underTest
            .home
            .isActivityContainerVisible
            .onEach { latest = it }
            .launchIn(this)

        val activity = WifiActivityModel(hasActivityIn = false, hasActivityOut = false)
        wifiRepository.setWifiActivity(activity)
        yield()

        assertThat(latest).isFalse()

        job.cancel()
    }

    private fun createAndSetViewModel() {
        // [WifiViewModel] creates its flows as soon as it's instantiated, and some of those flow
        // creations rely on certain config values that we mock out in individual tests. This method
        // allows tests to create the view model only after those configs are correctly set up.
        underTest = WifiViewModel(
            constants,
            context,
            logger,
            interactor,
            scope,
            statusBarPipelineFlags,
        )
    }

    private fun ContentDescription.getAsString(): String? {
        return when (this) {
            is ContentDescription.Loaded -> this.description
            is ContentDescription.Resource -> context.getString(this.res)
        }
    }

    companion object {
        private const val NETWORK_ID = 2
        private val ACTIVE_VALID_WIFI_NETWORK = WifiNetworkModel.Active(NETWORK_ID, ssid = "AB")
    }
}

private val IMMEDIATE = Dispatchers.Main.immediate
