/**
 * The parts of the fit editor that relate to command effects.
 */

package theorycrafter.ui.fiteditor

import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.text.AnnotatedString
import compose.widgets.GridScope
import theorycrafter.fits.FitHandle
import theorycrafter.TestTags
import theorycrafter.TheorycrafterContext
import theorycrafter.fitting.Fit
import theorycrafter.fitting.FittingEngine
import theorycrafter.fitting.RemoteEffect
import theorycrafter.utils.AutoSuggest


/**
 * A [RemoteEffectFitActions] implementation for command effects.
 */
private object CommandEffectFitActions: RemoteEffectFitActions() {


    override val Fit.effects: List<RemoteEffect>
        get() = remoteEffects.command.allExcludingAuxiliary


    override fun FittingEngine.ModificationScope.addRemoteEffect(
        targetFit: Fit,
        sourceFit: Fit,
        slotIndex: Int
    ): RemoteEffect {
        return targetFit.addCommandEffect(sourceFit, index = slotIndex)
    }


    override fun FittingEngine.ModificationScope.removeRemoteEffect(remoteEffect: RemoteEffect) {
        remoteEffect.target.removeCommandEffect(remoteEffect)
    }


}


/**
 * Provides the content of the command effect slot row when the value is being edited.
 */
private val EditedCommandEffectRow =
    EditedRemoteEffectRow { scope, onRemoteEffectSelected, onEditingCancelled ->
        with(scope) {
            val commandFitsAutoSuggest = rememberCommandingFitsAutoSuggest(LocalFit.current)
            val fitSelectionAutoSuggest = remember(commandFitsAutoSuggest) {
                AutoSuggest { query ->
                    commandFitsAutoSuggest(query)?.map {
                        RemoteEffectSelection.Fit(it)
                    }
                }
            }
            RemoteEffectSelectorRow(
                hint = "Command fit name",
                autoSuggest = fitSelectionAutoSuggest,
                onRemoteEffectSelected = onRemoteEffectSelected,
                onEditingCancelled = onEditingCancelled
            )
        }
}


/**
 * Returns the auto-suggest for commanding fits of the given fit.
 */
@Composable
private fun rememberCommandingFitsAutoSuggest(fit: Fit): AutoSuggest<FitHandle> {
    val commandingFits = fit.remoteEffects.command.allExcludingAuxiliary
    return remember(fit, commandingFits) {
        // Filter out the fit itself and all the fits it already has as command effects.
        val ignoredFitHandles = commandingFits
            .mapTo(mutableSetOf()) {
                TheorycrafterContext.fits.handleOf(it.source)
            }.also {
                it.add(TheorycrafterContext.fits.handleOf(fit))
            }
        AutoSuggest { text: String ->
            with(TheorycrafterContext) {
                queryFits(text)?.filter {
                    val shipType = eveData.shipType(it.shipTypeId)
                    eveData.canFitCommandBursts(shipType) && (it !in ignoredFitHandles)
                }
            }
        }
    }
}


/**
 * The section for setting the command effects.
 */
@Composable
fun GridScope.CommandEffectsSection(
    firstRowIndex: Int,
    isFirst: Boolean = false,
    fit: Fit,
): Int {
    return RemoteEffectsSection(
        firstRowIndex = firstRowIndex,
        isFirst = isFirst,
        fit = fit,
        remoteEffectSet = fit.remoteEffects.command,
        sectionTitle = AnnotatedString("Command Fits"),
        remoteFitActions = CommandEffectFitActions,
        remoteEffectSlotTestTag = TestTags.FitEditor::commandEffectRow,
        affectingModuleSlotTestTag = TestTags.FitEditor::commandEffectAffectingModuleRow,
        affectingModuleChargeTestTag = TestTags.FitEditor::commandEffectAffectingModuleChargeRow,
        affectingDroneSlotTestTag = null,
        moduleEffectSlotTestTag = null,
        moduleEffectChargeSlotTestTag = null,
        droneEffectSlotTestTag = null,
        emptySlotText = "Empty command fit slot",
        emptySlotTestTag = TestTags.FitEditor.EmptyCommandEffectRow,
        remoteEffectSelectionFromClipboardText = { null },
        editedRemoteEffectRow = EditedCommandEffectRow
    )
}
