/*:
 * @target MZ
 * @plugindesc ピクチャを通り過ぎて戻るように動かす（座標に変数対応・最終座標確定・ウェイト対応）v1.3.0
 * @author ChatGPT
 * 
 * @command OvershootMovePicture
 * @text 通り過ぎて戻るピクチャ移動
 *
 * @arg pictureId
 * @type number
 * @text ピクチャ番号
 * @min 1
 *
 * @arg targetX
 * @type string
 * @text 移動先X（数値または \v[n]）
 *
 * @arg targetY
 * @type string
 * @text 移動先Y（数値または \v[n]）
 *
 * @arg duration
 * @type number
 * @text 移動時間（フレーム数）
 * @min 1
 *
 * @arg overshoot
 * @type number
 * @text オーバーシュート量
 * @default 30
 *
 * @arg wait
 * @type boolean
 * @text 完了までウェイト
 * @default false
 */

(() => {
    const pluginName = "OvershootMovePicture";

    PluginManager.registerCommand(pluginName, "OvershootMovePicture", function(args) {
        const pictureId = Number(args.pictureId);
        const targetX = Number(convertEscape(args.targetX));
        const targetY = Number(convertEscape(args.targetY));
        const duration = Number(args.duration);
        const overshoot = Number(args.overshoot);
        const wait = args.wait === "true"; // ←追加

        const picture = $gameScreen.picture(pictureId);
        if (!picture) return;

        const startX = picture.x();
        const startY = picture.y();

        picture._overshootStartX = startX;
        picture._overshootStartY = startY;

        const dx = targetX - startX;
        const dy = targetY - startY;
        const dist = Math.sqrt(dx * dx + dy * dy);
        if (dist === 0) return;

        const normX = dx / dist;
        const normY = dy / dist;

        const overshootX = targetX + normX * overshoot;
        const overshootY = targetY + normY * overshoot;

        const half = Math.floor(duration / 2);

        picture._moveOvershootPhase = 1;
        picture._moveOvershootData = {
            phase1: { x: overshootX, y: overshootY, d: half },
            phase2: { x: targetX, y: targetY, d: duration - half },
            count: 0,
            pictureId: pictureId,
            finalX: targetX,
            finalY: targetY,
            waiting: wait
        };

        // ウェイト要求があればインタプリタに通知
        if (wait) {
            this.setWaitMode("overshootPicture" + pictureId);
        }
    });

    function convertEscape(str) {
        return str.replace(/\\v\[(\d+)\]/gi, (_, n) => $gameVariables.value(Number(n)));
    }

    const _Sprite_Picture_update = Sprite_Picture.prototype.update;
    Sprite_Picture.prototype.update = function () {
        _Sprite_Picture_update.call(this);
        const picture = this.picture();
        if (!picture || !picture._moveOvershootPhase) return;

        const data = picture._moveOvershootData;
        data.count++;

        if (picture._moveOvershootPhase === 1) {
            const t = data.count / data.phase1.d;
            if (t >= 1) {
                this.x = data.phase1.x;
                this.y = data.phase1.y;
                picture._moveOvershootPhase = 2;
                data.count = 0;
            } else {
                this.x = lerp(picture._overshootStartX, data.phase1.x, easeOutQuad(t));
                this.y = lerp(picture._overshootStartY, data.phase1.y, easeOutQuad(t));
            }
        } else if (picture._moveOvershootPhase === 2) {
            const t = data.count / data.phase2.d;
            if (t >= 1) {
                this.x = data.phase2.x;
                this.y = data.phase2.y;

                // ←★ピクチャの本来の位置を確定（内部座標も更新）
                const pic = $gameScreen.picture(data.pictureId);
                if (pic) {
                    $gameScreen.movePicture(
                        data.pictureId,
                        pic.origin(),
                        data.finalX,
                        data.finalY,
                        pic.scaleX(),
                        pic.scaleY(),
                        pic.opacity(),
                        pic.blendMode(),
                        1 // 1フレームで即時反映
                    );
                }

                // ウェイト解除
                if (data.waiting) {
                    data.waiting = false;
                }

                delete picture._moveOvershootPhase;
                delete picture._moveOvershootData;
                delete picture._overshootStartX;
                delete picture._overshootStartY;
            } else {
                this.x = lerp(data.phase1.x, data.phase2.x, easeOutQuad(t));
                this.y = lerp(data.phase1.y, data.phase2.y, easeOutQuad(t));
            }
        }
    };

    function lerp(a, b, t) {
        return a + (b - a) * t;
    }

    function easeOutQuad(t) {
        return t * (2 - t);
    }

    // Interpreterのウェイト処理拡張
    const _Game_Interpreter_updateWaitMode = Game_Interpreter.prototype.updateWaitMode;
    Game_Interpreter.prototype.updateWaitMode = function() {
        if (this._waitMode && this._waitMode.startsWith("overshootPicture")) {
            const pictureId = Number(this._waitMode.replace("overshootPicture", ""));
            const picture = $gameScreen.picture(pictureId);
            if (picture && picture._moveOvershootData && picture._moveOvershootData.waiting) {
                return true; // まだ移動中なら待機
            } else {
                this._waitMode = "";
                return false;
            }
        }
        return _Game_Interpreter_updateWaitMode.call(this);
    };
})();
