// Copyright 2023 TigRig All rights reserved.

// special_sf とは
// - システム変数 sf のうち、 C01 - C20 ( 登場人物名 ) と T001 - T099 ( 解読情報 ) などを指す
//   - 具体的にどの変数が対象とするかは、本プラグインの init.ks にて定義する
// - 本来 sf は全セーブデータ間で共通するものだが、special_sf は全セーブデータ間で共通化せず、
//   - セーブスロット１～６内で共通 ← special_sf スロット１
//   - セーブスロット７～１２内で共通 ← special_sf スロット２
//   - セーブスロット１３～１８内で共通 ← special_sf スロット３
// - と、３つの領域に分けて管理する

// どのように管理するか
// - ゲームのメイン処では sf.C01 や sf.T001 といった sf 直下の変数を使用
// - select_savelot.ks またはロード処理によって、使用する special_sf スロットが切り替わる時に
//   - sf.C01 や sf.T001 といった sf 直下の変数を sf.special_sf[0~2] の中にセーブする
//   - sf.special_sf[0~2] の中から sf.C01 や sf.T001 といった変数を sf 直下にロードする
// - ※なぜ sf.special_sf の中の値を直接ゲームのメイン処理に使用しないか
//   - sf.special_sf は後から追加した空間であり、既存機能は基本的に sf.C01 や sf.T001 といった sf 直下の変数を使用していた
//   - → 既存機能に影響を与えないために、 sf 直下の変数はそのまま残して利用し、sf.special_sf は保管専用空間とした

(function () {
    const sf = TYRANO.kag.variable.sf;
    const tmp = TYRANO.kag.tmp;

    // ==================================================
    // 関数郡
    // ==================================================

    /**
     * セーブスロット番号から対象の special_sf スロット番号を取得する
     * @param {Number} save_slot セーブスロット番号
     * @returns special_sf スロット番号
     */
    const getSpecialSfSlotNumFromSaveSlotNum = function (save_slot) {
        // - 0-5 なら `0`
        // - 6-11 なら `1`
        // - 12-17 なら `2`
        return Math.floor(save_slot / 8);
    };

    /**
     * special_sf スロットに属する対象のセーブスロット番号一覧を取得する
     * @param {Number} special_sf_slot special_sf スロット番号
     * @returns セーブスロット番号（配列）
     */
    const getSaveSlotNumsFromSpecialSfSlotNum = function (special_sf_slot) {
        // - `0` なら 0-5
        // - `1` なら 6-11
        // - `2` なら 12-17
        const save_slot_nums = [];
        for (let i = 0; i < 8; i++) {
            save_slot_nums.push(special_sf_slot * 8 + i);
        }
        return save_slot_nums;
    };

    /**
     * special_sf_default (initializeSpecialSfData で利用する special_sf の初期値) を現在の sf から設定する
     * ※ lang が変わると special_sf_default も変える必要がある
     */
    const setSpecialSfDefaultFromSf = function () {
        // sf を special_sf_default にセット
        sf.special_sf_default = {};
        for (const sf_prop of tmp.special_sf_properties) {
            if (sf[sf_prop] == undefined) {
                TYRANO.kag.error(`プラグイン special_sf でエラー: sf.${sf_prop} が定義されていません`);
                continue;
            }
            sf.special_sf_default[sf_prop] = sf[sf_prop];
        }
    };

    /**
     * special_sf を初期化する
     * @param {Number} special_sf_slot 初期化する special_sf スロット番号
     */
    const initializeSpecialSfData = function (special_sf_slot) {
        const special_sf_data = sf.special_sf[special_sf_slot];
        for (const sf_prop of tmp.special_sf_properties) {
            // 初期処理で作成したデフォルトの sf をセット
            special_sf_data[sf_prop] = sf.special_sf_default[sf_prop];
        }
    };

    /**
     * special_sf をセーブする
     * @param {Number} save_special_sf_slot セーブ先 special_sf スロット番号
     */
    const saveSpecialSfData = function (save_special_sf_slot) {
        const save_special_sf_data = sf.special_sf[save_special_sf_slot];
        for (const sf_prop of tmp.special_sf_properties) {
            if (sf[sf_prop] == undefined) {
                TYRANO.kag.warning(`プラグイン special_sf でエラー: sf.${sf_prop} が定義されていません`);
                continue;
            }
            save_special_sf_data[sf_prop] = sf[sf_prop];
        }
    };

    /**
     * special_sf をロードする
     * @param {Number} load_special_sf_slot ロードする special_sf スロット番号
     */
    const loadSpecialSfData = function (load_special_sf_slot) {
        const load_special_sf_data = sf.special_sf[load_special_sf_slot];
        for (const sf_prop of tmp.special_sf_properties) {
            if (load_special_sf_data[sf_prop] == undefined) continue;
            sf[sf_prop] = load_special_sf_data[sf_prop];
        }
    };

    // select_saveslot.ks でも special_sf に関する処理を行うため、一部の関数を公開しておく
    tmp.special_sf_functions = {};
    tmp.special_sf_functions.getSaveSlotNumsFromSpecialSfSlotNum = getSaveSlotNumsFromSpecialSfSlotNum;
    tmp.special_sf_functions.setSpecialSfDefaultFromSf = setSpecialSfDefaultFromSf;
    tmp.special_sf_functions.initializeSpecialSfData = initializeSpecialSfData;
    tmp.special_sf_functions.saveSpecialSfData = saveSpecialSfData;
    tmp.special_sf_functions.loadSpecialSfData = loadSpecialSfData;

    // ==================================================
    // 初期処理
    // ==================================================

    if (sf.already_special_sf_initialized != true) {
        // special_sf を初期化する
        // ※initializeSpecialSfData() は実行不要
        //   ( 初期状態からは必ず select_saveslot.ks が実行される仕様であり、
        //     その際に必ず initializeSpecialSfData() が実行されるため )
        sf.special_sf = [{}, {}, {}];

        // 初期化済みフラグを立てる
        sf.already_special_sf_initialized = true;
    }

    // ==================================================
    // ロードスロットのクリックイベント実装
    // ==================================================

    // ※ロード画面は動的に生成されるため、画面生成後にクリックイベントをセットする必要がある
    TYRANO.kag.menu.oldDisplayLoad = TYRANO.kag.menu.displayLoad;
    TYRANO.kag.menu.displayLoad = function () {
        // ロード画面生成処理
        TYRANO.kag.menu.oldDisplayLoad();

        // 生成完了後に処理をしたいため、 50ms 遅延実行する
        setTimeout(function () {
            // ロードスロットのクリックイベント
            $(".save_list_item").on("click", function () {
                // ロードスロットナンバーに応じて、 ロード対象の special_sf スロットを算出
                const slot = $(this).data("num");
                const load_special_sf_slot = getSpecialSfSlotNumFromSaveSlotNum(slot);

                // 現在の special_sf スロットに、 sf 直下の変数をセーブする
                // ( select_saveslot.ks にて current_special_sf_slot を初期化しているため undefined である可能性は考慮不要）
                saveSpecialSfData(sf.current_special_sf_slot);

                // special_sf をロード
                loadSpecialSfData(load_special_sf_slot);

                // 現在の special_sf スロットを更新
                sf.current_special_sf_slot = load_special_sf_slot;
            });
        }, 50);
    };

    // ==================================================
    // セーブスロットの使用制限
    // - special_sf スロット１使用中 → セーブスロット１～６のみ使用可能
    // - special_sf スロット２使用中 → セーブスロット７～１２のみ使用可能
    // - special_sf スロット３使用中 → セーブスロット１３～１８のみ使用可能
    // ==================================================

    // ※セーブ画面は動的に生成されるため、画面生成後にクリックイベントをセットする必要がある
    TYRANO.kag.menu.oldDisplaySave = TYRANO.kag.menu.displaySave;
    TYRANO.kag.menu.displaySave = function () {
        // セーブ画面生成処理
        TYRANO.kag.menu.oldDisplaySave();

        // 生成完了後に処理をしたいため、 50ms 遅延実行する
        setTimeout(function () {
            // セーブスロット全ループ
            $(".save_list_item").each(function () {
                // セーブスロットナンバーに応じて、 連動する special_sf スロットを算出
                const slot = $(this).data("num");
                const sync_target_special_sf_slot = getSpecialSfSlotNumFromSaveSlotNum(slot);

                // 現在の special_sf スロットと連動するセーブスロット以外は使用不可にする
                if (sf.current_special_sf_slot !== sync_target_special_sf_slot) {
                    $(this).css({
                        opacity: 0.3,
                    });
                    $(this).off("click");
                    $(this).off("mouseenter");
                    $(this).find(".save_list_item_delete").off("click");
                    $(this).find(".save_list_item_delete").off("mouseenter");
                }
            });
        }, 50);
    };
})();

