//=============================================================================
// Keke_ChangeLayoutLight - お手軽レイアウト変更
// バージョン: 1.8.3
//=============================================================================
// Copyright (c) 2020 ケケー
// Released under the MIT license
// http://opensource.org/licenses/mit-license.php
//=============================================================================

/*:
 * @target MZ
 * @plugindesc 各種レイアウトを手軽に変更する
 * @author ケケー
 * @url https://kekeelabo.com
 *
 * @help
 * 【ver.1.8.3】
 * 各種レイアウト(コマンドやタッチUIの位置)を手軽に変更する
 * オプションでプレイヤーにレイアウトを変更させることも可能
 * 
 * 
 * ● 使い方 ●
 *
 * ■レイアウトを変更する
 * => プラグインパラメータ → レイアウト変更
 *
 * ◎メニューコマンド位置
 * メニューコマンド(アイテムとか)を左に置くか右に置くか
 *
 * ◎バトルコマンド位置
 * バトルコマンド(攻撃とか)を左に置くか右に置くか
 *
 * ◎メニューヘルプ位置
 * メニューヘルプ(アイテムとかの説明)を上に置くか下に置くか
 *
 * ◎タッチUI位置
 * タッチUI(戻るボタンとか)を上に置くか下に置くか
 *
 *
 * ■連動設定
 * => プラグインパラメータ → 連動設定
 * レイアウト変更の際の連動関係を調整する
 *
 * ◎装備コマンド連動
 * メニューコマンド位置を左にした時、装備コマンドの位置も左にする(標準は右固定)
 *
 * ◎プロフィール連動
 * メニューヘルプ位置を上にしたとき、
 * ステータス画面のプロフィール欄の位置も上にする(標準は下固定)
 *
 *
 * ■オプションでのレイアウト変更
 * => プラグインパラメータ → オプション
 * オプションからもレイアウトを変更できるようにする
 *
 * ◎項目の表示順を変えたい場合
 * オプションリストの順番を変える
 *
 * ◎項目を消したい場合
 * オプションリストから消す
 *
 * ◎項目名を変えたい場合
 * オプションリストの名前を変える
 * ただし頭の a- や b- の部分は変えないこと
 *
 * 
 * ● 利用規約 ●
 * MITライセンスのもと、自由に使ってくれて大丈夫です
 *
 *
 *
 * Easily change various layouts (position of commands and touch UI)
 * Option to let the player change the layout
 *
 * ● How to use ●
 *
 * ■ Change the layout
 * => plug-in parameter → layout change
 *
 * ● Menu command position
 * Place menu commands (items, etc.) left or right
 *
 * ● Battle command position
 * Whether to put the battle command (such as attack) on the left or right
 *
 * ● Menu help position
 * Whether to put the menu help (description of items etc.) above or below
 *
 * ● Touch UI position
 * Whether to put the touch UI (such as the back button)
 *   on top or on the bottom
 *
 *
 * ■ Interlocking settings
 * => plug-in parameter → interlock setting
 * Adjust dependencies when changing layouts
 *
 * ● Equip command linkage
 * When the menu command position is set to the left,
 *   the position of the equipment command is also set to the left
 *   (standard is fixed to the right)
 *
 * ● Profile linked
 * When the menu help position is set to the top,
 * the position of the profile column of the status screen is also set
 * to the top (fixed to the bottom by default).
 *
 *
 * ● Layout change with option
 * => plug-in parameter → option
 * Make it possible to change the layout also from the options
 *
 * ● If you want to change the display order of items
 * change the order of the option list
 *
 * ● If you want to delete item
 * Remove from option list
 *
 * ● If you want to change the item name
 * rename option list
 * But don't change the a- and b- parts of the head
 *
 *
 * ● Terms of Use ●
 * Feel free to use it under the MIT license.
 * 
 * 
 * 
 * @param レイアウト変更
 *
 * @param メニューコマンド位置
 * @parent レイアウト変更
 * @desc menuCommand_pos メニューコマンドの位置。左か右か
 * @type select
 * @option 左
 * @option 右
 * @default 右
 *
 * @param バトルコマンド位置
 * @parent レイアウト変更
 * @desc battleCommand_pos バトルコマンドの位置。左か右か
 * @type select
 * @option 左
 * @option 右
 * @default 右
 *
 * @param メニューヘルプ位置
 * @parent レイアウト変更
 * @desc menuHelp_pop メニューヘルプ(スキルとか説明するの)の位置。上か下か
 * @type select
 * @option 上
 * @option 下
 * @default 下
 *
 * @param タッチUI位置
 * @parent レイアウト変更
 * @desc touchUI_pos タッチUI(戻るとかのボタン)の位置。上か下か
 * @type select
 * @option 上
 * @option 下
 * @default 上
 *
 * @param 連動設定
 *
 * @param 装備コマンド連動
 * @parent 連動設定
 * @desc link_equipCommand 装備画面のコマンドをメニューコマンド位置に連動させる(デフォは右固定)
 * @type boolean
 * @default true
 *
 * @param プロフィール連動
 * @parent 連動設定
 * @desc link_profile ステータス画面のプロフィールウインドウをヘルプ位置に連動させる(デフォは下固定)
 * @type boolean
 * @default true
 *
 * @param オプション
 *
 * @param オプションに追加
 * @parent オプション
 * @desc insertOption レイアウト設定をオプションに追加する
 * @type boolean
 * @default true
 *
 * @param オプションリスト
 * @parent オプション
 * @desc optionList 並び変えると表示順変更。リストから消すと非表示。名前を変えてもいいが、a- の部分は変えないこと
 * @type string[]
 * @default ["a-メニューコマンド位置","b-バトルコマンド位置","c-メニューヘルプ位置","d-タッチUI位置"]
 */
 
 
 
(() => {
    //- プラグイン名
    const pluginName = document.currentScript.src.match(/^.*\/(.*).js$/)[1];
    
    
    
    //==================================================
    //--  パラメータ受け取り
    //==================================================
    
    //- 真偽化
    function toBoolean(str) {
        if (!str) { return false; }
        const str2 = str.toString().toLowerCase();
        if (str2 == "true" || str2 == "on") { return true; }
        if (str2 == "false" || str2 == "off") { return false; }
        return Number(str);
    };

    const parameters = PluginManager.parameters(pluginName);
    
    //- レイアウト設定
    const keke_menuCmdPos = parameters["メニューコマンド位置"];
    const keke_battleCmdPos = parameters["バトルコマンド位置"]; 
    const keke_menuHelpPos = parameters["メニューヘルプ位置"];
    const keke_touchUIPos = parameters["タッチUI位置"];
    
    //- 連動設定
    const keke_equipCmdAdapt = toBoolean(parameters["装備コマンド連動"]);
    const keke_profileAdapt = toBoolean(parameters["プロフィール連動"]);
    
    //- オプション
    const keke_insertOption  = toBoolean(parameters["オプションに追加"]);
    const keke_optionList = JSON.parse(parameters["オプションリスト"]);
     
     
     
    //==================================================
    //--  プラグインデータ
    //==================================================
    
    //- ゲームシステム/初期化(処理追加)
    const _Game_System_initialize = Game_System.prototype.initialize;
    Game_System.prototype.initialize = function() {
        _Game_System_initialize.apply(this);
        // メニューコマンド位置
        this._menuCmdPosKe = keke_menuCmdPos;
        // バトルコマンド位置
        this._battleCmdPosKe = keke_battleCmdPos;
        // メニューヘルプ位置
        this._menuHelpPosKe = keke_menuHelpPos;
        // タッチUI位置
        this._touchUIPosKe = keke_touchUIPos;
    };
    
    
    
    //==================================================
    //--  レイアウト設定
    //==================================================
    
    //- シーン・メニューベース/右コマンドモードか(処理追加)
    const _Scene_MenuBase_isRightInputMode = Scene_MenuBase.prototype.isRightInputMode;
    Scene_MenuBase.prototype.isRightInputMode = function() {
        let result = _Scene_MenuBase_isRightInputMode.apply(this);
        // 本プラグインの変数を適用
        switch ($gameSystem._menuCmdPosKe) {
            case "左":
                result = false;
                break;
            case "右":
                result = true;
        }
        return result;
    };
    
    
    //- シーンバトル/右コマンドモードか(処理追加)
    const _Scene_Battle_isRightInputMode = Scene_Battle.prototype.isRightInputMode;
    Scene_Battle.prototype.isRightInputMode = function() {
        let result = _Scene_Battle_isRightInputMode.apply(this);
        // 本プラグインの変数を適用
        switch ($gameSystem._battleCmdPosKe) {
            case "左":
                result = false;
                break;
            case "右":
                result = true;
        }
        return result;
    };
    
    
    //- シーンベース/下ヘルプモードか(処理追加)
    const _Scene_Base_isBottomHelpMode = Scene_Base.prototype.isBottomHelpMode;
    Scene_Base.prototype.isBottomHelpMode = function() {
        let result = _Scene_Base_isBottomHelpMode.apply(this);
        // 本プラグインの変数を適用
        switch ($gameSystem._menuHelpPosKe) {
            case "上":
                result = false;
                break;
            case "下":
                result = true;
        }
        return result;
    };
    
    
    //- シーンベース/下UIボタンモードか(処理追加)
    const _Scene_Base_isBottomButtonMode = Scene_Base.prototype.isBottomButtonMode;
    Scene_Base.prototype.isBottomButtonMode = function() {
        let result = _Scene_Base_isBottomButtonMode.apply(this);
        // 本プラグインの変数を適用
        switch ($gameSystem._touchUIPosKe) {
            case "上":
                result = false;
                break;
            case "下":
                result = true;
        }
        return result;
    };
    
    
    
    //==================================================
    //--  連動設定
    //==================================================
    
    //- シーンエクイップ/項目ウインドウの形成(処理追加)
    const _Scene_Equip_createItemWindow = Scene_Equip.prototype.createItemWindow;
    Scene_Equip.prototype.createItemWindow = function() {
         _Scene_Equip_createItemWindow.apply(this);
         // 装備コマンドをメニューコマンド位置に連動させる
         if (keke_equipCmdAdapt && !this.isRightInputMode()) {
             if (this._commandWindow) {this._commandWindow.x -= this._statusWindow.width; }
             this._slotWindow.x -= this._statusWindow.width;
             this._itemWindow.x -= this._statusWindow.width;
             this._statusWindow.x += this._slotWindow.width;
          }
    };
    
    
    //- シーンステータス/ステータス装備ウインドウの形成(処理追加)
    const _Scene_Status_createStatusEquipWindow = Scene_Status.prototype.createStatusEquipWindow;
    Scene_Status.prototype.createStatusEquipWindow = function() {
        _Scene_Status_createStatusEquipWindow.apply(this);
        // プロフィールをメニュヘルプ位置に連動させる
        if (keke_profileAdapt && !this.isBottomHelpMode()) {
            this._profileWindow.y = this.isBottomButtonMode() ? 0 : this.buttonAreaHeight();
            this._statusWindow.y += this._profileWindow.height;
            this._statusParamsWindow.y += this._profileWindow.height;
            this._statusEquipWindow.y += this._profileWindow.height;
        }
    };
    
    
    
    //==================================================
    //--  オプション追加
    //==================================================

    //- コンフィグマネージャー/メニューコマンド位置
    Object.defineProperty(ConfigManager, "menuCmdPos", {
        get: function() {
            return $gameSystem._menuCmdPosKe;
        },
        set: function(value) {
            $gameSystem._menuCmdPosKe = value;
        },
        configurable: true
    });
    
    //-  コンフィグマネージャー/バトルコマンド位置
    Object.defineProperty(ConfigManager, "battleCmdPos", {
        get: function() {
            return $gameSystem._battleCmdPosKe;
        },
        set: function(value) {
            $gameSystem._battleCmdPosKe = value;
        },
        configurable: true
    });
    
    //-  コンフィグマネージャー/メニューヘルプ位置
    Object.defineProperty(ConfigManager, "menuHelpPos", {
        get: function() {
            return $gameSystem._menuHelpPosKe;
        },
        set: function(value) {
            $gameSystem._menuHelpPosKe = value;
        },
        configurable: true
    });
    
    //-  コンフィグマネージャー/タッチUI位置
    Object.defineProperty(ConfigManager, "touchUIPos", {
        get: function() {
            return $gameSystem._touchUIPosKe;
        },
        set: function(value) {
            $gameSystem._touchUIPosKe = value;
        },
        configurable: true
    });
    
    
    //- ウインドウオプション/コマンドリストの作成(処理追加)
    const _Window_Options_makeCommandList = Window_Options.prototype.makeCommandList;
    Window_Options.prototype.makeCommandList = function() {
        _Window_Options_makeCommandList.apply(this);
        // メニューレイアウトオプションの追加
        addMenuLayoutOptions(this);
    };


    //- メニューレイアウトオブションの追加
    function addMenuLayoutOptions(windo) {
        if (!keke_insertOption) { return; }
        let added = false;
        // 全ての追加項目を処理
        for (let item of keke_optionList) {
            // 項目名設定
            if (item.startsWith("a-")) {
                item = item.replace(/^\w+-/, "");
                windo.addCommand(item, "menuCmdPos");
            }
            if (item.startsWith("b-")) {
                item = item.replace(/^\w+-/, "");
                windo.addCommand(item, "battleCmdPos");
            }
            if (item.startsWith("c-")) {
                item = item.replace(/^\w+-/, "");
                windo.addCommand(item, "menuHelpPos");
            }
            if (item.startsWith("d-")) {
                item = item.replace(/^\w+-/, "");
                windo.addCommand(item, "touchUIPos");
            }
            added = true;
        }
        // 追加したら文字列を追加
        if (added) {
            windo._posLRStrsKe = ["左", "右"];
            windo._posUDStrsKe = ["上", "下"];
        }
        // オプションのリサイズ
        resizeOption(windo);
    };
    
    //- オプションのリサイズ
    function resizeOption(windo){
        // コマンド数取得
        let cmdNum = windo._list.length;
        // 高さ変更(画面高さは超えないように)
        let height = Math.min(Graphics.boxHeight, windo.fittingHeight(cmdNum));
        windo.height = height;
        // Y位置変更
        windo.y = (Graphics.boxHeight - windo.height) / 2;
    };
    
    
    //- ウインドウオプション/オプションウインドウの矩形(処理追加)
    const _Scene_Options_optionsWindowRect = Scene_Options.prototype.optionsWindowRect;
    Scene_Options.prototype.optionsWindowRect = function() {
        let result = _Scene_Options_optionsWindowRect.apply(this);
        // 高さを拡大
        if (keke_insertOption) { result.height = Graphics.height; }
        return result;
    };
    
    
    //- ウインドウオプション/ステータステキスト(処理追加)
    const _Window_Options_statusText = Window_Options.prototype.statusText;
    Window_Options.prototype.statusText = function(index) {
        let result = _Window_Options_statusText.apply(this, arguments);
        // シンボルと値を取得
        const symbol = this.commandSymbol(index);
        const value = this.getConfigValue(symbol);
        // 位置設定のときは独自のテキストに
        if (symbol == "menuCmdPos" || symbol == "battleCmdPos" || symbol == "menuHelpPos" || symbol == "touchUIPos") {
            return value;
        }
        return result;
    };
    
    
    //- ウインドウオプション/決定時の処理(処理追加)
    const _Window_Options_processOk = Window_Options.prototype.processOk;
    Window_Options.prototype.processOk = function() {
        const symbol = this.commandSymbol(this.index());
        // コマンド位置のとき
        if (symbol == "menuCmdPos" || symbol == "battleCmdPos") {
            changeOptionString(this, symbol, this._posLRStrsKe, true, true);
        // UI位置のとき
        } else if (symbol == "menuHelpPos" || symbol == "touchUIPos") {
            changeOptionString(this, symbol, this._posUDStrsKe, true, true);
        // それ以外のとき
        } else {
            _Window_Options_processOk.apply(this);
        }
    };
    
    //- ウインドウオプション/右カーソルの処理(処理追加)
    const _Window_Options_cursorRight = Window_Options.prototype.cursorRight;
    Window_Options.prototype.cursorRight = function() {
        const symbol = this.commandSymbol(this.index());
        // コマンド位置のとき
        if (symbol == "menuCmdPos" || symbol == "battleCmdPos") {
            changeOptionString(this, symbol, this._posLRStrsKe, true, true);
        // UI位置のとき
        } else if (symbol == "menuHelpPos" || symbol == "touchUIPos") {
            changeOptionString(this, symbol, this._posUDStrsKe, true, true);
        // それ以外のとき
        } else {
            _Window_Options_cursorRight.apply(this);
        }
    };
    
    //- ウインドウオプション/左カーソルの処理(処理追加)
    const _Window_Options_cursorLeft = Window_Options.prototype.cursorLeft;
    Window_Options.prototype.cursorLeft = function() {
        const symbol = this.commandSymbol(this.index());
        // コマンド位置のとき
        if (symbol == "menuCmdPos" || symbol == "battleCmdPos") {
            changeOptionString(this, symbol, this._posLRStrsKe, false, true);
        // UI位置のとき
        } else if (symbol == "menuHelpPos" || symbol == "touchUIPos") {
            changeOptionString(this, symbol, this._posUDStrsKe, true, true);
        // それ以外のとき
        } else {
            _Window_Options_cursorLeft.apply(this);
        }
    };
    
    //- オプション文字列の変更
    function changeOptionString(windo, symbol, strs, forward, wrap) {
        // ストルスがなかったらリターン
        if (!strs) { return; }
        // テキスト取得
        const text = windo.getConfigValue(symbol);
        // インデックス取得
        let index = strs.indexOf(text);
        // インデックス最大数取得
        const iMax = strs.length - 1;
        // インデックスがなかったら 0 に
        if (index < 0) { index = 0; }
        // インデックスを変更
        index = index+ (forward ? 1 : -1);
        // ループさせる
        if (wrap) {
            if (index > iMax) { index = 0; }
            if (index < 0) { index = iMax; }
        }
        // 範囲内に収める
        index = index.clamp(0, iMax);
        // 新しい値を取得
        const value = strs[index];
        // セット
        windo.setConfigValue(symbol, value);
        windo.redrawItem(windo.findSymbol(symbol));
        windo.playCursorSound();
    };

    
    //- コンフィグマネージャー/データの作成(処理追加)
    const _ConfigManager_makeData = ConfigManager.makeData;
    ConfigManager.makeData = function() {
        let config = _ConfigManager_makeData.apply(this);
        if (keke_insertOption) {
            // ゲーム開始時用
            config._menuCmdPosKe = $gameSystem._menuCmdPosKe;
            config._battleCmdPosKe = $gameSystem._battleCmdPosKe;
            config._menuHelpPosKe = $gameSystem._menuHelpPosKe;
            config._touchUIPosKe = $gameSystem._touchUIPosKe;
            // ニューゲーム用
            this._menuCmdPosKe = $gameSystem._menuCmdPosKe;
            this._battleCmdPosKe = $gameSystem._battleCmdPosKe;
            this._menuHelpPosKe = $gameSystem._menuHelpPosKe;
            this._touchUIPosKe = $gameSystem._touchUIPosKe;
        }
        return config;
    };
    
    //- コンフィグマネージャー/データの適用(処理追加)
    const _ConfigManager_applyData = ConfigManager.applyData;
    ConfigManager.applyData = function(config) {
        _ConfigManager_applyData.apply(this, arguments);
        if (keke_insertOption) {
            // オプションのデータをゲーム開始時に呼び出す
            const items = keke_optionList;
            if (items.filter(item => item.startsWith("a-")).length) {
                this._menuCmdPosKe = config._menuCmdPosKe;
            }
            if (items.filter(item => item.startsWith("b-")).length) {
                this._battleCmdPosKe = config._battleCmdPosKe;
            }
            if (items.filter(item => item.startsWith("c-")).length) {
                this._menuHelpPosKe = config._menuHelpPosKe;
            }
            if (items.filter(item => item.startsWith("d-")).length) {
                this._touchUIPosKe = config._touchUIPosKe;
            }
        }
    };
    
    //- データマネージャー/ニューゲームのセットアップ(処理追加)
    const _DataManager_setupNewGame = DataManager.setupNewGame;
    DataManager.setupNewGame = function() {
        _DataManager_setupNewGame.apply(this);
        if (keke_insertOption) {
            // オプションのデータをニューゲーム時に呼び出す
            cm = ConfigManager;
            if (cm._menuCmdPosKe) {
                $gameSystem._menuCmdPosKe = cm._menuCmdPosKe;
            }
            if (cm._battleCmdPosKe) {
                $gameSystem._battleCmdPosKe = cm._battleCmdPosKe;
            }
            if (cm._menuHelpPosKe) {
                $gameSystem._menuHelpPosKe = cm._menuHelpPosKe;
            }
            if (cm._touchUIPosKe) {
                $gameSystem._touchUIPosKe = cm._touchUIPosKe;
            }
        }
    };
    
})();