package com.dowstats.service.w40k

import com.dowstats.Metadata
import com.dowstats.data.entities.*
import com.dowstats.data.entities.ModifiersBase.ModifiersBaseCompanion.fillDataFromRgdTable
import com.dowstats.data.entities.ModifiersBase.ModifiersBaseCompanion.filterUseless
import com.dowstats.data.entities.addon.AddonModifiers
import com.dowstats.data.entities.addon.AddonRequirements
import com.dowstats.data.entities.addon.BuildingAddon
import com.dowstats.data.entities.building.Building
import com.dowstats.data.rgd.RgdData
import com.dowstats.data.rgd.RgdDataUtil.getBooleanByName
import com.dowstats.data.rgd.RgdDataUtil.getDoubleByName
import com.dowstats.data.rgd.RgdDataUtil.getIntByName
import com.dowstats.data.rgd.RgdDataUtil.getRgdTableByName
import com.dowstats.data.rgd.RgdDataUtil.getStringByName
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service

@Service
class BuildingAddonRgdExtractService @Autowired constructor(
    private val commonParseRgdService: CommonParseRgdService,
) {
    val log = LoggerFactory.getLogger(BuildingAddonRgdExtractService::class.java)

    fun extractToAddonEntity(
        fileName: String,
        modDictionary: Map<Int, String>,
        addonRgdData: List<RgdData>,
        modFolderData: String,
        building: Building,
        mod: Mod,
    ): BuildingAddon {

        val addon = BuildingAddon()
        addon.building = building

        val uiInfoRgd = addonRgdData.getRgdTableByName("ui_info") ?: throw Exception("Could not find ui_info at $fileName")
        val uiInfo = commonParseRgdService.getUiInfo(uiInfoRgd, modDictionary, modFolderData, mod, log)
        addon.name = uiInfo.name
        addon.description = uiInfo.description
        addon.uiIndexHint = addonRgdData.getIntByName("ui_index_hint") ?: 0
        addon.uiHotkeyName = addonRgdData.getStringByName("ui_hotkey_name")
        addon.icon = uiInfo.iconPath
        addon.filename = fileName

        val buildCost = commonParseRgdService.getBuildCost(addonRgdData.getRgdTableByName("time_cost"))
        addon.addonCostRequisition = buildCost.requisition
        addon.addonCostPower = buildCost.power
        addon.addonCostPopulation = buildCost.population
        addon.addonCostFaith = buildCost.faith
        addon.addonCostSouls = buildCost.souls
        addon.addonCostTime = buildCost.time
        addon.addonModifiers = getAddonModifiers(addon, addonRgdData).toMutableSet()
        addon.addonRequirements = getAddonRequirements(addon, addonRgdData).toMutableSet()

        addon.modId = mod.id

        return addon
    }

    private fun getAddonModifiers(addon: BuildingAddon, addonData: List<RgdData>): List<AddonModifiers> {
        val modifiers = addonData.getRgdTableByName("modifiers")
        return modifiers?.mapNotNull { m ->
            if (m.name.contains("modifier_")) {
                val mTable = m.value as List<RgdData>
                if (mTable.getStringByName("\$REF") == "modifiers\\no_modifier.lua") null else {
                    AddonModifiers().also {
                        it.addon = addon
                    }.fillDataFromRgdTable(mTable)
                }
            } else null
        }?.filterUseless() ?: emptyList()
    }

    private fun getAddonRequirements(addon: BuildingAddon, addonData: List<RgdData>): List<AddonRequirements> {
        val requirements = addonData.getRgdTableByName("requirements")
        return requirements?.mapNotNull { r ->
            if (r.name.contains("required_")) {
                val rTable = r.value as List<RgdData>
                if (rTable.getStringByName("\$REF")?.contains(Metadata.Requirements.REFERENCE_REQUIREMENT_NONE) == true) null else {
                    AddonRequirements().also {
                        it.addon = addon
                        it.reference = rTable.getStringByName("\$REF")
                        it.replaceWhenDone = rTable.getBooleanByName("replace_when_done") == true
                        it.value = commonParseRgdService.getRequirementReference(it.reference, rTable, addon.filename!!, log)
                    }
                }
            } else null
        } ?: emptyList()
    }

}
