//=============================================================================
// RPG Maker MZ - Scene_StaffRoll
//
// Copyright 2024 Panzer-IV. All rights reserved.
// This source code or any portion thereof must not be
// reproduced or used without licensed in any manner whatsoever.
//=============================================================================
/*:
 * @target MZ
 * @plugindesc スタッフロール画面プラグイン
 * @author 四号戦車
 * @base PluginCommonBase
 * @base DebugSwitch
 * @base PluginUtils
 * @orderAfter PluginCommonBase
 * @orderAfter DebugSwitch
 * @orderAfter PluginUtils
 *
 * @param images
 * @text スタッフロール画像
 * @desc スタッフロールの画像
 * @type file[]
 * @dir img/system
 * @default []
 *
 * @param bgm
 * @text BGM指定
 * @desc BGMの指定です。
 * @type file
 * @dir audio/bgm
 * @default
 *
 * @param event
 * @text 次のイベント
 * @desc スタッフロール終了後移動するイベントの指定です。
 * @type common_event
 * @default 0
 *
 * @param scrollWithMusic
 * @text BGM追従スクロール設定
 * @desc BGMの終了とスクロールの終了を併せます。
 * @type boolean
 * @default false
 *
 * @help Scene_StaffRoll.js
 *
 * Version: 0.0.1
 *
 * スタッフロール画面
 *
 * @command startStaffRoll
 * @text スタッフロール開始
 * @desc スタッフロールを開始します。
 */
(() => {
	"use strict";

    //========================================================================
    // プラグイン定義
    //========================================================================
    const pluginName = "Scene_StaffRoll";
    const script = document.currentScript;
    const param  = PluginManagerEx.createParameter(script);

    //========================================================================
    // コアスクリプト変更部 (Scene_Boot)
    //========================================================================
    const _Scene_Boot_prototype_onDatabaseLoaded = Scene_Boot.prototype.onDatabaseLoaded;
    Scene_Boot.prototype.onDatabaseLoaded = function() {
        _Scene_Boot_prototype_onDatabaseLoaded.apply(this, arguments);
        // preload
        param.images.forEach(image => {
            ImageManager.loadSystem(image);
        });
    }

    //========================================================================
    // 定数定義 (StaffRollState)
    //========================================================================
    const StaffRollState = {
       NONE: 'none',
       READY: 'ready',
       RUNNING: 'running',
       ENDING: 'ending',
       END: 'end',
    };

    const ENDING_WAIT = 60;
    const MOVE_IN_SKIP = 200;
    const MOVE_NORMAL = 4;

    //========================================================================
    // クラス定義 (Scene_StaffRoll)
    //========================================================================
    class Scene_StaffRoll extends Scene_Base {
        constructor() {
            super();

            this.sprite = null;
            this.duration = 60 * 2; // 2 minutes
            this.currentY = 0;
            this.movePerFrame = 1;
            this._state = StaffRollState.NONE;
            this.endingCount = 0;
            this.imageHeight = Graphics.height;
        }

        create() {
            super.create();

            this.sprite = new Sprite_Scrollable(Graphics.width, Graphics.height);
            let height = 0;
            param.images.forEach(image => {
                const sprite = new Sprite(ImageManager.loadSystem(image));
                sprite.move((Graphics.width - sprite.width) / 2, height);
                this.sprite.addChild(sprite);
                height += sprite.height;
            });
            this.imageHeight = height;
            this.sprite.enableInput(false);
            this.sprite.enableScrollX(false);
            this.sprite.move(0, 0);

            this.addChild(this.sprite);
            this.movePerFrame = this._calcMoveHeight()
        }

        start() {
            super.start();

            if (!!param.bgm && param.bgm !== '') {
                const bgm = {
                    name: param.bgm,
                    volume: 100,
                    pitch: 100,
                    pan: 0,
                    pos: 0,
                };

                if (param.scrollWithMusic) {
                    AudioManager.stopBgm();
                    AudioManager._bgmBuffer = AudioManager.createBuffer("bgm/", bgm.name);
                    AudioManager.updateBgmParameters(bgm);

                    const webAudio = AudioManager._bgmBuffer;

                    const scene = this;
                    const onBgmLoaded = () => {
                        scene.duration = webAudio._totalTime;
                        scene.movePerFrame = scene._calcMoveHeight()
                        if (!AudioManager._meBuffer) {
                            AudioManager._bgmBuffer.play(false, 0);
                        }
                        AudioManager.updateCurrentBgm(bgm, 0);
                        scene.setState(StaffRollState.RUNNING);
                    };

                    if (webAudio.isReady()) {
                        onBgmLoaded.bind(this)();
                    } else {
                        webAudio.addLoadListener(onBgmLoaded.bind(this));
                    }
                } else {
                    AudioManager.playBgm(bgm, 0);
                    this.setState(StaffRollState.RUNNING);
                }
            } else {
                this.setState(StaffRollState.RUNNING);
            }
        }

        update() {
            super.update();

            if (!!this.sprite) {
                this.sprite.update();
            }

            switch (this._state) {
                case StaffRollState.RUNNING: {
                    if (Input.isPressed(InputClass.INPUT_CLASS_CTRL)) {
                        this.currentY += MOVE_IN_SKIP;
                    } else {
                        this.currentY += this.movePerFrame;
                    }

                    const yEnd = Math.max(this.imageHeight - Graphics.height, 0);
                    if (this.currentY > yEnd) {
                        this.currentY = yEnd;
                    }
                    this.sprite.smoothScrollTo(0, this.currentY, 10);

                    if (this.currentY >= yEnd) {
                        AudioManager.fadeOutBgm(ENDING_WAIT);
                        this.setState(StaffRollState.ENDING);
                    }
                    break;
                }
                case StaffRollState.ENDING: {
                    this.endingCount++;
                    if (this.endingCount > ENDING_WAIT) {
                        this.setState(StaffRollState.END);
                        AudioManager.stopBgm();
                        this.fadeOutAll();
                        this.popScene();
                        PluginUtils.fireCommonEvent(param.event);
                    }
                    break;
                }
                default:
                    /* nothing to do */
                    break;
            } // switch
        }

        stop() {
            super.stop();
        }

        setState(newState) {
            Logger.d(`Scene_StaffRole: setState old = ${this._state}, new = ${newState}`);
            this._state = newState;
        }

        _calcMoveHeight() {
            if (param.scrollWithMusic) {
                const bgmFrame = this.duration * 60;
                return this.imageHeight / bgmFrame;
            } else {
                return MOVE_NORMAL;
            }
        }
    };

    //========================================================================
    // プラグインコマンド
    //========================================================================
    PluginManagerEx.registerCommand(script, 'startStaffRoll', args => {
        SceneManager._scene.fadeOutAll();
        SceneManager.push(Scene_StaffRoll);
    });
})();
