const chancePerScroll = 0.3
const notFoundBonusRolls = 2
const hexCastingScrollTables = {
    few: [
		"minecraft:chests/jungle_temple",
        "repurposed_structures:archaeology/monument_jungle",
		"minecraft:chests/simple_dungeon",
		"betterdungeons:zombie_dungeon/chests/special",
		"betterdungeons:skeleton_dungeon/chests/middle",
		"betterdungeons:small_dungeon/chests/loot_piles",
		// "betterdungeons:spider_dungeon/chests/egg_room",
        "nova_structures:archaelogy/desert_ruin_inside_temple",
        "nova_structures:chests/stray_fort_tresure",
        /^repurposed_structures:chests\/dungeons\//,
        "repurposed_structures:chests/bastions/underground/treasure"
	],
    some: [
		"minecraft:chests/bastion_treasure",
		"minecraft:chests/shipwreck_map",
        /^repurposed_structures:chests\/shipwrecks\/\w+\/map$/,
        "nova_structures:chests/desert_ruins/desert_ruin_main_temple",
        "nova_structures:chests/witch_villa/lab"
	],
    many: [
		"minecraft:chests/stronghold_library",
		"betterfortresses:chests/worship"
	]
}

LootJS.modifiers(event => {
    event
        .addLootTableModifier(hexCastingScrollTables.few)
        .apply(catchWrap(rollScrolls(1)))

    event
        .addLootTableModifier(hexCastingScrollTables.some)
        .apply(catchWrap(rollScrolls(2)))

    event
        .addLootTableModifier(hexCastingScrollTables.many)
        .apply(catchWrap(rollScrolls(3)))
})

function catchWrap(method) {
    return function(a) {
        try {
            return method.call(this, a)
        } catch(err) {
            console.error(err)
        }
    }
}

// const PatternRegistry = Java.loadClass('at.petrak.hexcasting.api.PatternRegistry')
const IXplatAbstractions = Java.loadClass('at.petrak.hexcasting.xplat.IXplatAbstractions')
const HexUtils = Java.loadClass('at.petrak.hexcasting.api.utils.HexUtils')
const HexTags = Java.loadClass('at.petrak.hexcasting.api.mod.HexTags')
const PatternRegistryManifest = Java.loadClass('at.petrak.hexcasting.common.casting.PatternRegistryManifest')
// const HexPattern = Java.loadClass('at.petrak.hexcasting.api.spell.math.HexPattern')
const CompoundTag = Java.loadClass('net.minecraft.nbt.CompoundTag')

ServerEvents.highPriorityData(datapack => {
    // let perworldPatterns = PatternRegistry.getAllPerWorldPatternNames().toArray()
    let patternKeys = getPerWorldPatternKeys()
    
    for(let key of patternKeys) {
        let resourcePath = `kubejs:advancements/${getAdvancementPath(key)}`
        
        datapack.addJson(
            resourcePath,
            createScrollAdvancement(key)
        )
    }
})

const getAdvancementPath = patternKey => {
    let rl = patternKey.location()
    return `scrolls/${rl.getNamespace()}/${rl.getPath()}`
}

const createScrollAdvancement = patternKey => ({
    "criteria": {
        "requirement": {
            "trigger": "minecraft:inventory_changed",
            "conditions": {
                "items": [
                    {
                        "items": [
                            "hexcasting:scroll"
                        ],
                        "nbt": JSON.stringify({
                            op_id: patternKey.toString()
                        })
                    }
                ]
            }
        }
    }
})

// https://github.com/FallingColors/HexMod/issues/629
const rollScrolls = count => lootContext => {
    console.log('Loading scrolls')

    // Remove the scrolls already added by hexcasting
    lootContext.removeLoot(Ingredient.of("hexcasting:scroll"))

    if(lootContext.getPlayer() == null) {
        console.error('Cannot generate scrolls without a player')
        return
    }
    
    // let worldLookup = PatternRegistry.getPerWorldPatterns(lootContext.getLevel())
    let table = createWeightedPatternTable(lootContext, getPerWorldPatternKeys(), notFoundBonusRolls)
    let random = lootContext.getRandom()
    
    for(let i = 0; i < count; i++) {
        let patternKey = table[random.nextInt(table.length)]
        let pattern = PatternRegistryManifest.getCanonicalStrokesPerWorld(patternKey, lootContext.getServer().getOverworld())
        let entry = LootEntry.of('hexcasting:scroll', createScrollTag(patternKey, pattern))
            .when(c => c.randomChance(chancePerScroll))

        lootContext.addLoot(entry)
    }
}

const createWeightedPatternTable = (lootContext, patternKeys, notFoundBonus) => {
    let player = lootContext.getPlayer()
    // https://github.com/FallingColors/HexMod/blob/6286da360820cf542b38b862cfc1011145e2f78b/Common/src/main/java/at/petrak/hexcasting/common/loot/AddPerWorldPatternToScrollFunc.java#L43
    let table = []

    for(let patternKey of patternKeys) {
        let advancementId = new ResourceLocation('kubejs', getAdvancementPath(patternKey))
        let advancement = player.server.getAdvancement(advancementId).advancement
        let hasFound = player.advancements.getOrStartProgress(advancement).done

        if(!hasFound) {
            for(let i = 0; i < notFoundBonus; i++) {
                table.push(patternKey)
            }
        }

        table.push(patternKey)
    }

    return table
}

const resourceKeyIsOfTag = 'isOfTag(net.minecraft.core.Registry,net.minecraft.resources.ResourceKey,net.minecraft.tags.TagKey)'
const getPerWorldPatternKeys = () => {
    let actionRegistry = IXplatAbstractions.INSTANCE.getActionRegistry()

    return actionRegistry.registryKeySet()
        .toArray()
        .filter(key => {
            return HexUtils[resourceKeyIsOfTag](actionRegistry, key, HexTags.Actions.PER_WORLD_PATTERN)
        })
}

// https://github.com/FallingColors/HexMod/blob/6286da360820cf542b38b862cfc1011145e2f78b/Common/src/main/java/at/petrak/hexcasting/common/loot/AddPerWorldPatternToScrollFunc.java#L50
const createScrollTag = (patternKey, pattern) => {
    let tag = new CompoundTag()

    tag.putString('op_id', patternKey.location().toString())
    tag.put('pattern', pattern.serializeToNBT())

    return tag
}