import { world, system } from "@minecraft/server";

// --- 定数定義 ---
const APP_ID = "aperion";
const HUD_PROP = `${APP_ID}:hide_hud`;
const DIFF_PROP = `${APP_ID}:difficulty`;

// 難易度設定データ
const DIFFICULTIES = {
    easy: {
        damage: 2,
        charge: 2,      
        decay: -4,      
        recoverPercent: 0.7,
        label: "§aEASY"
    },
    normal: {
        damage: 4,
        charge: 1,      
        decay: -8,      
        recoverPercent: 0.95,
        label: "§eNORMAL"
    },
    hard: {
        damage: 8,      
        charge: 1,      
        decay: -16,     
        recoverPercent: 0.99,
        label: "§c§lHARD (EXTREME)"
    }
};

const OVERDRIVE_LEVEL = 15;

// プレイヤー状態管理
const lastLocations = new Map();
const safeUntilMove = new Map(); // 動き出すまで安全かどうかを管理

/**
 * 難易度取得
 */
function getDifficulty() {
    const diff = world.getDynamicProperty(DIFF_PROP);
    return DIFFICULTIES[diff] ?? DIFFICULTIES.normal;
}

// スポーン・リスポーン処理
world.afterEvents.playerSpawn.subscribe((event) => {
    const { player } = event;
    // 動き出すまで安全フラグを立てる
    safeUntilMove.set(player.id, true);
    lastLocations.delete(player.id);
});

// ディメンション移動（ネザー/エンド等）時の処理
world.afterEvents.playerDimensionChange.subscribe((event) => {
    const { player } = event;
    // 移動直後も動き出すまで安全にする
    safeUntilMove.set(player.id, true);
    lastLocations.delete(player.id);
});

// 退出時のクリーンアップ
world.beforeEvents.playerLeave.subscribe((event) => {
    const { player } = event;
    lastLocations.delete(player.id);
    safeUntilMove.delete(player.id);
});

// チャットコマンド処理
world.beforeEvents.chatSend.subscribe((event) => {
    const { sender: player, message } = event;
    const msg = message.toLowerCase().trim();

    if (msg === "!hud") {
        event.cancel = true;
        const current = player.getDynamicProperty(HUD_PROP) === true;
        player.setDynamicProperty(HUD_PROP, !current);
        player.sendMessage(`§b[System]§r HUD display: ${!current ? "§cOFF" : "§aON"}`);
        return;
    }

    let targetDiff = null;
    if (msg === "!d1") targetDiff = "easy";
    if (msg === "!d2") targetDiff = "normal";
    if (msg === "!d3") targetDiff = "hard";

    if (targetDiff) {
        event.cancel = true;
        world.setDynamicProperty(DIFF_PROP, targetDiff);
        world.sendMessage(`§b[System]§r ${player.name} changed difficulty to: ${DIFFICULTIES[targetDiff].label}`);
        return;
    }
});

// メインループ
system.runInterval(() => {
    const config = getDifficulty();

    for (const player of world.getAllPlayers()) {
        const playerId = player.id;

        // 位置情報の初期化
        if (!lastLocations.has(playerId)) {
            lastLocations.set(playerId, player.location);
            continue;
        }

        const { x, y, z } = player.location;
        const lastLoc = lastLocations.get(playerId);
        const hideHud = player.getDynamicProperty(HUD_PROP) === true;

        // 移動距離を計算
        const distance = Math.sqrt(
            Math.pow(x - lastLoc.x, 2) +
            Math.pow(y - lastLoc.y, 2) +
            Math.pow(z - lastLoc.z, 2)
        );

        // --- 安全状態チェック ---

        // (1) 動き出すまで安全 (スポーン/ポータル移動後)
        if (safeUntilMove.get(playerId) === true) {
            if (distance > 0.15) {
                // 一定以上動いたら安全時間を終了
                safeUntilMove.set(playerId, false);
            } else {
                // 動いていない間は安全
                if (!hideHud) {
                    player.onScreenDisplay.setActionBar(`§a§l[ READY TO MOVE (SAFE) ]`);
                }
                lastLocations.set(playerId, { x, y, z });
                continue;
            }
        }

        // (2) 睡眠中
        if (player.isSleeping) {
            if (!hideHud) player.onScreenDisplay.setActionBar(`§b§l[ SLEEPING (SAFE) ]`);
            lastLocations.set(playerId, { x, y, z });
            continue;
        }

        // (3) チャット中
        if (player.isChatting) {
            if (!hideHud) player.onScreenDisplay.setActionBar(`§e§l[ CHATTING (SAFE) ]`);
            lastLocations.set(playerId, { x, y, z });
            continue;
        }

        // --- メインロジック (エネルギー計算) ---

        let level = player.level;
        let progress = player.xpEarnedAtCurrentLevel;

        if (distance > 0.15) {
            // 充電中
            player.addExperience(config.charge);
            if (!hideHud) {
                player.onScreenDisplay.setActionBar(`§b>> CHARGING... §l${Math.floor(distance * 100)}%`);
            }
        } else {
            // 放電/ダメージ
            if (level > 0 || progress > 0.1) {
                player.addExperience(config.decay);

                if (player.xpEarnedAtCurrentLevel <= 0 && player.level > 0) {
                    player.addLevels(-1);
                    const nextLevelReq = player.totalXpNeededForNextLevel ?? 20;
                    const recoverAmount = Math.floor(nextLevelReq * config.recoverPercent);
                    player.addExperience(recoverAmount);
                }

                if (!hideHud) {
                    player.onScreenDisplay.setActionBar(`§c!! WARNING: ENERGY LOW !!`);
                }
            } else {
                player.applyDamage(config.damage);
                player.playSound("random.break");
                if (!hideHud) {
                    player.onScreenDisplay.setActionBar(`§4§l!!! DANGER: STOPPED !!!`);
                }
            }
        }

        // オーバードライブ
        if (level >= OVERDRIVE_LEVEL) {
            player.addEffect("haste", 20, { amplifier: 2, showParticles: false });
            player.addEffect("speed", 20, { amplifier: 1, showParticles: false });
            if (!hideHud) {
                player.onScreenDisplay.setActionBar(`§a§l>>> SPRINT BOOST <<<`);
            }
        }

        lastLocations.set(playerId, { x, y, z });
    }
}, 4);