//=============================================================================
// ItemPopup.js
//=============================================================================
/*:
 * @target MZ
 * @plugindesc アイテムと所持金入手時にポップアップ表示するプラグイン（イベント経由のみ）
 * @author えむうん
 * 
 * @param windowWidth
 * @text ウィンドウ幅
 * @type number
 * @min 1
 * @default 300
 *
 * @param windowHeight
 * @text ウィンドウ高さ
 * @type number
 * @min 1
 * @default 100
 *
 * @param displayTime
 * @text 表示時間
 * @type number
 * @min 1
 * @default 120
 * @desc ポップアップウィンドウの表示時間（フレーム単位）
 *
 * @param positionType
 * @text 表示位置タイプ
 * @type select
 * @option 固定位置
 * @value fixed
 * @option プレイヤー追従
 * @value player
 * @default fixed
 *
 * @param windowX
 * @text ウィンドウX位置
 * @type number
 * @min 0
 * @default 408
 * @desc 固定位置表示の場合のX座標
 *
 * @param windowY
 * @text ウィンドウY位置
 * @type number
 * @min 0
 * @default 312
 * @desc 固定位置表示の場合のY座標
 *
 * @param playerOffsetX
 * @text プレイヤーからのX offset
 * @type number
 * @min -1000
 * @max 1000
 * @default 0
 * @desc プレイヤー追従時のX方向のオフセット
 *
 * @param playerOffsetY
 * @text プレイヤーからのY offset
 * @type number
 * @min -1000
 * @max 1000
 * @default -48
 * @desc プレイヤー追従時のY方向のオフセット
 *
 * @param windowOpacity
 * @text ウィンドウ透明度
 * @type number
 * @min 0
 * @max 255
 * @default 255
 *
 * @param popupSpacing
 * @text ポップアップ間隔
 * @type number
 * @min 1
 * @default 10
 * @desc ポップアップウィンドウ同士の間隔（ピクセル単位）
 *
 * @param popupDelay
 * @text ポップアップディレイ
 * @type number
 * @min 0
 * @default 30
 * @desc 各ポップアップウィンドウの表示ディレイ（フレーム単位）
 *
 * @param itemSE
 * @text アイテムSE
 * @type struct<SoundEffect>
 * @default {"name":"Heal","volume":"90","pitch":"100","pan":"0"}
 *
 * @param goldSE
 * @text 所持金SE
 * @type struct<SoundEffect>
 * @default {"name":"Coin","volume":"90","pitch":"100","pan":"0"}
 *
 * @help
 * このプラグインは、アイテムと所持金をイベントで入手した時にポップアップウィンドウを表示します。
 * 
 * 【表示位置タイプについて】
 * 固定位置: 画面上の指定した座標に表示されます。
 * プレイヤー追従: プレイヤーキャラクターの位置を基準に表示されます。
 * オフセット値を使って、プレイヤーからの相対位置を調整できます。
 * 
 * 変更点:
 * - イベントコマンドでアイテム、武器、防具を増やした場合のみ、ポップアップウィンドウが表示されます。
 * - GetEnemyRewards.js でアイテムを取得した場合にもポップアップウィンドウが表示されます。
 * - 装備を外した場合にポップアップウィンドウが表示されないようにしました。
 * - RPGツクールMZ用に最適化されました。
 * - 表示位置をプレイヤー追従にも設定できるようになりました。
 */

/*~struct~SoundEffect:
 * @param name
 * @text SEファイル名
 * @type file
 * @dir audio/se
 * @default Heal
 * 
 * @param volume
 * @text 音量
 * @type number
 * @min 0
 * @max 100
 * @default 90
 * 
 * @param pitch
 * @text ピッチ
 * @type number
 * @min 50
 * @max 150
 * @default 100
 * 
 * @param pan
 * @text 位相
 * @type number
 * @min -100
 * @max 100
 * @default 0
 */

(() => {
    'use strict';
    
    const pluginName = "ItemPopup";
    const parameters = PluginManager.parameters(pluginName);

    const windowWidth = Number(parameters['windowWidth'] || 300);
    const windowHeight = Number(parameters['windowHeight'] || 100);
    const displayTime = Number(parameters['displayTime'] || 120);
    const positionType = String(parameters['positionType'] || 'fixed');
    const fixedWindowX = Number(parameters['windowX'] || 408);
    const fixedWindowY = Number(parameters['windowY'] || 312);
    const playerOffsetX = Number(parameters['playerOffsetX'] || 0);
    const playerOffsetY = Number(parameters['playerOffsetY'] || -48);
    const windowOpacity = Number(parameters['windowOpacity'] || 255);
    const popupSpacing = Number(parameters['popupSpacing'] || 10);
    const popupDelay = Number(parameters['popupDelay'] || 30);

    const parseSEParameter = (paramString) => {
        try {
            const obj = JSON.parse(paramString);
            return {
                name: String(obj.name || ''),
                volume: Number(obj.volume || 90),
                pitch: Number(obj.pitch || 100),
                pan: Number(obj.pan || 0)
            };
        } catch (e) {
            console.error('ItemPopup: Failed to parse SE parameter:', e);
            return {
                name: 'Heal',
                volume: 90,
                pitch: 100,
                pan: 0
            };
        }
    };

    const itemSE = parseSEParameter(parameters['itemSE']);
    const goldSE = parseSEParameter(parameters['goldSE']);

    let popups = [];
    let popupQueue = [];
    let popupDelayTimer = 0;
    let isEquipChange = false;

    //-----------------------------------------------------------------------------
    // Window_ItemPopup
    //
    class Window_ItemPopup extends Window_Base {
        constructor(text) {
            // 初期位置を計算
            const position = calculateInitialPosition();
            super(new Rectangle(position.x, position.y, windowWidth, windowHeight));
            this.opacity = windowOpacity;
            this._text = text;
            this._displayCount = displayTime;
            this._reachedTarget = false;
            this._baseX = position.x;
            this._baseY = position.y;
            this.refresh();
        }

        update() {
            super.update();
            if (positionType === 'player') {
                this.updatePosition();
            }
            if (this._reachedTarget) {
                if (this._displayCount > 0) {
                    this._displayCount--;
                } else {
                    this.parent.removeChild(this);
                    const index = popups.indexOf(this);
                    if (index > -1) {
                        popups.splice(index, 1);
                    }
                    $gameParty.updatePopups();
                }
            }
        }

        updatePosition() {
            const position = calculateInitialPosition();
            this._baseX = position.x;
            this._baseY = position.y;
        }

        refresh() {
            this.contents.clear();
            this.drawText(this._text, 0, 0, this.innerWidth, 'center');
        }
    }

    //-----------------------------------------------------------------------------
    // Calculate Position
    //
    const calculateInitialPosition = () => {
        if (positionType === 'player') {
            const player = $gamePlayer;
            const x = player.screenX() + playerOffsetX - windowWidth / 2;
            const y = player.screenY() + playerOffsetY - windowHeight;
            return { x, y };
        } else {
            return { x: fixedWindowX, y: fixedWindowY };
        }
    };

    //-----------------------------------------------------------------------------
    // Game_Party
    //
    const _Game_Party_gainItem = Game_Party.prototype.gainItem;
    Game_Party.prototype.gainItem = function(item, amount, includeEquip) {
        _Game_Party_gainItem.call(this, item, amount, includeEquip);
        if (amount > 0 && item && !isEquipChange) {
            this.queuePopup(item.name + ' x' + amount, itemSE);
        }
    };

    Game_Party.prototype.queuePopup = function(text, se) {
        popupQueue.push({ text: text, se: se });
    };

    Game_Party.prototype.processPopupQueue = function() {
        if (popupQueue.length > 0 && popupDelayTimer <= 0) {
            const popupData = popupQueue.shift();
            this.showPopup(popupData.text, popupData.se);
            popupDelayTimer = popupDelay;
        }
    };

    Game_Party.prototype.showPopup = function(text, se) {
        const popup = new Window_ItemPopup(text);
        SceneManager._scene.addChild(popup);
        popups.unshift(popup);
        AudioManager.playSe(se);
        this.updatePopups();
    };

    Game_Party.prototype.updatePopups = function() {
        for (let i = 0; i < popups.length; i++) {
            let targetY = popups[i]._baseY - (i * (windowHeight + popupSpacing));
            if (targetY < 0) {
                targetY = popups[i]._baseY + ((popups.length - 1 - i) * (windowHeight + popupSpacing));
            }
            this.animatePopup(popups[i], targetY);
        }
    };

    Game_Party.prototype.animatePopup = function(popup, targetY) {
        const moveSpeed = 5;
        if (popup.y < targetY) {
            popup.y = Math.min(popup.y + moveSpeed, targetY);
        } else if (popup.y > targetY) {
            popup.y = Math.max(popup.y - moveSpeed, targetY);
        }
        if (Math.abs(popup.y - targetY) < moveSpeed) {
            popup.y = targetY;
            popup._reachedTarget = true;
        }
    };

    //-----------------------------------------------------------------------------
    // Game_Actor
    //
    const _Game_Actor_changeEquip = Game_Actor.prototype.changeEquip;
    Game_Actor.prototype.changeEquip = function(slotId, item) {
        isEquipChange = true;
        _Game_Actor_changeEquip.call(this, slotId, item);
        isEquipChange = false;
    };

    //-----------------------------------------------------------------------------
    // Game_Party
    //
    const _Game_Party_gainGold = Game_Party.prototype.gainGold;
    Game_Party.prototype.gainGold = function(amount) {
        _Game_Party_gainGold.call(this, amount);
        if (amount > 0) {
            this.queuePopup('所持金 +' + amount, goldSE);
        }
    };

    //-----------------------------------------------------------------------------
    // Scene_Map
    //
    const _Scene_Map_update = Scene_Map.prototype.update;
    Scene_Map.prototype.update = function() {
        _Scene_Map_update.call(this);
        if (popupDelayTimer > 0) {
            popupDelayTimer--;
        }
        $gameParty.processPopupQueue();
        $gameParty.updatePopups();
    };

    //-----------------------------------------------------------------------------
    // Game_Interpreter
    //
    const _Game_Interpreter_command126 = Game_Interpreter.prototype.command126;
    Game_Interpreter.prototype.command126 = function(params) {
        const result = _Game_Interpreter_command126.call(this, params);
        if (params[1] > 0) {
            const item = $dataItems[params[0]];
            if (item) {
                $gameParty.queuePopup(item.name + ' x' + params[1], itemSE);
            }
        }
        return result;
    };

    const _Game_Interpreter_command127 = Game_Interpreter.prototype.command127;
    Game_Interpreter.prototype.command127 = function(params) {
        const result = _Game_Interpreter_command127.call(this, params);
        if (params[1] > 0) {
            const item = $dataWeapons[params[0]];
            if (item) {
                $gameParty.queuePopup(item.name + ' x' + params[1], itemSE);
            }
        }
        return result;
    };

    const _Game_Interpreter_command128 = Game_Interpreter.prototype.command128;
    Game_Interpreter.prototype.command128 = function(params) {
        const result = _Game_Interpreter_command128.call(this, params);
        if (params[1] > 0) {
            const item = $dataArmors[params[0]];
            if (item) {
                $gameParty.queuePopup(item.name + ' x' + params[1], itemSE);
            }
        }
        return result;
    };
})();