// (C)2017 Triacontane
// http://opensource.org/licenses/mit-license.php
// [Blog]   : https://triacontane.blogspot.jp/
// [Twitter]: https://twitter.com/triacontane/
// [GitHub] : https://github.com/triacontane/
/*:
 * @plugindesc 
 * @author triacontane
 *
 * @param CommonEventInfo
 * @desc 各画面で実行するコモンイベントの情報です。
 * @default
 * @type struct<CommonEventInfo>[]
 *
 * @param MaxMenuPicture
 * @desc メニュー画面で表示するピクチャの最大数です。
 * @default 10
 * @type number
 * @min 1
 * @max 100
 *
 * @param SaveInterpreterIndex
 * @desc イベントの実行位置を記憶して別画面から戻ってきたときに記憶した位置から再開します。
 * @default false
 * @type boolean
 *
 * @param ActivateTimer
 * @desc メニュー画面中でもタイマーを表示し、かつタイマーを進めます。
 * @default false
 * @type boolean
 *
 * @param CommandPrefix
 * @desc プラグインコマンドおよびメモ欄の接頭辞です。コマンドやメモ欄が他プラグインと被る場合に指定してください。
 * @default
 *
 * @help 
 */
/*~struct~CommonEventInfo:
 *
 * @param SceneName
 * @desc コモンイベント実行対象の画面です。独自に追加した画面を対象にする場合はクラス名を直接入力してください。
 * @type select
 * @default
 * @option メインメニュー
 * @value Scene_Menu
 * @option アイテム
 * @value Scene_Item
 * @option スキル
 * @value Scene_Skill
 * @option 装備
 * @value Scene_Equip
 * @option ステータス
 * @value Scene_Status
 * @option オプション
 * @value Scene_Options
 * @option セーブ
 * @value Scene_Save
 * @option ロード
 * @value Scene_Load
 * @option ゲーム終了
 * @value Scene_End
 * @option ショップ
 * @value Scene_Shop
 * @option 名前入力
 * @value Scene_Name
 * @option デバッグ
 * @value Scene_Debug
 * @option サウンドテスト
 * @value Scene_SoundTest
 * @option 用語辞典
 * @value Scene_Glossary
 *
 * @param CommonEventId
 * @desc 画面で並列実行するコモンイベントのIDです。トリガーを並列実行にする必要はなく、スイッチも参照されません。
 * @default 1
 * @type common_event
 *
 */
/*:ja
 * @plugindesc 
 * @author トリアコンタン
 *
 * @param コモンイベント情報
 * @desc 各画面で実行するコモンイベントの情報です。
 * @default
 * @type struct<CommonEventInfo>[]
 *
 * @param ピクチャ表示最大数
 * @desc メニュー画面で表示するピクチャの最大数です。
 * @default 10
 * @type number
 * @min 1
 * @max 100
 *
 * @param 実行位置を記憶
 * @desc イベントの実行位置を記憶して別画面から戻ってきたときに記憶した位置から再開します。
 * @default false
 * @type boolean
 *
 * @param タイマー有効化
 * @desc メニュー画面中でもタイマーを表示し、かつタイマーを進めます。
 * @default false
 * @type boolean
 *
 * @param コマンド接頭辞
 * @desc プラグインコマンドおよびメモ欄の接頭辞です。コマンドやメモ欄が他プラグインと被る場合に指定してください。
 * @default
 *
 * @help 
 */
/*~struct~CommonEventInfo:ja
 *
 * @param SceneName
 * @desc コモンイベント実行対象の画面です。独自に追加した画面を対象にする場合はクラス名を直接入力してください。
 * @type select
 * @default
 * @option メインメニュー
 * @value Scene_Menu
 * @option アイテム
 * @value Scene_Item
 * @option スキル
 * @value Scene_Skill
 * @option 装備
 * @value Scene_Equip
 * @option ステータス
 * @value Scene_Status
 * @option オプション
 * @value Scene_Options
 * @option セーブ
 * @value Scene_Save
 * @option ロード
 * @value Scene_Load
 * @option ゲーム終了
 * @value Scene_End
 * @option ショップ
 * @value Scene_Shop
 * @option 名前入力
 * @value Scene_Name
 * @option デバッグ
 * @value Scene_Debug
 * @option サウンドテスト
 * @value Scene_SoundTest
 * @option 用語辞典
 * @value Scene_Glossary
 * @option 公式ガチャ
 * @value Scene_Gacha
 *
 * @param CommonEventId
 * @desc 画面で並列実行するコモンイベントのIDです。トリガーを並列実行にする必要はなく、スイッチも参照されません。
 * @default 1
 * @type common_event
 *
 */
(function() {
    'use strict';
    var pluginName = 'JsScript37Set';
    var getParamString = function(paramNames) {
        if (!Array.isArray(paramNames)) paramNames = [paramNames];
        for (var i = 0; i < paramNames.length; i++) {
            var name = PluginManager.parameters(pluginName)[paramNames[i]];
            if (name !== undefined) return name;
        }
        return '';
    };
    var getParamNumber = function(paramNames, min, max) {
        var value = getParamString(paramNames);
        if (arguments.length < 2) min = -Infinity;
        if (arguments.length < 3) max = Infinity;
        return (parseInt(value) || 0).clamp(min, max);
    };
    var getParamBoolean = function(paramNames) {
        var value = getParamString(paramNames);
        return value.toUpperCase() === 'TRUE';
    };
    var getParamArrayJson = function(paramNames, defaultValue) {
        var value = getParamString(paramNames) || null;
        try {
            value = JSON.parse(value);
            if (value === null) {
                value = defaultValue;
            } else {
                value = value.map(function(valueData) {
                    return JSON.parse(valueData);
                });
            }
        } catch (e) {
            alert('!!!Plugin param is wrong.!!!\nPlugin:.js\nName:[]\nValue:');
            value = defaultValue;
        }
        return value;
    };
    var convertEscapeCharacters = function(text) {
        if (isNotAString(text)) text = '';
        var windowLayer = SceneManager._scene._windowLayer;
        return windowLayer ? windowLayer.children[0].convertEscapeCharacters(text) : text;
    };
    var isNotAString = function(args) {
        return String(args) !== args;
    };
    var convertAllArguments = function(args) {
        return args.map(function(arg) {
            return convertEscapeCharacters(arg);
        });
    };
    var setPluginCommand = function(commandName, methodName) {
        pluginCommandMap.set(param.commandPrefix + commandName, methodName);
    };
    var getClassName = function(object) {
        return object.constructor.toString().replace(/function\s+(.*)\s*\([\s\S]*/m, '$1');
    };
    var param                  = {};
    param.commonEventInfo      = getParamArrayJson(['CommonEventInfo', 'コモンイベント情報'], []);
    param.commandPrefix        = getParamString(['CommandPrefix', 'コマンド接頭辞']);
    param.maxMenuPicture       = getParamNumber(['MaxMenuPicture', 'ピクチャ表示最大数'], 1);
    param.saveInterpreterIndex = getParamBoolean(['SaveInterpreterIndex', '実行位置を記憶']);
    param.activateTimer        = getParamBoolean(['ActivateTimer', 'タイマー有効化']);
    var pluginCommandMap = new Map();
    setPluginCommand('ウィンドウ操作禁止', 'execDisableWindowControl');
    setPluginCommand('DISABLE_WINDOW_CONTROL', 'execDisableWindowControl');
    setPluginCommand('ウィンドウ操作許可', 'execEnableWindowControl');
    setPluginCommand('ENABLE_WINDOW_CONTROL', 'execEnableWindowControl');
    setPluginCommand('イベントの実行停止', 'execStopEvent');
    setPluginCommand('STOP_EVENT', 'execStopEvent');
    var _Game_Interpreter_pluginCommand      = Game_Interpreter.prototype.pluginCommand;
    Game_Interpreter.prototype.pluginCommand = function(command, args) {
        _Game_Interpreter_pluginCommand.apply(this, arguments);
        var pluginCommandMethod = pluginCommandMap.get(command.toUpperCase());
        if (pluginCommandMethod) {
            this[pluginCommandMethod](convertAllArguments(args));
        }
    };
    Game_Interpreter.prototype.execDisableWindowControl = function() {
        $gameTemp.setDisableWindowControl(true);
    };
    Game_Interpreter.prototype.execEnableWindowControl = function() {
        $gameTemp.setDisableWindowControl(false);
    };
    Game_Interpreter.prototype.isWindowActive = function(windowName) {
        var sceneWindow = this.getSceneWindow(windowName);
        return sceneWindow ? sceneWindow.active : false;
    };
    Game_Interpreter.prototype.getSceneWindow = function(windowName) {
        return SceneManager.getSceneWindow('_' + windowName);
    };
    Game_Interpreter.prototype.getSceneWindowIndex = function() {
        var index = -1;
        SceneManager.getSceneWindowList().some(function(sceneWindow) {
            if (sceneWindow instanceof Window_Selectable && sceneWindow.active) {
                index = sceneWindow.index();
                return true;
            } else {
                return false;
            }
        });
        return index;
    };
    Game_Interpreter.prototype.refreshGlossary = function() {
        var glossaryWindow = this.getSceneWindow('glossaryWindow');
        if (glossaryWindow.visible) {
            var glossaryListWindow = this.getSceneWindow('glossaryListWindow');
            glossaryWindow.refresh(glossaryListWindow.item());
        }
    };
    Game_Interpreter.prototype.execStopEvent = function() {
        this._menuCommonStop = true;
    };
    Game_Interpreter.prototype.isMenuCommonStop = function() {
        return this._menuCommonStop;
    };
    var _Game_Temp_initialize      = Game_Temp.prototype.initialize;
    Game_Temp.prototype.initialize = function() {
        _Game_Temp_initialize.apply(this, arguments);
        this._menuCommonEvent = {};
        this.clearSceneInformation();
    };
    Game_Temp.prototype.setupMenuCommonEvent = function(commonEventId, sceneName, sceneIndex) {
        this._sceneName  = sceneName;
        this._sceneIndex = sceneIndex;
        if (param.saveInterpreterIndex && this.isExistSameCommonEvent(commonEventId)) {
            return this._menuCommonEvent[sceneName];
        }
        return this._menuCommonEvent[sceneName] = this.createMenuCommonEvent(commonEventId);
    };
    Game_Temp.prototype.createMenuCommonEvent = function(commonEventId) {
        if (commonEventId > 0) {
            var commonEvent = new Game_MenuCommonEvent(commonEventId);
            if (commonEvent.event()) {
                return commonEvent;
            }
        }
        return null;
    };
    Game_Temp.prototype.isExistSameCommonEvent = function(commonEventId) {
        var commonEvent = this._menuCommonEvent[this._sceneName];
        return commonEvent && commonEvent.isSameEvent(commonEventId);
    };
    Game_Temp.prototype.setDisableWindowControl = function(value) {
        this._disableWindowControl = value;
    };
    Game_Temp.prototype.isDisableWindowControl = function() {
        return !!this._disableWindowControl;
    };
    Game_Temp.prototype.getSceneIndex = function() {
        return this._sceneIndex;
    };
    Game_Temp.prototype.isInMenu = function() {
        return this.getSceneIndex() >= 0;
    };
    Game_Temp.prototype.clearSceneInformation = function() {
        this._sceneIndex = -1;
        this._sceneName  = '';
    };
    if (param.maxMenuPicture > 0) {
        var _Game_Screen_realPictureId      = Game_Screen.prototype.realPictureId;
        Game_Screen.prototype.realPictureId = function(pictureId) {
            var sceneIndex = $gameTemp.getSceneIndex();
            if (sceneIndex >= 0) {
                return pictureId + this.maxMapPictures() * 2 + sceneIndex * this.maxPictures();
            } else {
                return _Game_Screen_realPictureId.apply(this, arguments);
            }
        };
        var _Game_Screen_maxPictures      = Game_Screen.prototype.maxPictures;
        Game_Screen.prototype.maxPictures = function() {
            return $gameTemp.isInMenu() ? param.maxMenuPicture : _Game_Screen_maxPictures.apply(this, arguments);
        };
        Game_Screen.prototype.maxMapPictures = function() {
            return _Game_Screen_maxPictures.apply(this, arguments);
        };
    }
    function Game_MenuCommonEvent() {
        this.initialize.apply(this, arguments);
    }
    Game_MenuCommonEvent.prototype             = Object.create(Game_CommonEvent.prototype);
    Game_MenuCommonEvent.prototype.constructor = Game_MenuCommonEvent;
    Game_MenuCommonEvent.prototype.isActive = function() {
        return true;
    };
    Game_MenuCommonEvent.prototype.isSameEvent = function(commonEventId) {
        return this._commonEventId === commonEventId;
    };
    var _Game_MenuCommonEvent_update      = Game_MenuCommonEvent.prototype.update;
    Game_MenuCommonEvent.prototype.update = function() {
        if (this._interpreter) {
            if (!this._interpreter.isRunning()) {
                this._interpreter.execEnableWindowControl();
            }
            if (this._interpreter.isMenuCommonStop()) {
                return;
            }
        }
        _Game_MenuCommonEvent_update.apply(this, arguments);
    };
    var _Scene_MenuBase_create      = Scene_MenuBase.prototype.create;
    Scene_MenuBase.prototype.create = function() {
        _Scene_MenuBase_create.apply(this, arguments);
        this.createCommonEvent();
    };
    Scene_MenuBase.prototype.createCommonEvent = function() {
        this.setupCommonEvent();
        if (!this.hasCommonEvent()) {
            return;
        }
        this.createSpriteset();
        if (!this._messageWindow) {
            this.createMessageWindow();
        }
        if (!this._scrollTextWindow) {
            this.createScrollTextWindow();
        }
        this.changeParentMessageWindow();
    };
    var _Scene_MenuBase_start = Scene_MenuBase.prototype.start;
    Scene_MenuBase.prototype.start = function() {
        _Scene_MenuBase_start.apply(this, arguments);
        if (this.hasCommonEvent()) {
            this.addChild(this._messageWindow);
            this.addChild(this._scrollTextWindow);
            this._messageWindow.subWindows().forEach(function(win) {
                this.addChild(win);
            }, this);
        }
    };
    Scene_MenuBase.prototype.hasCommonEvent = function() {
        return !!this._commonEvent;
    };
    Scene_MenuBase.prototype.createMessageWindow = function() {
        Scene_Map.prototype.createMessageWindow.call(this);
    };
    Scene_MenuBase.prototype.createScrollTextWindow = function() {
        Scene_Map.prototype.createScrollTextWindow.call(this);
    };
    Scene_MenuBase.prototype.changeParentMessageWindow = function() {
        this.addChild(this._windowLayer.removeChild(this._messageWindow));
        this.addChild(this._windowLayer.removeChild(this._scrollTextWindow));
        this._messageWindow.subWindows().forEach(function(win) {
            this.addChild(this._windowLayer.removeChild(win));
        }, this);
    };
    Scene_MenuBase.prototype.changeImplementationWindowMessage  = Scene_Map.prototype.changeImplementationWindowMessage;
    Scene_MenuBase.prototype.restoreImplementationWindowMessage = Scene_Map.prototype.restoreImplementationWindowMessage;
    Scene_MenuBase.prototype.onPause                            = Scene_Map.prototype.onPause;
    Scene_MenuBase.prototype.offPause                           = Scene_Map.prototype.offPause;
    Scene_MenuBase._stopWindow = false;
    Scene_MenuBase.prototype.createSpriteset = function() {
        this._spriteset = new Spriteset_Menu();
        this.addChild(this._spriteset);
    };
    Scene_MenuBase.prototype.setupCommonEvent = function() {
        var commonEventItem = this.getCommonEventData();
        var commonEventId   = commonEventItem ? parseInt(commonEventItem['CommonEventId']) : 0;
        var sceneIndex      = param.commonEventInfo.indexOf(commonEventItem);
        this._commonEvent   = $gameTemp.setupMenuCommonEvent(commonEventId, this._sceneName, sceneIndex);
    };
    Scene_MenuBase.prototype.getCommonEventData = function() {
        this._sceneName = getClassName(this);
        return param.commonEventInfo.filter(function(data) {
            return data['SceneName'] === this._sceneName;
        }, this)[0];
    };
    var _Scene_MenuBase_updateChildren      = Scene_MenuBase.prototype.updateChildren;
    Scene_MenuBase.prototype.updateChildren = function() {
        Scene_MenuBase._stopWindow = this.hasCommonEvent() && this.isNeedStopWindow();
        _Scene_MenuBase_updateChildren.apply(this, arguments);
    };
    Scene_MenuBase.prototype.isNeedStopWindow = function() {
        return $gameTemp.isDisableWindowControl() || $gameMessage.isBusy();
    };
    Scene_MenuBase.prototype.updateCommonEvent = function() {
        if (!this.hasCommonEvent()) {
            return;
        }
        this._commonEvent.update();
        $gameScreen.update();
        if (param.activateTimer) {
            $gameTimer.update(true);
        }
        this.checkGameover();
        this.updateTouchPicturesIfNeed();
    };
    /**
     * updateTouchPicturesIfNeed
     * for PictureCallCommon.js
     */
    Scene_MenuBase.prototype.updateTouchPicturesIfNeed = function() {
        if (this.updateTouchPictures && param.maxMenuPicture > 0) {
            this.updateTouchPictures();
        }
    };
    var _Scene_Base_update      = Scene_Base.prototype.update;
    Scene_Base.prototype.update = function() {
        this.updateCommonEvent();
        _Scene_Base_update.apply(this, arguments);
    };
    Scene_Base.prototype.updateCommonEvent = function() {
    };
    var _Scene_Base_terminate      = Scene_Base.prototype.terminate;
    Scene_Base.prototype.terminate = function() {
        _Scene_Base_terminate.apply(this, arguments);
        if ($gameTemp) {
            $gameTemp.clearSceneInformation();
        }
    };
    function Spriteset_Menu() {
        this.initialize.apply(this, arguments);
    }
    Spriteset_Menu.prototype             = Object.create(Spriteset_Base.prototype);
    Spriteset_Menu.prototype.constructor = Spriteset_Menu;
    var _Spriteset_Menu_createBaseSprite      = Spriteset_Menu.prototype.createBaseSprite;
    Spriteset_Menu.prototype.createBaseSprite = function() {
        _Spriteset_Menu_createBaseSprite.apply(this, arguments);
        this._blackScreen.opacity = 0;
    };
    var _Spriteset_Menu_createTimer      = Spriteset_Menu.prototype.createTimer;
    Spriteset_Menu.prototype.createTimer = function() {
        if (param.activateTimer) {
            _Spriteset_Menu_createTimer.apply(this, arguments);
        }
    };
    SceneManager.getSceneWindow = function(windowName) {
        var sceneWindow = this._scene[windowName];
        return sceneWindow instanceof Window ? sceneWindow : null;
    };
    SceneManager.getSceneWindowList = function() {
        var windowList = [];
        for (var sceneWindow in this._scene) {
            if (this._scene.hasOwnProperty(sceneWindow) && this._scene[sceneWindow] instanceof Window) {
                windowList.push(this._scene[sceneWindow]);
            }
        }
        return windowList;
    };
    var _Window_Selectable_update = Window_Selectable.prototype.update;
    Window_Selectable.prototype.update = function() {
        if (Scene_MenuBase._stopWindow && this.isStopWindow()) {
            return;
        }
        _Window_Selectable_update.apply(this, arguments);
    };
    Window_Selectable.prototype.isStopWindow = function() {
        return !this._messageWindow;
    };
})();
