/*
 * 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.customization.model.picker.quickaffordance.ui.viewmodel

import android.content.Context
import android.content.Intent
import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry
import com.android.customization.picker.quickaffordance.data.repository.KeyguardQuickAffordancePickerRepository
import com.android.customization.picker.quickaffordance.domain.interactor.KeyguardQuickAffordancePickerInteractor
import com.android.customization.picker.quickaffordance.domain.interactor.KeyguardQuickAffordanceSnapshotRestorer
import com.android.customization.picker.quickaffordance.ui.viewmodel.KeyguardQuickAffordancePickerViewModel
import com.android.customization.picker.quickaffordance.ui.viewmodel.KeyguardQuickAffordanceSlotViewModel
import com.android.customization.picker.quickaffordance.ui.viewmodel.KeyguardQuickAffordanceSummaryViewModel
import com.android.customization.picker.quickaffordance.ui.viewmodel.KeyguardQuickAffordanceViewModel
import com.android.systemui.shared.customization.data.content.CustomizationProviderClient
import com.android.systemui.shared.customization.data.content.FakeCustomizationProviderClient
import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
import com.android.wallpaper.module.InjectorProvider
import com.android.wallpaper.picker.common.icon.ui.viewmodel.Icon
import com.android.wallpaper.picker.common.text.ui.viewmodel.Text
import com.android.wallpaper.picker.undo.data.repository.UndoRepository
import com.android.wallpaper.picker.undo.domain.interactor.UndoInteractor
import com.android.wallpaper.testing.FAKE_RESTORERS
import com.android.wallpaper.testing.FakeSnapshotStore
import com.android.wallpaper.testing.TestCurrentWallpaperInfoFactory
import com.android.wallpaper.testing.TestInjector
import com.android.wallpaper.testing.collectLastValue
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertWithMessage
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.setMain
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4

@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(JUnit4::class)
class KeyguardQuickAffordancePickerViewModelTest {

    private lateinit var underTest: KeyguardQuickAffordancePickerViewModel

    private lateinit var context: Context
    private lateinit var testScope: TestScope
    private lateinit var client: FakeCustomizationProviderClient
    private lateinit var quickAffordanceInteractor: KeyguardQuickAffordancePickerInteractor

    private var latestStartedActivityIntent: Intent? = null

    @Before
    fun setUp() {
        InjectorProvider.setInjector(TestInjector())
        context = InstrumentationRegistry.getInstrumentation().targetContext
        val testDispatcher = StandardTestDispatcher()
        testScope = TestScope(testDispatcher)
        Dispatchers.setMain(testDispatcher)
        client = FakeCustomizationProviderClient()

        quickAffordanceInteractor =
            KeyguardQuickAffordancePickerInteractor(
                repository =
                    KeyguardQuickAffordancePickerRepository(
                        client = client,
                        backgroundDispatcher = testDispatcher,
                    ),
                client = client,
                snapshotRestorer = {
                    KeyguardQuickAffordanceSnapshotRestorer(
                            interactor = quickAffordanceInteractor,
                            client = client,
                        )
                        .apply { runBlocking { setUpSnapshotRestorer(FakeSnapshotStore()) } }
                },
            )
        val undoInteractor =
            UndoInteractor(
                scope = testScope.backgroundScope,
                repository = UndoRepository(),
                restorerByOwnerId = FAKE_RESTORERS,
            )
        underTest =
            KeyguardQuickAffordancePickerViewModel.Factory(
                    context = context,
                    quickAffordanceInteractor = quickAffordanceInteractor,
                    undoInteractor = undoInteractor,
                    wallpaperInfoFactory = TestCurrentWallpaperInfoFactory(context),
                    activityStarter = { intent -> latestStartedActivityIntent = intent },
                )
                .create(KeyguardQuickAffordancePickerViewModel::class.java)
    }

    @After
    fun tearDown() {
        Dispatchers.resetMain()
    }

    @Test
    fun `Select an affordance for each side`() =
        testScope.runTest {
            val slots = collectLastValue(underTest.slots)
            val quickAffordances = collectLastValue(underTest.quickAffordances)

            // Initially, the first slot is selected with the "none" affordance selected.
            assertPickerUiState(
                slots = slots(),
                affordances = quickAffordances(),
                selectedSlotText = "Left button",
                selectedAffordanceText = "None",
            )
            assertPreviewUiState(
                slots = slots(),
                expectedAffordanceNameBySlotId =
                    mapOf(
                        KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START to null,
                        KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END to null,
                    ),
            )

            // Select "affordance 1" for the first slot.
            quickAffordances()?.get(1)?.onClicked?.invoke()
            assertPickerUiState(
                slots = slots(),
                affordances = quickAffordances(),
                selectedSlotText = "Left button",
                selectedAffordanceText = FakeCustomizationProviderClient.AFFORDANCE_1,
            )
            assertPreviewUiState(
                slots = slots(),
                expectedAffordanceNameBySlotId =
                    mapOf(
                        KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START to
                            FakeCustomizationProviderClient.AFFORDANCE_1,
                        KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END to null,
                    ),
            )

            // Select an affordance for the second slot.
            // First, switch to the second slot:
            slots()?.get(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END)?.onClicked?.invoke()
            // Second, select the "affordance 3" affordance:
            quickAffordances()?.get(3)?.onClicked?.invoke()
            assertPickerUiState(
                slots = slots(),
                affordances = quickAffordances(),
                selectedSlotText = "Right button",
                selectedAffordanceText = FakeCustomizationProviderClient.AFFORDANCE_3,
            )
            assertPreviewUiState(
                slots = slots(),
                expectedAffordanceNameBySlotId =
                    mapOf(
                        KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START to
                            FakeCustomizationProviderClient.AFFORDANCE_1,
                        KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END to
                            FakeCustomizationProviderClient.AFFORDANCE_3,
                    ),
            )

            // Select a different affordance for the second slot.
            quickAffordances()?.get(2)?.onClicked?.invoke()
            assertPickerUiState(
                slots = slots(),
                affordances = quickAffordances(),
                selectedSlotText = "Right button",
                selectedAffordanceText = FakeCustomizationProviderClient.AFFORDANCE_2,
            )
            assertPreviewUiState(
                slots = slots(),
                expectedAffordanceNameBySlotId =
                    mapOf(
                        KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START to
                            FakeCustomizationProviderClient.AFFORDANCE_1,
                        KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END to
                            FakeCustomizationProviderClient.AFFORDANCE_2,
                    ),
            )
        }

    @Test
    fun `Unselect - AKA selecting the none affordance - on one side`() =
        testScope.runTest {
            val slots = collectLastValue(underTest.slots)
            val quickAffordances = collectLastValue(underTest.quickAffordances)

            // Select "affordance 1" for the first slot.
            quickAffordances()?.get(1)?.onClicked?.invoke()
            // Select an affordance for the second slot.
            // First, switch to the second slot:
            slots()?.get(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END)?.onClicked?.invoke()
            // Second, select the "affordance 3" affordance:
            quickAffordances()?.get(3)?.onClicked?.invoke()

            // Switch back to the first slot:
            slots()?.get(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START)?.onClicked?.invoke()
            // Select the "none" affordance, which is always in position 0:
            quickAffordances()?.get(0)?.onClicked?.invoke()

            assertPickerUiState(
                slots = slots(),
                affordances = quickAffordances(),
                selectedSlotText = "Left button",
                selectedAffordanceText = "None",
            )
            assertPreviewUiState(
                slots = slots(),
                expectedAffordanceNameBySlotId =
                    mapOf(
                        KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START to null,
                        KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END to
                            FakeCustomizationProviderClient.AFFORDANCE_3,
                    ),
            )
        }

    @Test
    fun `Show enablement dialog when selecting a disabled affordance`() =
        testScope.runTest {
            val slots = collectLastValue(underTest.slots)
            val quickAffordances = collectLastValue(underTest.quickAffordances)
            val dialog = collectLastValue(underTest.dialog)

            val enablementInstructions = listOf("instruction1", "instruction2")
            val enablementActionText = "enablementActionText"
            val packageName = "packageName"
            val action = "action"
            val enablementActionComponentName = "$packageName/$action"
            // Lets add a disabled affordance to the picker:
            val affordanceIndex =
                client.addAffordance(
                    CustomizationProviderClient.Affordance(
                        id = "disabled",
                        name = "disabled",
                        iconResourceId = 1,
                        isEnabled = false,
                        enablementInstructions = enablementInstructions,
                        enablementActionText = enablementActionText,
                        enablementActionComponentName = enablementActionComponentName,
                    )
                )

            // Lets try to select that disabled affordance:
            quickAffordances()?.get(affordanceIndex + 1)?.onClicked?.invoke()

            // We expect there to be a dialog that should be shown:
            assertThat(dialog()?.icon)
                .isEqualTo(Icon.Loaded(FakeCustomizationProviderClient.ICON_1, null))
            assertThat(dialog()?.title).isEqualTo(Text.Loaded("disabled"))
            assertThat(dialog()?.message)
                .isEqualTo(Text.Loaded(enablementInstructions.joinToString("\n")))
            assertThat(dialog()?.buttons?.size).isEqualTo(1)
            assertThat(dialog()?.buttons?.first()?.text)
                .isEqualTo(Text.Loaded(enablementActionText))

            // Once we report that the dialog has been dismissed by the user, we expect there to be
            // no
            // dialog to be shown:
            underTest.onDialogDismissed()
            assertThat(dialog()).isNull()
        }

    @Test
    fun `Start settings activity when long-pressing an affordance`() =
        testScope.runTest {
            val quickAffordances = collectLastValue(underTest.quickAffordances)

            // Lets add a configurable affordance to the picker:
            val configureIntent = Intent("some.action")
            val affordanceIndex =
                client.addAffordance(
                    CustomizationProviderClient.Affordance(
                        id = "affordance",
                        name = "affordance",
                        iconResourceId = 1,
                        isEnabled = true,
                        configureIntent = configureIntent,
                    )
                )

            // Lets try to long-click the affordance:
            quickAffordances()?.get(affordanceIndex + 1)?.onLongClicked?.invoke()

            assertThat(latestStartedActivityIntent).isEqualTo(configureIntent)
        }

    @Test
    fun `summary - affordance selected in both bottom-start and bottom-end`() =
        testScope.runTest {
            val slots = collectLastValue(underTest.slots)
            val quickAffordances = collectLastValue(underTest.quickAffordances)
            val summary = collectLastValue(underTest.summary)

            // Select "affordance 1" for the first slot.
            quickAffordances()?.get(1)?.onClicked?.invoke()
            // Select an affordance for the second slot.
            // First, switch to the second slot:
            slots()?.get(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END)?.onClicked?.invoke()
            // Second, select the "affordance 3" affordance:
            quickAffordances()?.get(3)?.onClicked?.invoke()

            assertThat(summary())
                .isEqualTo(
                    KeyguardQuickAffordanceSummaryViewModel(
                        description =
                            "${FakeCustomizationProviderClient.AFFORDANCE_1}," +
                                " ${FakeCustomizationProviderClient.AFFORDANCE_3}",
                        icon1 = FakeCustomizationProviderClient.ICON_1,
                        icon2 = FakeCustomizationProviderClient.ICON_3,
                    )
                )
        }

    @Test
    fun `summary - affordance selected only on bottom-start`() =
        testScope.runTest {
            val slots = collectLastValue(underTest.slots)
            val quickAffordances = collectLastValue(underTest.quickAffordances)
            val summary = collectLastValue(underTest.summary)

            // Select "affordance 1" for the first slot.
            quickAffordances()?.get(1)?.onClicked?.invoke()

            assertThat(summary())
                .isEqualTo(
                    KeyguardQuickAffordanceSummaryViewModel(
                        description = FakeCustomizationProviderClient.AFFORDANCE_1,
                        icon1 = FakeCustomizationProviderClient.ICON_1,
                        icon2 = null,
                    )
                )
        }

    @Test
    fun `summary - affordance selected only on bottom-end`() =
        testScope.runTest {
            val slots = collectLastValue(underTest.slots)
            val quickAffordances = collectLastValue(underTest.quickAffordances)
            val summary = collectLastValue(underTest.summary)

            // Select an affordance for the second slot.
            // First, switch to the second slot:
            slots()?.get(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END)?.onClicked?.invoke()
            // Second, select the "affordance 3" affordance:
            quickAffordances()?.get(3)?.onClicked?.invoke()

            assertThat(summary())
                .isEqualTo(
                    KeyguardQuickAffordanceSummaryViewModel(
                        description = FakeCustomizationProviderClient.AFFORDANCE_3,
                        icon1 = null,
                        icon2 = FakeCustomizationProviderClient.ICON_3,
                    )
                )
        }

    @Test
    fun `summary - no affordances selected`() =
        testScope.runTest {
            val slots = collectLastValue(underTest.slots)
            val quickAffordances = collectLastValue(underTest.quickAffordances)
            val summary = collectLastValue(underTest.summary)

            assertThat(summary()?.description).isEqualTo("None")
            assertThat(summary()?.icon1).isNotNull()
            assertThat(summary()?.icon2).isNull()
        }

    /**
     * Asserts the entire picker UI state is what is expected. This includes the slot tabs and the
     * affordance list.
     *
     * @param slots The observed slot view-models, keyed by slot ID
     * @param affordances The observed affordances
     * @param selectedSlotText The text of the slot that's expected to be selected
     * @param selectedAffordanceText The text of the affordance that's expected to be selected
     */
    private fun assertPickerUiState(
        slots: Map<String, KeyguardQuickAffordanceSlotViewModel>?,
        affordances: List<KeyguardQuickAffordanceViewModel>?,
        selectedSlotText: String,
        selectedAffordanceText: String,
    ) {
        assertSlotTabUiState(
            slots = slots,
            slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
            isSelected = "Left button" == selectedSlotText,
        )
        assertSlotTabUiState(
            slots = slots,
            slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END,
            isSelected = "Right button" == selectedSlotText,
        )

        var foundSelectedAffordance = false
        assertThat(affordances).isNotNull()
        affordances?.forEach { affordance ->
            val nameMatchesSelectedName = affordance.contentDescription == selectedAffordanceText
            assertWithMessage(
                    "Expected affordance with name \"${affordance.contentDescription}\" to have" +
                        " isSelected=$nameMatchesSelectedName but it was ${affordance.isSelected}"
                )
                .that(affordance.isSelected)
                .isEqualTo(nameMatchesSelectedName)
            foundSelectedAffordance = foundSelectedAffordance || nameMatchesSelectedName
        }
        assertWithMessage("No affordance is selected!").that(foundSelectedAffordance).isTrue()
    }

    /**
     * Asserts that a slot tab has the correct UI state.
     *
     * @param slots The observed slot view-models, keyed by slot ID
     * @param slotId the ID of the slot to assert
     * @param isSelected Whether that slot should be selected
     */
    private fun assertSlotTabUiState(
        slots: Map<String, KeyguardQuickAffordanceSlotViewModel>?,
        slotId: String,
        isSelected: Boolean,
    ) {
        val viewModel = slots?.get(slotId) ?: error("No slot with ID \"$slotId\"!")
        assertThat(viewModel.isSelected).isEqualTo(isSelected)
    }

    /**
     * Asserts the UI state of the preview.
     *
     * @param slots The observed slot view-models, keyed by slot ID
     * @param expectedAffordanceNameBySlotId The expected name of the selected affordance for each
     * slot ID or `null` if it's expected for there to be no affordance for that slot in the preview
     */
    private fun assertPreviewUiState(
        slots: Map<String, KeyguardQuickAffordanceSlotViewModel>?,
        expectedAffordanceNameBySlotId: Map<String, String?>,
    ) {
        assertThat(slots).isNotNull()
        slots?.forEach { (slotId, slotViewModel) ->
            val expectedAffordanceName = expectedAffordanceNameBySlotId[slotId]
            val actualAffordanceName =
                slotViewModel.selectedQuickAffordances.firstOrNull()?.contentDescription
            assertWithMessage(
                    "At slotId=\"$slotId\", expected affordance=\"$expectedAffordanceName\" but" +
                        " was \"$actualAffordanceName\"!"
                )
                .that(actualAffordanceName)
                .isEqualTo(expectedAffordanceName)
        }
    }
}
