/*
 * Copyright 2019 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.ui.material

import androidx.compose.Composable
import androidx.compose.getValue
import androidx.compose.setValue
import androidx.compose.state
import androidx.test.filters.LargeTest
import androidx.ui.core.Modifier
import androidx.ui.core.testTag
import androidx.compose.foundation.Box
import androidx.compose.foundation.Icon
import androidx.compose.foundation.Text
import androidx.compose.foundation.background
import androidx.compose.ui.graphics.Color
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.preferredHeight
import androidx.ui.material.icons.Icons
import androidx.ui.material.icons.filled.Favorite
import androidx.ui.material.samples.ScrollingTextTabs
import androidx.ui.material.samples.TextTabs
import androidx.ui.test.assertCountEquals
import androidx.ui.test.assertHeightIsEqualTo
import androidx.ui.test.assertIsEqualTo
import androidx.ui.test.assertIsSelected
import androidx.ui.test.assertIsNotSelected
import androidx.ui.test.assertPositionInRootIsEqualTo
import androidx.ui.test.createComposeRule
import androidx.ui.test.performClick
import androidx.ui.test.onAllNodes
import androidx.ui.test.onNodeWithTag
import androidx.ui.test.getBoundsInRoot
import androidx.ui.test.isInMutuallyExclusiveGroup
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.height
import androidx.compose.ui.unit.width
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4

@LargeTest
@RunWith(JUnit4::class)
class TabTest {

    private val ExpectedSmallTabHeight = 48.dp
    private val ExpectedLargeTabHeight = 72.dp

    private val icon = Icons.Filled.Favorite

    @get:Rule
    val composeTestRule = createComposeRule(disableTransitions = true)

    @Test
    fun textTab_height() {
        composeTestRule
            .setMaterialContentForSizeAssertions {
                Tab(text = { Text("Text") }, selected = true, onSelected = {})
            }
            .assertHeightIsEqualTo(ExpectedSmallTabHeight)
    }

    @Test
    fun iconTab_height() {
        composeTestRule
            .setMaterialContentForSizeAssertions {
                Tab(icon = { Icon(icon) }, selected = true, onSelected = {})
            }
            .assertHeightIsEqualTo(ExpectedSmallTabHeight)
    }

    @Test
    fun textAndIconTab_height() {
        composeTestRule
            .setMaterialContentForSizeAssertions {
                Surface {
                    Tab(
                        text = { Text("Text and Icon") },
                        icon = { Icon(icon) },
                        selected = true,
                        onSelected = {}
                    )
                }
            }
            .assertHeightIsEqualTo(ExpectedLargeTabHeight)
    }

    @Test
    fun fixedTabRow_indicatorPosition() {
        val indicatorHeight = 1.dp

        composeTestRule.setMaterialContent {
            var state by state { 0 }
            val titles = listOf("TAB 1", "TAB 2")

            val indicatorContainer = @Composable { tabPositions: List<TabRow.TabPosition> ->
                TabRow.IndicatorContainer(tabPositions, state) {
                    Box(
                        Modifier
                            .fillMaxWidth()
                            .preferredHeight(indicatorHeight)
                            .background(color = Color.Red)
                        .testTag("indicator")
                    )
                }
            }

            Box(Modifier.testTag("tabRow")) {
                TabRow(
                    items = titles,
                    selectedIndex = state,
                    indicatorContainer = indicatorContainer
                ) { index, text ->
                    Tab(
                        text = { Text(text) },
                        selected = state == index,
                        onSelected = { state = index }
                    )
                }
            }
        }

        val tabRowBounds = onNodeWithTag("tabRow").getBoundsInRoot()

        onNodeWithTag("indicator")
            .assertPositionInRootIsEqualTo(
                expectedLeft = 0.dp,
                expectedTop = tabRowBounds.height - indicatorHeight
            )

        // Click the second tab
        onAllNodes(isInMutuallyExclusiveGroup())[1].performClick()

        // Indicator should now be placed in the bottom left of the second tab, so its x coordinate
        // should be in the middle of the TabRow
        onNodeWithTag("indicator")
            .assertPositionInRootIsEqualTo(
                expectedLeft = (tabRowBounds.width / 2),
                expectedTop = tabRowBounds.height - indicatorHeight
            )
    }

    @Test
    fun singleLineTab_textBaseline() {
        composeTestRule.setMaterialContent {
            var state by state { 0 }
            val titles = listOf("TAB")

            Box {
                TabRow(
                    modifier = Modifier.testTag("tabRow"),
                    items = titles,
                    selectedIndex = state
                ) { index, text ->
                    Tab(
                        text = {
                            Text(text, Modifier.testTag("text"))
                        },
                        selected = state == index,
                        onSelected = { state = index }
                    )
                }
            }
        }

        val expectedBaseline = 18.dp
        val indicatorHeight = 2.dp
        val expectedBaselineDistance = expectedBaseline + indicatorHeight

        val tabRowBounds = onNodeWithTag("tabRow").getBoundsInRoot()
        val textBounds = onNodeWithTag("text").getBoundsInRoot()
        val textBaselinePos = onNodeWithTag("text").getLastBaselinePosition()

        val baselinePositionY = textBounds.top + textBaselinePos
        val expectedPositionY = tabRowBounds.height - expectedBaselineDistance
        baselinePositionY.assertIsEqualTo(expectedPositionY, "baseline y-position")
    }

    @Test
    fun singleLineTab_withIcon_textBaseline() {
        composeTestRule.setMaterialContent {
            var state by state { 0 }
            val titles = listOf("TAB")

            Box {
                TabRow(
                    modifier = Modifier.testTag("tabRow"),
                    items = titles,
                    selectedIndex = state
                ) { index, text ->
                    Tab(
                        text = {
                            Text(text, Modifier.testTag("text"))
                        },
                        icon = { Icon(Icons.Filled.Favorite) },
                        selected = state == index,
                        onSelected = { state = index }
                    )
                }
            }
        }

        val expectedBaseline = 14.dp
        val indicatorHeight = 2.dp
        val expectedBaselineDistance = expectedBaseline + indicatorHeight

        val tabRowBounds = onNodeWithTag("tabRow").getBoundsInRoot()
        val textBounds = onNodeWithTag("text").getBoundsInRoot()
        val textBaselinePos = onNodeWithTag("text").getLastBaselinePosition()

        val baselinePositionY = textBounds.top + textBaselinePos
        val expectedPositionY = tabRowBounds.height - expectedBaselineDistance
        baselinePositionY.assertIsEqualTo(expectedPositionY, "baseline y-position")
    }

    @Test
    fun twoLineTab_textBaseline() {
        composeTestRule.setMaterialContent {
            var state by state { 0 }
            val titles = listOf("Two line \n text")

            Box {
                TabRow(
                    modifier = Modifier.testTag("tabRow"),
                    items = titles,
                    selectedIndex = state
                ) { index, text ->
                    Tab(
                        text = {
                            Text(text, Modifier.testTag("text"), maxLines = 2)
                        },
                        selected = state == index,
                        onSelected = { state = index }
                    )
                }
            }
        }

        val expectedBaseline = 10.dp
        val indicatorHeight = 2.dp

        val tabRowBounds = onNodeWithTag("tabRow").getBoundsInRoot()
        val textBounds = onNodeWithTag("text").getBoundsInRoot()
        val textBaselinePos = onNodeWithTag("text").getLastBaselinePosition()

        val expectedBaselineDistance = expectedBaseline + indicatorHeight

        val baselinePositionY = textBounds.top + textBaselinePos
        val expectedPositionY = (tabRowBounds.height - expectedBaselineDistance)
        baselinePositionY.assertIsEqualTo(expectedPositionY, "baseline y-position")
    }

    @Test
    fun scrollableTabRow_indicatorPosition() {
        val indicatorHeight = 1.dp
        val scrollableTabRowOffset = 52.dp
        val minimumTabWidth = 90.dp

        composeTestRule.setMaterialContent {
            var state by state { 0 }
            val titles = listOf("TAB 1", "TAB 2")

            val indicatorContainer = @Composable { tabPositions: List<TabRow.TabPosition> ->
                TabRow.IndicatorContainer(tabPositions, state) {
                    Box(
                        Modifier
                            .fillMaxWidth()
                            .preferredHeight(indicatorHeight)
                            .background(color = Color.Red)
                        .testTag("indicator")
                    )
                }
            }

            Box {
                TabRow(
                    modifier = Modifier.testTag("tabRow"),
                    items = titles,
                    scrollable = true,
                    selectedIndex = state,
                    indicatorContainer = indicatorContainer
                ) { index, text ->
                    Tab(
                        text = { Text(text) },
                        selected = state == index,
                        onSelected = { state = index }
                    )
                }
            }
        }

        val tabRowBounds = onNodeWithTag("tabRow").getBoundsInRoot()

        // Indicator should be placed in the bottom left of the first tab
        onNodeWithTag("indicator")
            .assertPositionInRootIsEqualTo(
                // Tabs in a scrollable tab row are offset 52.dp from each end
                expectedLeft = scrollableTabRowOffset,
                expectedTop = tabRowBounds.height - indicatorHeight
            )

        // Click the second tab
        onAllNodes(isInMutuallyExclusiveGroup())[1].performClick()

        // Indicator should now be placed in the bottom left of the second tab, so its x coordinate
        // should be in the middle of the TabRow
        onNodeWithTag("indicator")
            .assertPositionInRootIsEqualTo(
                expectedLeft = scrollableTabRowOffset + minimumTabWidth,
                expectedTop = tabRowBounds.height - indicatorHeight
            )
    }

    @Test
    fun fixedTabRow_initialTabSelected() {
        composeTestRule
            .setMaterialContent {
                TextTabs()
            }

        // Only the first tab should be selected
        onAllNodes(isInMutuallyExclusiveGroup())
            .assertCountEquals(3)
            .apply {
                get(0).assertIsSelected()
                get(1).assertIsNotSelected()
                get(2).assertIsNotSelected()
            }
    }

    @Test
    fun fixedTabRow_selectNewTab() {
        composeTestRule
            .setMaterialContent {
                TextTabs()
            }

        // Only the first tab should be selected
        onAllNodes(isInMutuallyExclusiveGroup())
            .assertCountEquals(3)
            .apply {
                get(0).assertIsSelected()
                get(1).assertIsNotSelected()
                get(2).assertIsNotSelected()
            }

        // Click the last tab
        onAllNodes(isInMutuallyExclusiveGroup())[2].performClick()

        // Now only the last tab should be selected
        onAllNodes(isInMutuallyExclusiveGroup())
            .assertCountEquals(3)
            .apply {
                get(0).assertIsNotSelected()
                get(1).assertIsNotSelected()
                get(2).assertIsSelected()
            }
    }

    @Test
    fun scrollableTabRow_initialTabSelected() {
        composeTestRule
            .setMaterialContent {
                ScrollingTextTabs()
            }

        // Only the first tab should be selected
        onAllNodes(isInMutuallyExclusiveGroup())
            .assertCountEquals(10)
            .apply {
                get(0).assertIsSelected()
                (1..9).forEach {
                    get(it).assertIsNotSelected()
                }
            }
    }

    @Test
    fun scrollableTabRow_selectNewTab() {
        composeTestRule
            .setMaterialContent {
                ScrollingTextTabs()
            }

        // Only the first tab should be selected
        onAllNodes(isInMutuallyExclusiveGroup())
            .assertCountEquals(10)
            .apply {
                get(0).assertIsSelected()
                (1..9).forEach {
                    get(it).assertIsNotSelected()
                }
            }

        // Click the second tab
        onAllNodes(isInMutuallyExclusiveGroup())[1].performClick()

        // Now only the second tab should be selected
        onAllNodes(isInMutuallyExclusiveGroup())
            .assertCountEquals(10)
            .apply {
                get(0).assertIsNotSelected()
                get(1).assertIsSelected()
                (2..9).forEach {
                    get(it).assertIsNotSelected()
                }
            }
    }
}
