import { Entity, ItemStack, Player, system } from "@minecraft/server";
import { arrayIncludes, randomChance, randomFloat } from "../../utils/systemHelper";
import { BlockStateNames } from "../../blocks/utils/blockConstants";
import { DUMMY } from "../../entities/specific/dummy";
import { ItemComponents as IComponents } from "../utils/itemComponents";
import { EntityProperites } from "../../entities/utils/entityProperties";
import { EntityHelper } from "../../entities/utils/entityHelper";
import { WorldHelper } from "../../world/utils/worldHelper";

export const IGUANA_BOOTS = {
    _frostWalkerEnchantment: "frost_walker",
    _frostWalkerBlockTransformTo: "piki_beyondsurvival:basalt_broken",
    _frostWalkerBlockTransformBack: "minecraft:flowing_lava",
    _frostWalkerBlockTransformFromContains: "lava",
    _frostWalkerBlockBrokenAge: 3,
    _frostWalkerBlockAgeChance: 0.5,
    _iguanaBootsTypeIds: [
        "piki_beyondsurvival:greeniguana_boots",
        "piki_beyondsurvival:amberiguana_boots",
        "piki_beyondsurvival:shadowiguana_boots",
        "piki_beyondsurvival:zebraiguana_boots"
    ],
    _frostWalkerBlockTransformDurationMin: 1,
    _frostWalkerBlockTransformDurationMax: 2, 
    _ageCondition: function() {
        return true
    },
    _dummyDynamicPropertyType: "ager",
    
    // ENTRY POINT
    /**
     * @param {Entity} dummy
     * @returns 
     */
    shouldAgeBlock: function(dummy) {
        try {
            const block = dummy.dimension.getBlock(dummy.location)
            if (DUMMY.getType(dummy) != this._dummyDynamicPropertyType) return
            if (!block) return
            if (block.typeId != this._frostWalkerBlockTransformTo) {
                DUMMY.kill(dummy)
                return false
            } 
            const interval = randomFloat(this._frostWalkerBlockTransformDurationMax, this._frostWalkerBlockTransformDurationMin, 1)
            return system.currentTick % (interval * 20) == 0
        } catch {
            
        }
       
    },
    /**
     * Checks if the player can frost walk
     * @param {Entity|Player} entity 
     * @param {ItemStack} bootArmor 
     */
    isFrostWalkTrying: function(entity, bootArmor) {
        if (!bootArmor) return

        const {isFalling, isJumping, isFlying, location} = entity
        const isMoving = EntityHelper.entityHasVelocity(entity)

        const isIguanaBoots = arrayIncludes(this._iguanaBootsTypeIds, bootArmor.typeId)
        
        const enchantable = IComponents.getEnchantable(bootArmor)
        const isEnchanted = enchantable.getEnchantment(this._frostWalkerEnchantment)
 
        return !isFalling && isMoving && isEnchanted && isIguanaBoots // && !isFlying && !isJumping
    },

    // HELPER METHODS
    /**
     * 
     * @param {Entity} entity 
     * @param {ItemStack} itemStack 
     */
    frostWalk: function(entity, itemStack) {
        const enchantable = IComponents.getEnchantable(itemStack)
        const frostWalkEnchantment = enchantable?.getEnchantment(this._frostWalkerEnchantment)

        if (!frostWalkEnchantment) return;

        const {location} = entity
        const level = frostWalkEnchantment.level
        const dimension = (2 + level) * 2
        const [x1, z1, x2, z2] = WorldHelper.getBoundingBox([location.x, location.z], [dimension, dimension])

        let minX = Math.min(x1, x2);
        let maxX = Math.max(x1, x2);
        let minZ = Math.min(z1, z2);
        let maxZ = Math.max(z1, z2);

        for (let x = minX; x <= maxX; x++) {
            for (let z = minZ; z <= maxZ; z++) {
                const targetLocation = WorldHelper.createNewLocation(x, location.y, z);
                const block = entity.dimension.getBlock(targetLocation).below()
                const isLava = block.typeId.includes(this._frostWalkerBlockTransformFromContains)
                const isBasalt = block.typeId == this._frostWalkerBlockTransformTo
                const isScriptBlock = block.permutation.getState(BlockStateNames.scriptBlock)
                const isFullLiquid = block.permutation.getState(BlockStateNames.liquidDepth) == 0
                
                if (!block || !block.above().isAir) continue
                if (!isLava && !isBasalt) continue
                if (!isFullLiquid && !isScriptBlock) continue

                block.setType(this._frostWalkerBlockTransformTo)
                block.setPermutation(block.permutation.withState(BlockStateNames.scriptBlock, true))
                block.permutation.withState(BlockStateNames.customAge, 0)
                
                if (isBasalt) continue
                DUMMY.summon(block.dimension, block.location, this._dummyDynamicPropertyType)
            }
        }
    },
    
    /**
     * 
     * @param {Entity} dummy 
     */
    ageBlock(dummy) {
        try {
            if (!dummy.isValid()) return
            if (DUMMY.getType(dummy) != this._dummyDynamicPropertyType) return
            if (!randomChance(this._frostWalkerBlockAgeChance)) return
            if (!this._ageCondition()) return

            const block = dummy.dimension.getBlock(dummy.location)
            if (!block) throw new Error(false)

            const ageState = block.permutation.getState(BlockStateNames.customAge)
            const isScriptBlock = block.permutation.getState(BlockStateNames.scriptBlock)
            const isBasalt = block.typeId == this._frostWalkerBlockTransformTo
            
            if (!isScriptBlock || !isBasalt) {
                throw new Error(true);
            }
            if (ageState >= this._frostWalkerBlockBrokenAge) {
                block.setType(this._frostWalkerBlockTransformBack)
                throw new Error(true);
            }
            const newPermutation = block.permutation.withState(BlockStateNames.customAge, ageState + 1)
            block.setPermutation(newPermutation)
        } catch (killDummy) {
            if (killDummy) DUMMY.kill(dummy) 
        }
    }
}