import * as mc from "@minecraft/server"
import * as config from "./pb_scraft_config.js";

import "./pb_scraft_guidebook.js";
import "./pb_scraft_player";
import "./lib/projectile_tester";
import "./blocks/block_registry.js";
import { SPELL_PLAYERS } from "./pb_scraft_player";
import SpellHoldProjectile, { impact } from "./spells/pb_scraft_spellholdprojectile.js";
import SpellChannel from "./spells/pb_scraft_spellchannel.js";
import SpellHoldRaycast, { damagetick } from "./spells/pb_scraft_spellholdraycast.js";
import SpellTargetGround from "./spells/pb_scraft_spelltargetground.js";
import SpellAura from "./spells/pb_scraft_spellaura.js";


itemUseListener();
initAddOn();
config.updateGlobalSettings();
scriptListener();
handleEvents();

function itemUseListener() {

    //start casting
    mc.world.afterEvents.itemStartUse.subscribe((eventData) => {
        let player = eventData.source;
        let itemUse = eventData.itemStack;
        if (itemUse === undefined) return;
        const itemdata = config.CAST_ITEM_LIST.find((f) => f.identifier == itemUse.typeId);
        if (itemdata == undefined) return;

        const spellId = itemUse.getDynamicProperty("pb_scraft_spell");
        if (spellId === undefined) return;
        const spellData = config.SPELL_LIST.find((f) => f.identifier == spellId);
        if (spellData === undefined) return;

        const spellplayer = SPELL_PLAYERS.get(player.id);
        //mc.world.sendMessage("§aSTART: " + spellId);
        if (spellData.type == "projectile") spellplayer.launchSpell(new SpellHoldProjectile(player, spellData, itemUse), itemUse);
        if (spellData.type == "channel") spellplayer.launchSpell(new SpellChannel(player, spellData, itemUse), itemUse);
        if (spellData.type == "raycast") spellplayer.launchSpell(new SpellHoldRaycast(player, spellData, itemUse), itemUse);
        if (spellData.type == "ground") spellplayer.launchSpell(new SpellTargetGround(player, spellData, itemUse), itemUse);
        if (spellData.type == "aura") spellplayer.launchSpell(new SpellAura(player, spellData, itemUse), itemUse);
    })

    //stop casting
    mc.world.afterEvents.itemStopUse.subscribe((eventData) => {
        let player = eventData.source;
        let itemUse = eventData.itemStack;
        if (itemUse === undefined) return;
        const itemdata = config.CAST_ITEM_LIST.find((f) => f.identifier == itemUse.typeId);
        if (itemdata == undefined) return;

        const spellId = itemUse.getDynamicProperty("pb_scraft_spell");
        if (spellId === undefined) return;

        const spellplayer = SPELL_PLAYERS.get(player.id);
        spellplayer.stop(spellId);
    })
}

function handleEvents() {
    mc.system.afterEvents.scriptEventReceive.subscribe((eventData) => {
        const { id, sourceEntity, message, sourceBlock } = eventData;

        if (id == "pb_scraft:expire") {
            if (sourceEntity == undefined) return;
            const projectileData = config.EFFECT_LIST.find((f) => f.identifier == sourceEntity.typeId);
            if (projectileData != undefined) {
                impact({ dimension: sourceEntity.dimension, location: sourceEntity.location, projectile: sourceEntity }, projectileData);
                sourceEntity.remove();
            }
        }
        if (id == "pb_scraft:damage_tick") {
            if (sourceEntity == undefined) return;
            const projectileData = config.EFFECT_LIST.find((f) => f.identifier == sourceEntity.typeId);
            if (projectileData != undefined) {
                damagetick({ dimension: sourceEntity.dimension, location: sourceEntity.location, source: sourceEntity }, projectileData);
            }
        }
    })

    mc.world.afterEvents.projectileHitEntity.subscribe((eventData) => {
        const projectileData = config.EFFECT_LIST.find((f) => f.identifier == eventData.projectile.typeId);
        if (projectileData == undefined) return;
        impact(eventData, projectileData);
    });

    mc.world.afterEvents.projectileHitBlock.subscribe((eventData) => {
        const projectileData = config.EFFECT_LIST.find((f) => f.identifier == eventData.projectile.typeId);
        if (projectileData == undefined) return;
        impact(eventData, projectileData);
    });
}

function scriptListener() {
    mc.system.afterEvents.scriptEventReceive.subscribe((eventData) => {
        const { id, sourceEntity, message, sourceBlock } = eventData;

        if (id == "pb_scraft:stop") {
            sourceEntity.clearVelocity();
        }

        if (id == "pb_scraft:rune_test") {

            let mvm = new mc.MolangVariableMap();
            mvm.setFloat("variable.radius", 2);
            mvm.setFloat("variable.angle", 45);
            mvm.setFloat("variable.rotation", 0);

            //mc.world.sendMessage("num:" + parseInt(message));
            mc.world.getDimension(sourceEntity.dimension.id).spawnParticle("pb_scraft:rune_spin", sourceEntity.location, mvm);
        }
    })
}

function initAddOn() {
    if (mc.world.scoreboard.getObjective("pb_scraft_mana") === undefined) mc.world.scoreboard.addObjective("pb_scraft_mana", "pb_scraft_mana");
    if (mc.world.scoreboard.getObjective("pb_scraft_actionbar") === undefined) mc.world.scoreboard.addObjective("pb_scraft_actionbar", "pb_scraft_actionbar");
    if (mc.world.scoreboard.getObjective("pb_scraft_fail") === undefined) mc.world.scoreboard.addObjective("pb_scraft_fail", "pb_scraft_fail");

    if (mc.world.scoreboard.getObjective("pb_scraft_settings") === undefined) {
        mc.world.scoreboard.addObjective("pb_scraft_settings", "pb_scraft_settings");  //global settings
        mc.world.scoreboard.getObjective("pb_scraft_settings").setScore("MANA_REG", 5);
        mc.world.scoreboard.getObjective("pb_scraft_settings").setScore("DMG_SCALING", 100);
        mc.world.scoreboard.getObjective("pb_scraft_settings").setScore("PVP", 0);
        mc.world.scoreboard.getObjective("pb_scraft_settings").setScore("PVP_SCALING", 0);
    }
}