/*
 * Copyright 2023 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 androidx.tv.material3

import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.focusable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.text.BasicText
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.key.Key
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.semantics.SemanticsNode
import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.SemanticsNodeInteraction
import androidx.compose.ui.test.SemanticsNodeInteractionCollection
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertIsEqualTo
import androidx.compose.ui.test.assertIsFocused
import androidx.compose.ui.test.assertIsNotFocused
import androidx.compose.ui.test.assertWidthIsEqualTo
import androidx.compose.ui.test.getUnclippedBoundsInRoot
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onAllNodesWithText
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onRoot
import androidx.compose.ui.test.performKeyInput
import androidx.compose.ui.test.pressKey
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.DpRect
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.toSize
import androidx.test.platform.app.InstrumentationRegistry
import org.junit.Rule
import org.junit.Test

@OptIn(ExperimentalTvMaterial3Api::class)
class ModalNavigationDrawerTest {
    @get:Rule
    val rule = createComposeRule()

    @Test
    fun modalNavigationDrawer_initialStateClosed_closedStateComposableDisplayed() {
        rule.setContent {
            ModalNavigationDrawer(
                drawerState = remember { DrawerState(DrawerValue.Closed) },
                drawerContent = {
                    BasicText(text = if (it == DrawerValue.Open) "Opened" else "Closed")
                }
            ) { Box(Modifier.size(200.dp)) }
        }

        rule.onAllNodesWithText("Closed").assertAnyAreDisplayed()
    }

    @Test
    fun modalNavigationDrawer_initialStateOpen_openStateComposableDisplayed() {
        rule.setContent {
            ModalNavigationDrawer(
                drawerState = remember { DrawerState(DrawerValue.Open) },
                drawerContent = {
                    BasicText(text = if (it == DrawerValue.Open) "Opened" else "Closed")
                }) { BasicText("other content") }
        }

        rule.onAllNodesWithText("Opened").assertAnyAreDisplayed()
    }

    @Test
    fun modalNavigationDrawer_focusInsideDrawer_openedStateComposableDisplayed() {
        InstrumentationRegistry.getInstrumentation().setInTouchMode(false)
        val drawerFocusRequester = FocusRequester()
        rule.setContent {
            val navigationDrawerValue = remember { DrawerState(DrawerValue.Closed) }
            ModalNavigationDrawer(
                modifier = Modifier.focusRequester(drawerFocusRequester),
                drawerState = navigationDrawerValue,
                drawerContent = {
                    BasicText(
                        modifier = Modifier.focusable(),
                        text = if (it == DrawerValue.Open) "Opened" else "Closed"
                    )
                }) { BasicText("other content") }
        }

        rule.onAllNodesWithText("Closed").assertAnyAreDisplayed()

        rule.runOnIdle {
            drawerFocusRequester.requestFocus()
        }

        rule.onAllNodesWithText("Opened").assertAnyAreDisplayed()
    }

    @OptIn(ExperimentalTestApi::class, ExperimentalComposeUiApi::class)
    @Test
    fun modalNavigationDrawer_focusMovesOutOfDrawer_closedStateComposableDisplayed() {
        InstrumentationRegistry.getInstrumentation().setInTouchMode(false)
        val drawerFocusRequester = FocusRequester()
        rule.setContent {
            val navigationDrawerValue = remember { DrawerState(DrawerValue.Closed) }
            Row {
                ModalNavigationDrawer(
                    modifier = Modifier
                        .focusRequester(drawerFocusRequester)
                        .focusable(false),
                    drawerState = navigationDrawerValue,
                    drawerContent = {
                        BasicText(
                            modifier = Modifier.focusable(),
                            text = if (it == DrawerValue.Open) "Opened" else "Closed"
                        )
                    }) {
                    Box(modifier = Modifier.focusable()) {
                        BasicText("Button")
                    }
                }
            }
        }
        rule.runOnIdle {
            drawerFocusRequester.requestFocus()
        }
        rule.onAllNodesWithText("Opened").assertAnyAreDisplayed()
        rule.onRoot().performKeyInput { pressKey(Key.DirectionRight) }
        rule.onAllNodesWithText("Closed").assertAnyAreDisplayed()
    }

    @OptIn(ExperimentalTestApi::class)
    @Test
    fun modalNavigationDrawer_focusMovesIntoDrawer_openStateComposableDisplayed() {
        InstrumentationRegistry.getInstrumentation().setInTouchMode(false)
        val buttonFocusRequester = FocusRequester()
        rule.setContent {
            val navigationDrawerValue = remember { DrawerState(DrawerValue.Closed) }
            Row {
                ModalNavigationDrawer(
                    drawerState = navigationDrawerValue,
                    drawerContent = {
                        var isFocused by remember { mutableStateOf(false) }
                        BasicText(
                            text = if (it == DrawerValue.Open) "Opened" else "Closed",
                            modifier = Modifier
                                .onFocusChanged { focusState ->
                                    isFocused = focusState.isFocused
                                }
                                .background(if (isFocused) Color.Green else Color.Yellow)
                                .focusable()
                                .testTag("drawerItem")
                        )
                    }) {
                    Box(
                        modifier = Modifier
                            .focusRequester(buttonFocusRequester)
                            .focusable()
                    ) {
                        BasicText("Button")
                    }
                }
            }
        }
        rule.runOnIdle {
            buttonFocusRequester.requestFocus()
        }
        rule.onAllNodesWithText("Closed").assertAnyAreDisplayed()
        rule.onRoot().performKeyInput { pressKey(Key.DirectionLeft) }
        rule.waitForIdle()
        rule.onAllNodesWithText("Opened").assertAnyAreDisplayed()
        rule.onNodeWithTag("drawerItem").assertIsFocused()
    }

    @Test
    fun modalNavigationDrawer_closedState_widthOfDrawerIsWidthOfContent() {
        val contentWidthBoxTag = "contentWidthBox"
        val totalWidth = 100.dp
        val closedDrawerContentWidth = 30.dp
        val expectedContentWidth = totalWidth - closedDrawerContentWidth
        rule.setContent {
            Box(modifier = Modifier.width(totalWidth)) {
                NavigationDrawer(
                    drawerState = remember { DrawerState(DrawerValue.Closed) },
                    drawerContent = {
                        Box(Modifier.width(closedDrawerContentWidth)) {
                            // extra long content wrapped in a drawer-width restricting box
                            Box(Modifier.width(closedDrawerContentWidth * 10))
                        }
                    }
                ) { Box(
                    Modifier
                        .fillMaxWidth()
                        .testTag(contentWidthBoxTag)) }
            }
        }

        rule.onNodeWithTag(contentWidthBoxTag).assertWidthIsEqualTo(expectedContentWidth)
    }

    @Test
    fun modalNavigationDrawer_openState_widthOfDrawerIsWidthOfContent() {
        val contentWidthBoxTag = "contentWidthBox"
        val totalWidth = 100.dp
        val openDrawerContentWidth = 70.dp
        val expectedContentWidth = totalWidth - openDrawerContentWidth
        rule.setContent {
            Box(modifier = Modifier.width(totalWidth)) {
                NavigationDrawer(
                    drawerState = remember { DrawerState(DrawerValue.Closed) },
                    drawerContent = {
                        Box(Modifier.width(openDrawerContentWidth)) {
                            Box(Modifier.width(openDrawerContentWidth * 10))
                        }
                    }
                ) { Box(
                    Modifier
                        .fillMaxWidth()
                        .testTag(contentWidthBoxTag)) }
            }
        }

        rule.onNodeWithTag(contentWidthBoxTag).assertWidthIsEqualTo(expectedContentWidth)
    }

    @Test
    fun modalNavigationDrawer_rtl_drawerIsDrawnAtTheStart() {
        val contentWidthBoxTag = "contentWidthBox"
        val drawerContentBoxTag = "drawerContentBox"
        rule.setContent {
            CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
                ModalNavigationDrawer(
                    drawerState = remember { DrawerState(DrawerValue.Closed) },
                    drawerContent = {
                        Box(
                            Modifier
                                .testTag(drawerContentBoxTag)
                                .border(2.dp, Color.Red)) {
                            BasicText(text = if (it == DrawerValue.Open) "Opened" else "Closed")
                        }
                    }
                ) { Box(
                    Modifier
                        .fillMaxWidth()
                        .testTag(contentWidthBoxTag)) }
            }
        }

        val rightEdgeOfRoot = rule.onRoot().getUnclippedBoundsInRoot().right
        rule.onNodeWithTag(drawerContentBoxTag).assertRightPositionInRootIsEqualTo(rightEdgeOfRoot)
    }

    @Test
    fun modalNavigationDrawer_rtl_drawerExpandsTowardsEnd() {
        val contentWidthBoxTag = "contentWidthBox"
        val drawerContentBoxTag = "drawerContentBox"
        var drawerState: DrawerState? = null
        rule.setContent {
            CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
                drawerState = remember { DrawerState(DrawerValue.Closed) }
                ModalNavigationDrawer(
                    drawerState = drawerState!!,
                    drawerContent = {
                        Box(
                            Modifier
                                .testTag(drawerContentBoxTag)
                                .border(2.dp, Color.Red)) {
                            BasicText(text = if (it == DrawerValue.Open) "Opened" else "Closed")
                        }
                    }
                ) { Box(
                    Modifier
                        .fillMaxWidth()
                        .testTag(contentWidthBoxTag)) }
            }
        }

        val endPositionInClosedState =
            rule.onNodeWithTag(drawerContentBoxTag).getUnclippedBoundsInRoot().left

        rule.runOnIdle { drawerState?.setValue(DrawerValue.Open) }
        val endPositionInOpenState =
            rule.onNodeWithTag(drawerContentBoxTag).getUnclippedBoundsInRoot().left

        assert(endPositionInClosedState.value > endPositionInOpenState.value)
    }

    @OptIn(ExperimentalTestApi::class, ExperimentalComposeUiApi::class)
    @Test
    fun modalNavigationDrawer_parentContainerGainsFocus_onBackPress() {
        val drawerFocusRequester = FocusRequester()
        rule.setContent {
            Box(
                modifier = Modifier
                    .testTag("box-container")
                    .fillMaxSize()
                    .focusable()
            ) {
                ModalNavigationDrawer(
                    modifier = Modifier.focusRequester(drawerFocusRequester),
                    drawerState = remember { DrawerState(DrawerValue.Closed) },
                    drawerContent = {
                        BasicText(
                            text = if (it == DrawerValue.Open) "Opened" else "Closed",
                            modifier = Modifier.focusable()
                        )
                    }
                ) {
                    BasicText("other content")
                }
            }
        }

        rule.onAllNodesWithText("Closed").assertAnyAreDisplayed()

        rule.runOnIdle {
            drawerFocusRequester.requestFocus()
        }

        rule.onAllNodesWithText("Opened").assertAnyAreDisplayed()
        rule.onNodeWithTag("box-container").assertIsNotFocused()

        // Trigger back press
        rule.onRoot().performKeyInput { pressKey(Key.Back) }
        rule.waitForIdle()

        // Check if the parent container gains focus
        rule.onNodeWithTag("box-container").assertIsFocused()
    }

    private fun SemanticsNodeInteractionCollection.assertAnyAreDisplayed() {
        val result = (0 until fetchSemanticsNodes().size).map { get(it) }.any {
            try {
                it.assertIsDisplayed()
                true
            } catch (e: AssertionError) {
                false
            }
        }

        if (!result) throw AssertionError("Assert failed: None of the components are displayed!")
    }

    private fun SemanticsNodeInteraction.assertRightPositionInRootIsEqualTo(
        expectedRight: Dp
    ): SemanticsNodeInteraction {
        return withUnclippedBoundsInRoot {
            it.right.assertIsEqualTo(expectedRight, "right")
        }
    }

    private fun SemanticsNodeInteraction.withUnclippedBoundsInRoot(
        assertion: (DpRect) -> Unit
    ): SemanticsNodeInteraction {
        val node = fetchSemanticsNode("Failed to retrieve bounds of the node.")
        val bounds = with(node.layoutInfo.density) {
            node.unclippedBoundsInRoot.let {
                DpRect(it.left.toDp(), it.top.toDp(), it.right.toDp(), it.bottom.toDp())
            }
        }
        assertion.invoke(bounds)
        return this
    }

    private val SemanticsNode.unclippedBoundsInRoot: Rect
        get() {
            return if (layoutInfo.isPlaced) {
                Rect(positionInRoot, size.toSize())
            } else {
                Dp.Unspecified.value.let { Rect(it, it, it, it) }
            }
        }
}
