const GHAST_TEAR_CONDENSER_CHARGES = 3
const GHAST_TEAR_CONDENSER_RADIUS = 32
const GHAST_TEAR_CONDENSER_SOUL_BLOCKS = [
    'minecraft:soul_sand',
    'minecraft:soul_soil'
]

const ghastTearCondenserData = {}

function ghastTearCondenserKey(level, block) {
    return `${level.dimension}:${block.x},${block.y},${block.z}`
}

function hasSoulBlockNearCondenser(level, block) {
    const positions = [
        [1, 0, 0],
        [-1, 0, 0],
        [0, 0, 1],
        [0, 0, -1],
        [1, 0, 1],
        [1, 0, -1],
        [-1, 0, 1],
        [-1, 0, -1]
    ]

    return positions.some(offset => {
        const nearby = level.getBlock(block.x + offset[0], block.y + offset[1], block.z + offset[2])
        return nearby && GHAST_TEAR_CONDENSER_SOUL_BLOCKS.includes(nearby.id)
    })
}

function hasGhastNearCondenser(level, block) {
    const x = block.x + 0.5
    const y = block.y + 0.5
    const z = block.z + 0.5

    return level.server.runCommandSilent(
        `execute in minecraft:the_nether positioned ${x} ${y} ${z} if entity @e[type=minecraft:ghast,distance=..${GHAST_TEAR_CONDENSER_RADIUS}]`
    ) > 0
}

function playCondenserEffects(level, block, complete) {
    const x = block.x + 0.5
    const y = block.y + 0.8
    const z = block.z + 0.5
    const sound = complete ? 'minecraft:entity.ghast.scream' : 'minecraft:block.amethyst_block.chime'
    const particle = complete ? 'minecraft:soul_fire_flame' : 'minecraft:portal'

    level.runCommandSilent(`particle ${particle} ${x} ${y} ${z} 0.35 0.25 0.35 0.02 ${complete ? 30 : 12}`)
    level.runCommandSilent(`playsound ${sound} block @a[distance=..24] ${x} ${y} ${z} ${complete ? 0.7 : 0.45} ${complete ? 1.4 : 0.8}`)
}

function getVectorPart(vector, axis) {
    const value = vector[axis]
    return typeof value === 'function' ? value() : value
}

function getLookedAtBlock(level, player, maxDistance) {
    let look
    let eyeY

    try {
        look = player.getLookAngle()
        eyeY = player.getEyeY()
    } catch (error) {
        return null
    }

    const dx = getVectorPart(look, 'x')
    const dy = getVectorPart(look, 'y')
    const dz = getVectorPart(look, 'z')

    for (let distance = 0.5; distance <= maxDistance; distance += 0.1) {
        const block = level.getBlock(
            Math.floor(player.x + dx * distance),
            Math.floor(eyeY + dy * distance),
            Math.floor(player.z + dz * distance)
        )

        if (block && block.id !== 'minecraft:air' && block.id !== 'minecraft:cave_air' && block.id !== 'minecraft:void_air') {
            return block
        }
    }

    return null
}

function runGhastTearCondenser(event, block, item) {
    const { level, player } = event

    if (level.isClientSide()) return
    if (!block || block.id !== 'minecraft:crying_obsidian') return
    if (!item || item.id !== 'minecraft:glass_bottle') return

    event.cancel()

    if (level.dimension.toString() !== 'minecraft:the_nether') {
        player.tell(Text.of('The lament condenser only works in the Nether.').red())
        return
    }

    const below = level.getBlock(block.x, block.y - 1, block.z)
    if (!below || below.id !== 'minecraft:lava') {
        player.tell(Text.of('Lava must be directly below the crying obsidian.').red())
        return
    }

    if (!hasSoulBlockNearCondenser(level, block)) {
        player.tell(Text.of('Soul sand or soul soil must be next to the condenser.').red())
        return
    }

    if (!hasGhastNearCondenser(level, block)) {
        player.tell(Text.of('A living ghast must be nearby.').red())
        playCondenserEffects(level, block, false)
        return
    }

    const key = ghastTearCondenserKey(level, block)
    const charges = (ghastTearCondenserData[key] || 0) + 1

    if (charges < GHAST_TEAR_CONDENSER_CHARGES) {
        ghastTearCondenserData[key] = charges
        player.tell(Text.of(`The condenser absorbed a cry: ${charges}/${GHAST_TEAR_CONDENSER_CHARGES}.`).aqua())
        playCondenserEffects(level, block, false)
        return
    }

    ghastTearCondenserData[key] = 0
    item.shrink(1)
    player.give(Item.of('minecraft:ghast_tear'))
    player.tell(Text.of('The Nether cry condensed into a ghast tear.').aqua())
    playCondenserEffects(level, block, true)
}

BlockEvents.rightClicked(event => {
    runGhastTearCondenser(event, event.block, event.item)
})

ItemEvents.rightClicked('minecraft:glass_bottle', event => {
    if (event.level.isClientSide()) return

    const block = getLookedAtBlock(event.level, event.player, 5)
    if (!block || block.id !== 'minecraft:crying_obsidian') return

    runGhastTearCondenser(event, block, event.item)
})
