/*:
 * @target MZ
 * @plugindesc 多言語プラグイン
 * @author くろうど（kuroudo119）
 * @url https://twitter.com/kuroudo119
 * 
 * @param argLanguage
 * @text 言語一覧
 * @desc 切り替え可能な言語の一覧を指定します。
 * @default ["日本語"]
 * @type string[]
 * 
 * @param argOptionText
 * @text オプション表示名
 * @desc オプション画面に表示する項目名を指定します。
 * @default ["言語"]
 * @type string[]
 * 
 * @command setLanguage
 * @text 言語切替コマンド
 * @desc 指定された番号の言語に切り替えます。
 * @arg varLanguage
 * @text 言語番号変数
 * @desc この変数の値の言語番号に変更します。
 * 言語番号の値は 0 始まりです。
 * @default 1
 * @type variable
 * 
 * @command getLanguage
 * @text 現在言語取得コマンド
 * @desc 現在の言語番号を変数に入れます。
 * @arg varLanguage
 * @text 言語番号変数
 * @desc この変数に言語番号を入れます。
 * 言語番号の値は 0 始まりです。
 * @default 1
 * @type variable
 * 
 * @help
 * KRD_MZ_Multilingual.js
 * RPGツクールMZ用の多言語プラグインです。
 * 
 * 【権利表記】
 * (c) 2021 kuroudo119
 * 
 * 【利用規約】
 * 1．jsonファイルを編集可能なこと。
 * 2. 商用、非商用どちらの作品にも利用可能です。
 * 3. 作品のレーティングに関わらず利用可能です。
 * 4. 使用時に権利表記は不要です。連絡も不要です。
 * 5. 有償無償問わず、再配布は禁止です。
 * 6. Web など他者への公開（ソースコードの貼り付け）も禁止です。
 * 7. 権利表記以外の加工は自由に出来ます。
 * 8. 加工後の再配布も禁止です。
 * 9. 他のプラグインと競合する可能性がありますが、保証はありません。
 * 10. その他、本プラグインの利用による保証はありません。
 * 
 * 【更新履歴】
 * ver.0 (2021/01/26) 作成完了（未公開）
 * 
 * 【使い方】
 * プラグインパラメータを設定します。
 * プラグインパラメータの「テキストのリスト」では 1番からですが、
 * 言語番号を使用する時は -1 してください。
 * このプラグイン内部では 0番から始まるためです。
 * （例）
 * 1:日本語 を指定する時は、0を変数に入れてプラグインコマンドを使用します。
 * 
 * 「文章の表示」などのイベントコマンドでは、
 * プラグインコマンド「現在言語取得コマンド」を使用して、
 * 値に応じて「条件分岐」を使い、イベントコマンドを設定してください。
 * 
 * イベントコマンド「名前の変更」「二つ名の変更」「プロフィールの変更」を
 * 実行した場合、このプラグインでの言語の指定よりも、
 * イベントコマンドで変更した内容が優先されます。
 * 
 * アクター、職業、スキル、アイテム、武器、防具、敵キャラについては、
 * メモ欄を使用します。
 * 使用可能なタグは以下です。
 * 「_1」の部分は言語番号の連番です。
 * 0 はデータベース設定内容を使用するため、ありません。
 * 「:」と「>」の間に表示内容を記述してください。
 * 
 * <name_1:名前>
 * <nickname_1:二つ名>
 * <profile_1:プロフィール>
 * <description_1:説明>
 * <message1_1:スキルのメッセージ1行目、ステートのメッセージ（アクター）>
 * <message2_1:スキルのメッセージ2行目、ステートのメッセージ（敵キャラ）>
 * <message3_1:ステートのメッセージ（継続）>
 * <message4_1:ステートのメッセージ（解除）>
 * 
 * 属性、装備タイプ、スキルタイプ、通貨単位、用語は jsonファイルに記述します。
 * ファイル名は「KRD_Multilingual_1.json」（1の部分は言語番号の連番）です。
 * このファイルを「data」フォルダに入れてください。
 * 
 * 以下は jsonファイルのサンプルです。
 * これをコピーして jsonファイルを作成および編集してください。
 * 尚、System.json に同じデータ項目がありますので、
 * System.json からコピーしても構いません。

{
	"elements":[
		"","物理","炎","氷","雷","水","土","風","光","闇"
	],
	"equipTypes":[
		"","武器","盾","頭","身体","装飾品"
	],
	"skillTypes":[
		"","魔法","必殺技"
	],
	"currencyUnit":"Ｇ",
	"terms":{
		"basic":[
			"レベル","Lv","ＨＰ","HP","ＭＰ","MP","ＴＰ","TP","経験値","EXP"
		],
		"commands":[
			"戦う","逃げる","攻撃","防御","アイテム","スキル","装備","ステータス","並び替え","セーブ","ゲーム終了","オプション","武器","防具","大事なもの","装備","最強装備","全て外す","ニューゲーム","コンティニュー",null,"タイトルへ","やめる",null,"購入する","売却する"
		],
		"params":[
			"最大ＨＰ","最大ＭＰ","攻撃力","防御力","魔法力","魔法防御","敏捷性","運","命中率","回避率"
		],
		"messages":{
			"alwaysDash":"常時ダッシュ","commandRemember":"コマンド記憶","touchUI":"タッチUI","bgmVolume":"BGM 音量","bgsVolume":"BGS 音量","meVolume":"ME 音量","seVolume":"SE 音量","possession":"持っている数","expTotal":"現在の%1","expNext":"次の%1まで","saveMessage":"どのファイルにセーブしますか？","loadMessage":"どのファイルをロードしますか？","file":"ファイル","autosave":"オートセーブ","partyName":"%1たち","emerge":"%1が出現！","preemptive":"%1は先手を取った！","surprise":"%1は不意をつかれた！","escapeStart":"%1は逃げ出した！","escapeFailure":"しかし逃げることはできなかった！","victory":"%1の勝利！","defeat":"%1は戦いに敗れた。","obtainExp":"%1 の%2を獲得！","obtainGold":"お金を %1\\G 手に入れた！","obtainItem":"%1を手に入れた！","levelUp":"%1は%2 %3 に上がった！","obtainSkill":"%1を覚えた！","useItem":"%1は%2を使った！","criticalToEnemy":"会心の一撃！！","criticalToActor":"痛恨の一撃！！","actorDamage":"%1は %2 のダメージを受けた！","actorRecovery":"%1の%2が %3 回復した！","actorGain":"%1の%2が %3 増えた！","actorLoss":"%1の%2が %3 減った！","actorDrain":"%1は%2を %3 奪われた！","actorNoDamage":"%1はダメージを受けていない！","actorNoHit":"ミス！　%1はダメージを受けていない！","enemyDamage":"%1に %2 のダメージを与えた！","enemyRecovery":"%1の%2が %3 回復した！","enemyGain":"%1の%2が %3 増えた！","enemyLoss":"%1の%2が %3 減った！","enemyDrain":"%1の%2を %3 奪った！","enemyNoDamage":"%1にダメージを与えられない！","enemyNoHit":"ミス！　%1にダメージを与えられない！","evasion":"%1は攻撃をかわした！","magicEvasion":"%1は魔法を打ち消した！","magicReflection":"%1は魔法を跳ね返した！","counterAttack":"%1の反撃！","substitute":"%1が%2をかばった！","buffAdd":"%1の%2が上がった！","debuffAdd":"%1の%2が下がった！","buffRemove":"%1の%2が元に戻った！","actionFailure":"%1には効かなかった！"
		}
	}
}

 * 
 */

(() => {

'use strict';

const PLUGIN_NAME	= "KRD_MZ_Multilingual";
const PARAM			= PluginManager.parameters(PLUGIN_NAME);

const argLanguage	= JSON.parse(PARAM["argLanguage"] || ["日本語"]);
const argOptionText	= JSON.parse(PARAM["argOptionText"] || ["言語"]);

const defaultValue = 0;
ConfigManager.multilingual = defaultValue;

const rubyPlugin = $plugins.find(plugin => plugin.name === "KRD_MZ_Ruby") || {status:false};
const useRubyPlugin = rubyPlugin.status === true;
const heightPlus = 12;
const yPlus = 16;

//--------------------------------------
// Plugin Command for MZ

PluginManager.registerCommand(PLUGIN_NAME, "setLanguage", args => {
	const varLanguage = Number(args.varLanguage) || 1;
	const value = $gameVariables.value(varLanguage);
	if (value < 0 || value >= argLanguage.length) {
		return;
	}
	ConfigManager.multilingual = value;
	ConfigManager.save();
});

PluginManager.registerCommand(PLUGIN_NAME, "getLanguage", args => {
	const varLanguage = Number(args.varLanguage) || 1;
	const value = ConfigManager.multilingual;
	$gameVariables.setValue(varLanguage, value);
});

//--------------------------------------
// オプション画面

const KRD_Scene_Options_maxCommands = Scene_Options.prototype.maxCommands;
Scene_Options.prototype.maxCommands = function() {
	return KRD_Scene_Options_maxCommands.apply(this, arguments) + 1;
};

const KRD_Window_Options_addGeneralOptions = Window_Options.prototype.addGeneralOptions;
Window_Options.prototype.addGeneralOptions = function() {
	KRD_Window_Options_addGeneralOptions.apply(this, arguments);
	this.addCommand(argOptionText[ConfigManager.multilingual], "multilingual");
};

const KRD_ConfigManager_makeData = ConfigManager.makeData;
ConfigManager.makeData = function() {
	const config = KRD_ConfigManager_makeData.apply(this, arguments);
	config.multilingual = this.multilingual;
	return config;
};

const KRD_ConfigManager_applyData = ConfigManager.applyData;
ConfigManager.applyData = function(config) {
	KRD_ConfigManager_applyData.apply(this, arguments);
	this.multilingual = this.readIndex(config, "multilingual");
};

ConfigManager.readIndex = function(config, name) {
	if (name in config) {
		return Number(config[name]).clamp(0, argLanguage.length - 1);
	} else {
		return defaultValue;
	}
};

const KRD_Window_Options_statusText = Window_Options.prototype.statusText;
Window_Options.prototype.statusText = function(index) {
	const symbol = this.commandSymbol(index);
	if (symbol !== "multilingual") {
		return KRD_Window_Options_statusText.apply(this, arguments);
	}
	const value = this.getConfigValue(symbol);
	return argLanguage[value];
};

const KRD_Window_Options_processOk = Window_Options.prototype.processOk;
Window_Options.prototype.processOk = function() {
	const index = this.index();
	const symbol = this.commandSymbol(index);
	if (symbol !== "multilingual") {
		KRD_Window_Options_processOk.apply(this, arguments);
		return;
	}
	this.changeIndex(symbol, this.getConfigValue(symbol) + 1);
};

const KRD_Window_Options_cursorRight = Window_Options.prototype.cursorRight;
Window_Options.prototype.cursorRight = function() {
	const index = this.index();
	const symbol = this.commandSymbol(index);
	if (symbol !== "multilingual") {
		KRD_Window_Options_cursorRight.apply(this, arguments);
		return;
	}
	const value = Math.min(this.getConfigValue(symbol) + 1, argLanguage.length - 1);
	this.changeIndex(symbol, value);
};

const KRD_Window_Options_cursorLeft = Window_Options.prototype.cursorLeft;
Window_Options.prototype.cursorLeft = function() {
	const index = this.index();
	const symbol = this.commandSymbol(index);
	if (symbol !== "multilingual") {
		KRD_Window_Options_cursorLeft.apply(this, arguments);
		return;
	}
	const value = Math.max(this.getConfigValue(symbol) - 1, 0);
	this.changeIndex(symbol, value);
};

Window_Options.prototype.changeIndex = function(symbol, value) {
	if (value >= argLanguage.length) {
		value = 0;
	} else if (value < 0) {
		value = argLanguage.length - 1;
	}
	const lastValue = this.getConfigValue(symbol);
	if (lastValue !== value) {
		this.setConfigValue(symbol, value);
		this.redrawItem(this.findSymbol(symbol));
		this.playCursorSound();
	}

	//追加（ひぃま
	if(symbol === 'multilingual'){
		$gameVariables.setValue(25, value);
	}
};

//--------------------------------------
// 表示：アイテム名など

const KRD_Window_Base_drawItemName = Window_Base.prototype.drawItemName;
Window_Base.prototype.drawItemName = function(item, x, y, width) {
	if (item) {
		let data = {name: ""};
		if (DataManager.isItem(item)) {
			data = getData($dataItems[item.id]);
		} else if (DataManager.isSkill(item)) {
			data = getData($dataSkills[item.id]);
		} else if (DataManager.isWeapon(item)) {
			data = getData($dataWeapons[item.id]);
		} else if (DataManager.isArmor(item)) {
			data = getData($dataArmors[item.id]);
		}

		if (useRubyPlugin) {
			const iconY = y + (this.lineHeight() - ImageManager.iconHeight) / 2;
			const textMargin = ImageManager.iconWidth + 4;
			const itemWidth = Math.max(0, width - textMargin);
			this.resetTextColor();
			this.drawIcon(item.iconIndex, x, iconY + heightPlus);
			this.drawTextEx(data.name, x + textMargin, y, itemWidth);
		} else {
			KRD_Window_Base_drawItemName.call(this, data, x, y, width);
		}
	}
};

	
const KRD_Window_Base_drawDescription = Window_Base.prototype.drawDescription;
Window_Base.prototype.drawDescription = function(item, x, y, width) {
	if (item) {
		let data = {description: ""};
		if (DataManager.isItem(item)) {
			data = getData($dataItems[item.id]);
		} else if (DataManager.isSkill(item)) {
			data = getData($dataSkills[item.id]);
		} else if (DataManager.isWeapon(item)) {
			data = getData($dataWeapons[item.id]);
		} else if (DataManager.isArmor(item)) {
			data = getData($dataArmors[item.id]);
		}

		if (useRubyPlugin) {
			this.changeTextColor(ColorManager.normalColor());
			const fontSize = 21;
			this.drawTextEx("\\FS[" + fontSize +"]" + data.description, x, y - yPlus, width);
		} else {
			KRD_Window_Base_drawDescription.call(this, data, x, y, width);
		}
	}
};

//追加（ひぃま
Window_Base.prototype.itemData = function(item) {
	if (item) {
			let data = {name: ""};
			if (DataManager.isItem(item)) {
					data = getData($dataItems[item.id]);
			} else if (DataManager.isSkill(item)) {
					data = getData($dataSkills[item.id]);
			} else if (DataManager.isWeapon(item)) {
					data = getData($dataWeapons[item.id]);
			} else if (DataManager.isArmor(item)) {
					data = getData($dataArmors[item.id]);
			}
			return data;
	}
};

//--------------------------------------
// 取得：アクター情報

const KRD_Game_Actor_name = Game_Actor.prototype.name;
Game_Actor.prototype.name = function() {
	const id = this.actorId();
	const dafaultName = $dataActors[id].name;
	if (this._name !== dafaultName) {
		// イベントで変更した場合は変更を優先する。
		return KRD_Game_Actor_name.apply(this, arguments);
	}
	return getData($dataActors[id]).name;
};

const KRD_Game_Actor_nickname = Game_Actor.prototype.nickname;
Game_Actor.prototype.nickname = function() {
	const id = this.actorId();
	const dafaultNickname = $dataActors[id].nickname;
	if (this._nickname !== dafaultNickname) {
		// イベントで変更した場合は変更を優先する。
		return KRD_Game_Actor_nickname.apply(this, arguments);
	}
	return getData($dataActors[id]).nickname;
};

const KRD_Game_Actor_profile = Game_Actor.prototype.profile;
Game_Actor.prototype.profile = function() {
	const id = this.actorId();
	const dafaultProfile = $dataActors[id].profile;
	if (this._profile !== dafaultProfile) {
		// イベントで変更した場合は変更を優先する。
		return KRD_Game_Actor_profile.apply(this, arguments);
	}
	return getData($dataActors[id]).profile;
};

//--------------------------------------
// 取得：職業名

Window_StatusBase.prototype.drawActorClass = function(actor, x, y, width) {
	const data = getData($dataClasses[actor.currentClass().id]);

	width = width || 168;
	this.resetTextColor();
	this.drawText(data.name, x, y, width);
};

//--------------------------------------
// 取得：敵キャラ名

Game_Enemy.prototype.originalName = function() {
	const data = getData($dataEnemies[this.enemyId()]);
	return data.name;
};

//--------------------------------------
// 取得：用語

const KRD_DataManager_loadDatabase = DataManager.loadDatabase;
DataManager.loadDatabase = function() {
	for(let i = 1; i < argLanguage.length; i++) {
		this._databaseFiles.push({ name: "$dataMultilingual_" + i, src: "KRD_Multilingual_" + i + ".json" });
	}
	KRD_DataManager_loadDatabase.apply(this, arguments);
};

const KRD_TextManager_basic = TextManager.basic;
TextManager.basic = function(basicId) {
	const language = ConfigManager.multilingual;
	if (language <= 0) {
		return KRD_TextManager_basic.apply(this, arguments);
	}
	const data = eval("$dataMultilingual_" + language);
	return data.terms.basic[basicId] || "";
};

const KRD_TextManager_param = TextManager.param;
TextManager.param = function(paramId) {
	const language = ConfigManager.multilingual;
	if (language <= 0) {
		return KRD_TextManager_param.apply(this, arguments);
	}
	const data = eval("$dataMultilingual_" + language);
	return data.terms.params[paramId] || "";
};

const KRD_TextManager_command = TextManager.command;
TextManager.command = function(commandId) {
	const language = ConfigManager.multilingual;
	if (language <= 0) {
		return KRD_TextManager_command.apply(this, arguments);
	}
	const data = eval("$dataMultilingual_" + language);
	return data.terms.commands[commandId] || "";
};

const KRD_TextManager_message = TextManager.message;
TextManager.message = function(messageId) {
	const language = ConfigManager.multilingual;
	if (language <= 0) {
		return KRD_TextManager_message.apply(this, arguments);
	}
	const data = eval("$dataMultilingual_" + language);
	return data.terms.messages[messageId] || "";
};

Object.defineProperty(TextManager, "currencyUnit", {
	get: function() {
		const language = ConfigManager.multilingual;
		if (language <= 0) {
			return $dataSystem.currencyUnit;
		}
		const data = eval("$dataMultilingual_" + language);
		return data.currencyUnit || "";
	},
	configurable: true
});

//--------------------------------------
// 取得：用語（追加関数）

TextManager.skillType = function(id) {
	const language = ConfigManager.multilingual;
	if (language <= 0) {
		return $dataSystem.skillTypes[id];
	}
	const data = eval("$dataMultilingual_" + language);
	return data.skillTypes[id] || "";
};

Window_SkillType.prototype.makeCommandList = function() {
	if (this._actor) {
		const skillTypes = this._actor.skillTypes();
		for (const stypeId of skillTypes) {
			const name = TextManager.skillType(stypeId);
			this.addCommand(name, "skill", true, stypeId);
		}
	}
};

Window_ActorCommand.prototype.addSkillCommands = function() {
	const skillTypes = this._actor.skillTypes();
	for (const stypeId of skillTypes) {
		const name = TextManager.skillType(stypeId);
		this.addCommand(name, "skill", true, stypeId);
	}
};

TextManager.equipType = function(id) {
	const language = ConfigManager.multilingual;
	if (language <= 0) {
		return $dataSystem.equipTypes[id];
	}
	const data = eval("$dataMultilingual_" + language);
	return data.equipTypes[id] || "";
};

Window_StatusBase.prototype.actorSlotName = function(actor, index) {
	const slots = actor.equipSlots();
	return TextManager.equipType(slots[index]);
};

TextManager.element = function(id) {
	const language = ConfigManager.multilingual;
	if (language <= 0) {
		return $dataSystem.elements[id];
	}
	const data = eval("$dataMultilingual_" + language);
	return data.elements[id] || "";
};

//--------------------------------------
// バトルログ

Window_BattleLog.prototype.displayAction = function(subject, item) {
	const numMethods = this._methods.length;
	if (DataManager.isSkill(item)) {
		const data = getData(item);
		this.displayItemMessage(data.message1, subject, item);
		this.displayItemMessage(data.message2, subject, item);
	} else {
		this.displayItemMessage(TextManager.useItem, subject, item);
	}
	if (this._methods.length === numMethods) {
		this.push("wait");
	}
};

Window_BattleLog.prototype.displayAddedStates = function(target) {
	const result = target.result();
	const states = result.addedStateObjects();
	for (const state of states) {
		const data = getData(state);
		const stateText = target.isActor() ? data.message1 : data.message2;
		if (state.id === target.deathStateId()) {
			this.push("performCollapse", target);
		}
		if (stateText) {
			this.push("popBaseLine");
			this.push("pushBaseLine");
			this.push("addText", stateText.format(target.name()));
			this.push("waitForEffect");
		}
	}
};

Window_BattleLog.prototype.displayRemovedStates = function(target) {
	const result = target.result();
	const states = result.removedStateObjects();
	for (const state of states) {
		const data = getData(state);
		if (data.message4) {
			this.push("popBaseLine");
			this.push("pushBaseLine");
			this.push("addText", data.message4.format(target.name()));
		}
	}
};

//--------------------------------------
// ステートメッセージ

Game_BattlerBase.prototype.mostImportantStateText = function() {
	for (const state of this.states()) {
		const data = getData(state);
		if (data.message3) {
			return data.message3;
		}
	}
	return "";
};

Game_Actor.prototype.showRemovedStates = function() {
	for (const state of this.result().removedStateObjects()) {
		const data = getData(state);
		if (data.message4) {
			$gameMessage.add(data.message4.format(this._name));
		}
	}
};

//--------------------------------------
})();

//--------------------------------------
// 共通関数

function getData(data) {
	const language = ConfigManager.multilingual;
	return {
		get name() {
			return data.meta["name_" + Number(language)] || data.name;
		},
		get nickname() {
			return data.meta["nickname_" + Number(language)] || data.nickname;
		},
		get profile() {
			return data.meta["profile_" + Number(language)] || data.profile;
		},
		get description() {
			return data.meta["description_" + Number(language)] || data.description;
		},
		get message1() {
			return data.meta["message1_" + Number(language)] || data.message1;
		},
		get message2() {
			return data.meta["message2_" + Number(language)] || data.message2;
		},
		get message3() {
			return data.meta["message3_" + Number(language)] || data.message3;
		},
		get message4() {
			return data.meta["message4_" + Number(language)] || data.message4;
		},
		get iconIndex() {
			return data.iconIndex;
		}
	};
};

//追加（ひぃま
Scene_Load.prototype.reloadMapIfUpdated = function() {
	if ($gameSystem.versionId() !== $dataSystem.versionId) {
			const mapId = $gameMap.mapId();
			const x = $gamePlayer.x;
			const y = $gamePlayer.y;
			$gamePlayer.reserveTransfer(mapId, x, y);
			$gamePlayer.requestMapReload();
			const value = ConfigManager.multilingual;//test
		$gameVariables.setValue(25, value);//test
	}
};