let ClientboundSetEntityMotionPacket = Java.loadClass("net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket");

function containsTag(tags, tag) {
    let found = false;
    tags.forEach(t => {
        if (t.equals(tag)) {found = true}
    })
    return found;
}

StartupEvents.registry("palladium:abilities", (event) => {
    // modified sheriff movement script
    event.create("arrzenhanced:movement")
    .icon(palladium.createItemIcon("minecraft:barrier"))
    .addProperty("motion_scale", "float", 1.1, "Motion Scale")
    .tick((entity, entry, holder, enabled) => {
        if (enabled) {
            let motionscale = entry.getPropertyByName("motion_scale")
            let move = entity.getLookAngle().scale(motionscale);
            entity.setDeltaMovement(move);

            if (entity.isPlayer()) {
                entity.connection.send(new ClientboundSetEntityMotionPacket(entity));
            }
        }
    });
    
    // kept args for backwards compat
    event.create("arrzenhanced:aoe_damage")
    .icon(palladium.createItemIcon("minecraft:barrier"))
    .addProperty("radius", "integer", 10, "Radius in which surrounding entities will be damaged")
    .addProperty("damage", "float", 3.0, "Damage the ability will deal")
    .addProperty("fire_seconds", "float", 0.0, "How many seconds the entity should be on fire")
    .addProperty("tag_ex", "string", "exclusion_tag", "Tag that exlcudes entities if desired")
    .addProperty("effect", "string", null, "Status effect to give")
    .addProperty("effect_seconds", "float", 2.0, "Status effect seconds")
    .tick((entity, entry, holder, enabled) => {
        if (enabled) {
            let tag_ex = entry.getPropertyByName("tag_ex"),
            firetick = entry.getPropertyByName("fire_seconds"),
            damage = entry.getPropertyByName("damage"),
            radius = entry.getPropertyByName("radius") * 2.0,
            effect = entry.getPropertyByName("effect"),
            effect_seconds = entry.getPropertyByName("effect_seconds")

            let coords = entity.position()

            let level = entity.getLevel()
            level.getEntitiesWithin(AABB.of(
                coords.x() + radius,
                coords.y() + radius,
                coords.z() + radius,
                coords.x() - radius,
                coords.y() - radius,
                coords.z() - radius
            )).forEach(target => {
                if (
                    target !== entity &&
                    target.type !== "minecraft:item" &&
                    target.type !== "minecraft:item_frame" &&
                    target.type !== "minecraft:glow_item_frame" &&
                    target.type !== "minecraft:armor_stand" &&
                    target.type !== "palladium:suit_stand" &&
                    !containsTag(target.getTags().toArray(), tag_ex)
                ) {
                    if (effect != null) {
                        if (!target?.potionEffects) return
                        target.potionEffects.add(effect, effect_seconds * 20, 0, false, false)
                    }

                    let damageSource = getDamageSourceBothSides(level, "minecraft:player_attack", entity, target)
                    target.attack(damageSource, damage)
                    target.setSecondsOnFire(firetick)
                }
            })
        }
    })

    // independency's sake, originally GS
    event.create("arrzenhanced:stat_ability")
    .icon(palladium.createItemIcon("minecraft:barrier"))
    .addProperty("score_value", "string", "Score.Board", "scoreboard name")
    .addProperty("Division_Amount", "string", "1", "optional, amnt to divide by")
    .addProperty("Attribute_Type", "string", "palladium:levitation_speed", "target attribute")
    .addProperty("UUID", "string", "cc154bdc-21f8-11ee-be56-0242ac120002", "UUID used for attribute")
    .addProperty("Attribute_Mod", "string", "addition", "valid options: [addition, multiply_total, multiply_base]")
    .lastTick((entity, entry, holder, enabled) => {
        if (enabled) {
            if (entity.isPlayer()) {
                let division = entry.getPropertyByName("Division_Amount"),
                attribute = entry.getPropertyByName("Attribute_Type"),
                uuid = entry.getPropertyByName("UUID"),
                attribute_mod = entry.getPropertyByName("Attribute_Mod"),
                validOptions = ["addition", "multiply_total", "multiply_base"],
                username = entity.getGameProfile().getName(),
                scoreboard = Utils.server.scoreboard,
                scoreboard_obj = scoreboard.getObjective(entry.getPropertyByName("score_value"))

                if (!validOptions.includes(attribute_mod)) {
                    console.log("ERROR: Invalid attribute modifier!")
                    return false
                }

                if (scoreboard_obj != null) {
                    let score = scoreboard.getOrCreatePlayerScore(username, scoreboard_obj);
                    let value = score.getScore();
                    entity.removeAttribute(attribute, uuid)
                }
            }
        }
    })  
    .tick((entity, entry, holder, enabled) => {
        if (enabled) {
            if (entity.isPlayer()) {
                let division = entry.getPropertyByName("Division_Amount"),
                attribute = entry.getPropertyByName("Attribute_Type"),
                uuid = entry.getPropertyByName("UUID"),
                attribute_mod = entry.getPropertyByName("Attribute_Mod"),
                username = entity.getGameProfile().getName(),
                scoreboard = Utils.server.scoreboard,
                scoreboard_obj = scoreboard.getObjective(entry.getPropertyByName("score_value"))

                if (scoreboard_obj != null) {
                    let score = scoreboard.getOrCreatePlayerScore(username, scoreboard_obj)
                    let value = score.getScore()
                    entity.modifyAttribute(attribute, uuid, (value / division), attribute_mod)
                }
            }
        }
    });
});


