import * as mc from "@minecraft/server";
import * as vector from "../utils/vector";
import * as selectors from "../utils/selectors";
import { GeomancyWhitelist } from "../items/earthrendGauntlet";

export const ATTACK_RANGE = 12;
const ATTACK_KF = [20, 35]
const ATTACK_CD = 70;

const ATTACK_HIT_DIST = 3;
const ATTACK_KB = 1.5;
export const ATTACK_DAMAGE = 5;

export function eventBehavior(event) {
    const entity = event.entity;

    if (event.eventId === 'register') {
        entity.setDynamicProperty("hf_mzs:attack_cooldown", ATTACK_CD);
        entity.setProperty("hf_mzs:attacking", false);
        return;
    }
    if (event.eventId === 'attempt_attack') {
        if (entity.getDynamicProperty("hf_mzs:attack_cooldown") > 0)
            return;
        const player = getTarget(entity);
        if (player === undefined || !player.isValid())
            return;
        if (Math.abs(player.location.y - entity.location.y) > 2)
            return;
        entity.setProperty("hf_mzs:attacking", true);
        entity.addEffect("slowness", ATTACK_KF[1], {
            amplifier: 100,
            showParticles: false
        });
        rotateToTarget(entity, player);
        mc.system.runTimeout(() => {
            if (!player.isValid())
                return;
            rotateToTarget(entity, player);
            // knockback
            selectors.union({
                location: entity.location,
                maxDistance: ATTACK_HIT_DIST,
                excludeFamilies: ['inanimate', 'hf_mzs_bluff']
            }, ['mob', 'player'], entity.dimension, entity.id)
                .forEach((target) => {
                    if (target.isValid()) {
                        const dir = vector.subtract(target.location,
                            entity.location);
                        target.applyKnockback(dir.x, dir.z,
                            ATTACK_KB, ATTACK_KB / 3);
                        target.applyDamage(ATTACK_DAMAGE, {
                            cause: "entityAttack",
                            damagingEntity: entity
                        });
                    }
                });

            // projectile
            const proj = entity.dimension.spawnEntity("hf_mzs:bluff_projectile", entity.location);
            const dir = vector.flatten(entity.getViewDirection(), 'y');
            proj.setDynamicProperty("hf_mzs:x_dir", dir.x);
            proj.setDynamicProperty("hf_mzs:z_dir", dir.z);
            proj.setDynamicProperty("hf_mzs:shooter", entity.id);

            // effects
            entity.runCommand("/particle hf_mzs:bluff_crash2 ~~~");
            entity.runCommand("/particle hf_mzs:bluff_crash3 ~~~");
            entity.runCommand("/camerashake add @a[r=16] 0.25 0.25 positional");

            mc.system.runTimeout(() => {
                entity.setDynamicProperty("hf_mzs:attack_cooldown", ATTACK_CD);
                entity.setProperty("hf_mzs:attacking", false);
            }, ATTACK_KF[1] - ATTACK_KF[0]);
        }, ATTACK_KF[0]);
        return;
    }
    // make it despawn because very rarely it fails to for some reason
    if (event.eventId === 'death') {
        mc.system.runTimeout(()=>{
            if (!event.entity.isValid())
                return;
            event.entity.triggerEvent("drop");
        }, 50);
        return;
    }
    // if (event.eventId === 'death') {
    //     return;
    // }
}
export function tick5(entity) {
    if (entity.getDynamicProperty("hf_mzs:attack_cooldown") > 0)
        entity.setDynamicProperty("hf_mzs:attack_cooldown",
            entity.getDynamicProperty("hf_mzs:attack_cooldown") - 5);

    const entities = selectors.union({
        location: entity.location,
        maxDistance: 1,
    }, ["player", "mob"], entity.dimension, entity.id);

    for (let i = 0; i < entities.length; i++) {
        if (entities[i] === undefined || !entities[i].isValid())
            continue;
        entity.setDynamicProperty("hf_mzs:attack_cooldown", 0);
        const v = vector.subtract(entities[i].location, entity.location);
        entities[i].applyKnockback(v.x, v.y, 1.5, 0);
    }
    
    // check if on solid ground to play particle
    const ground = entity.dimension.getBlockFromRay(vector.add(entity.location, vector.up), vector.down, {
       maxDistance: 2,
       includePassableBlocks: false,
       includeLiquidBlocks: false 
    });
    if (ground !== undefined && !ground.block.isValid())
        return;
    //mc.world.sendMessage(`${ground.block.typeId}`);
    if (ground === undefined || !GeomancyWhitelist.includes(ground.block.typeId)) {
        entity.setProperty("hf_mzs:on_rock", false);
        return;
    }
    entity.setProperty("hf_mzs:on_rock", true);
}
export function tick1(entity) {
}

function getTarget(entity) {
    const targets = selectors.union({
        maxDistance: 64,
        location: entity.location
    }, ["player", "hf_mzs_sculptor"], entity.dimension, entity.id, false);
    for (const target of targets) {
        if (target.isValid() && (target.typeId === "minecraft:player" ? target.getGameMode()!=="creative" : 1))
            return target;
    }
    return undefined;
}
function rotateToTarget(entity, target) {
    const deltaPos = vector.subtract(target.location, entity.location);

    const xRot = -90+Math.acos(deltaPos.y / vector.magnitude(deltaPos))/Math.PI * 180;
    const yRot = -(Math.atan2(deltaPos.x, deltaPos.z))/Math.PI * 180;
    
    entity.setRotation({
        x: xRot, 
        y: yRot
    });
}