package theorycrafter.ui.tournaments

import androidx.compose.ui.input.key.Key
import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.assertAny
import androidx.compose.ui.test.isFocused
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.runDesktopComposeUiTest
import androidx.compose.ui.test.waitUntilExactlyOneExists
import eve.data.*
import theorycrafter.*
import theorycrafter.tournaments.BasicPointsCompositionRules
import theorycrafter.tournaments.Composition
import theorycrafter.tournaments.TournamentDescriptor
import theorycrafter.tournaments.TournamentRules
import theorycrafter.ui.fiteditor.PackForBattleConfiguration
import kotlin.test.Test


/**
 * Tests the tournament compositions UI.
 */
class TournamentsWindowTest: TheorycrafterTest() {


    /**
     * Tests that after naming a new composition, the focus moves to the composition editor.
     */
    @OptIn(ExperimentalTestApi::class)
    @Test
    fun namingNewCompMovesFocusToCompEditor() = runDesktopComposeUiTest {
        setApplicationContent {
            TournamentWindowContent(TestTournamentDescriptor)
        }

        // This is needed because the tournament is loaded asynchronously
        waitUntilExactlyOneExists(TournamentNodes.CompsList.NewCompositionButton)

        onNode(TournamentNodes.CompsList.NewCompositionButton).performClick()
        onNode(isFocused()).press(Key.Enter)
        onSubtreeRootedAt(TournamentNodes.CompEditor.RootNode).assertAny(isFocused())
    }

}


/**
 * A test tournament descriptor
 */
private val TestTournamentDescriptor = TournamentDescriptor(
    id = "test",
    name = "Test Tournament",
    shortName = "TT",
    rulesFactory = ::testTournamentRules,
)


/**
 * The test tournament rules.
 */
private fun testTournamentRules(eveData: EveData) = TournamentRules(
    compositionRules = object: BasicPointsCompositionRules(
        eveData = eveData,
        maxCompositionSize = 10,
        maxCompositionCost = 100,
        shipCostByType = eveData.shipTypes.associateWith { 10 },
    ) {
        override fun compositionShipsIllegalityReason(composition: Composition): List<String?> {
            return List(composition.ships.size) { null }
        }
    },
    fittingRules = object: TournamentRules.FittingRules {

        override fun isModuleLegal(moduleType: ModuleType, shipType: ShipType, isFlagship: Boolean): Boolean {
            return true
        }

        override fun fitModulesLegality(moduleTypes: List<ModuleType>, shipType: ShipType, isFlagship: Boolean): List<String?> {
            return List(moduleTypes.size) { null }
        }

        override fun isChargeLegal(chargeType: ChargeType?, moduleType: ModuleType): Boolean {
            return true
        }

        override fun isDroneLegal(droneType: DroneType): Boolean {
            return true
        }

        override fun isImplantLegal(implantType: ImplantType): Boolean {
            return true
        }

        override fun isCargoItemLegal(itemType: EveItemType): Boolean {
            return true
        }

        override val packForBattleConfiguration: PackForBattleConfiguration
            get() = TestPackForBattleConfiguration

    }

)


/**
 * The [PackForBattleConfiguration] for tests.
 */
private object TestPackForBattleConfiguration: PackForBattleConfiguration {

    context(EveData) override fun script(chargeType: ChargeType): Boolean {
        return true
    }

    context(EveData) override fun interdictionSphereLauncherProbe(chargeType: ChargeType): Boolean {
        return true
    }

    context(EveData) override fun ammo(shipType: ShipType, moduleType: ModuleType, chargeType: ChargeType): Boolean {
        return true
    }

}