/*:
 * @target MZ
 * @plugindesc 音量調節スライダー
 * @url https://twitter.com/kuroudo119/
 * @url https://github.com/kuroudo119/RPGMZ-Plugin
 * @author kuroudo119 (くろうど)
 * 
 * 
 * @help
音量調節スライダー

 * 
 * 
 */

(function () {
	// ####################################################
	// ################# アイテムの種類 ####################
	// ####################################################
	Scene_Options.prototype.create = function () {
		Scene_MenuBase.prototype.create.call(this);

		this.createCharaVoiceWindow();
		this.createOptionsWindow();
		this.createCategoryWindow();

		this._categoryWindow.setItemWindow(this._itemWindow);
		this._categoryWindow.setVoiceWindow(this._charaVoiceWindow);
		this._charaVoiceWindow.setItemWindow(this._itemWindow);
		this._itemWindow.setVoiceWindow(this._charaVoiceWindow);
	};
	// 背景
	Scene_Options.prototype.createBackground = function () {
		this._backgroundSprite = new Sprite();
		this._backgroundSprite.bitmap = ImageManager.loadSystem("option_back");
		this.addChild(this._backgroundSprite);

		this._backgroundTextSprite = new Sprite(new Bitmap(Graphics.width, Graphics.height));
		var b = this._backgroundTextSprite.bitmap;
		b.fontFace = "serif";
		b.fontSize = 32;
		b.textColor = "#000000";
		b.drawTextM("Configuration", 22, 20, 200, 22, "center");
		this.addChild(this._backgroundTextSprite);
	};

	Scene_Options.prototype.popScene = function () {
		// コンフィグを閉じるとき共通変数としてセーブ
		ConfigManager.saveCommonVariables();
		SceneManager.pop();
	};

	Scene_Options.prototype.createCategoryWindow = function () {
		const rect = this.categoryWindowRect();
		this._categoryWindow = new Window_OptionCategory(rect);
		this._categoryWindow.setHandler("ok", this.onCategoryOk.bind(this));
		this._categoryWindow.setHandler("cancel", this.popScene.bind(this));
		this.addWindow(this._categoryWindow);
	};
	Scene_Options.prototype.onCategoryOk = function () {
		this._itemWindow.activate();
		this._itemWindow.select(0);
	};
	Scene_Options.prototype.createOptionsWindow = function () {
		const rect = this.optionsWindowRect();
		this._itemWindow = new Window_Options(rect);
		this._itemWindow.setHandler("cancel", this.onItemCancel.bind(this));
		this.addWindow(this._itemWindow);
	};

	Scene_Options.prototype.onItemCancel = function () {
		this._itemWindow.deselect();
		this._categoryWindow.activate();
	};

	Scene_Options.prototype.charaVoiceWindowRect = function () {
		const ww = 1144;
		const wh = 320;
		const wx = (Graphics.boxWidth - ww) / 2;
		const wy = 400;
		return new Rectangle(wx, wy, ww, wh);
	};

	Scene_Options.prototype.createCharaVoiceWindow = function () {
		const rect = this.charaVoiceWindowRect();
		this._charaVoiceWindow = new Window_CharaVoice(rect);
		this._charaVoiceWindow.setHandler("cancel", this.onCharaVoiceCancel.bind(this));
		this._charaVoiceWindow.zIndex = 3000;
		//this._charaVoiceWindow.setHandler("ok", this.onCharaVoiceOk.bind(this));
		this.addWindow(this._charaVoiceWindow);
	};
	Scene_Options.prototype.onCharaVoiceCancel = function () {
		this._charaVoiceWindow.deselect();
		//this._charaVoiceWindow.hide();
		this._itemWindow.activate();
	};

	Scene_Options.prototype.categoryWindowRect = function () {
		const wx = 270;
		const wy = -6;
		const ww = 750;
		const wh = 58 + 8;
		return new Rectangle(wx, wy, ww, wh);
	};
	Scene_Options.prototype.optionsWindowRect = function () {
		const n = Math.min(this.maxCommands(), this.maxVisibleCommands());
		const ww = 1050;
		const wh = 450;
		const wx = (Graphics.boxWidth - ww) / 2;
		const wy = 110;
		return new Rectangle(wx, wy, ww, wh);
	};

	const Scene_Options_start = Scene_Options.prototype.start;
	Scene_Options.prototype.start = function () {
		Scene_Options_start.apply(this, arguments);
		if (!bgm_show) {
			bgm_show = true;

			const x = BASE_X - 100;
			const y = BASE_Y - 427;
			const lineHeight = BASE_LINE_HEIGHT + 4;
			this._bgmRange = new InputRange(
				AudioManager.bgmVolume,
				x,
				y + lineHeight * 0,
				this._itemWindow,
				"bgmVolume",
				"bgmVolume",
				"optGauge sound"
			);
			this._bgsRange = new InputRange(
				AudioManager.bgsVolume,
				x,
				y + lineHeight * 1,
				this._itemWindow,
				"bgsVolume",
				"bgsVolume",
				"optGauge sound"
			);

			this._seRange = new InputRange(AudioManager.seVolume, x, y + lineHeight * 2, this._itemWindow, "seVolume", "seVolume", "optGauge sound");
			this._meRange = new InputRange(AudioManager.meVolume, x, y + lineHeight * 3, this._itemWindow, "meVolume", "meVolume", "optGauge sound");

			this._msOpacityVolume = new InputRange(
				ConfigManager.msOpacityVolume,
				x,
				y + lineHeight * 0,
				this._itemWindow,
				"msOpacityVolume",
				"msOpacityVolume",
				"optGauge system_2"
			);
			this._autoMsSpeedVolume = new InputRange(
				ConfigManager.autoMsSpeedVolume,
				x,
				y + lineHeight * 2,
				this._itemWindow,
				"autoMsSpeedVolume",
				"autoMsSpeedVolume",
				"optGauge system_2"
			);
		}
	};

	const Scene_Options_terminate = Scene_Options.prototype.terminate;
	Scene_Options.prototype.terminate = function () {
		Scene_Options_terminate.apply(this, arguments);
		if (bgm_show) {
			bgm_show = false;
			// ↓作成したIDの""なしを引数にする
			document.body.removeChild(bgmVolume.closest("div"));
			document.body.removeChild(bgsVolume.closest("div"));
			document.body.removeChild(seVolume.closest("div"));
			document.body.removeChild(meVolume.closest("div"));

			document.body.removeChild(msOpacityVolume.closest("div"));
			document.body.removeChild(autoMsSpeedVolume.closest("div"));
		}
	};

	function Window_OptionCategory() {
		this.initialize(...arguments);
	}

	Window_OptionCategory.prototype = Object.create(Window_HorzCommand.prototype);
	Window_OptionCategory.prototype.constructor = Window_OptionCategory;

	Window_OptionCategory.prototype.initialize = function (rect) {
		Window_HorzCommand.prototype.initialize.call(this, rect);
		this._padding = 0;

		this.refresh();
		this.select(0);
		this.activate();
	};

	Window_OptionCategory.prototype.maxCols = function () {
		return 5;
	};

	 //Only "Item" and "Key Items" as categories
	Window_OptionCategory.prototype.makeCommandList = function () {
		this.addCommand("System 1", "system_1");
		this.addCommand("System 2", "system_2");
		this.addCommand("Sound", "sound");
		this.addCommand("Keypad", "key_pad");
		this.addCommand("Gamepad", "game_pad");
	};

	Window_OptionCategory.prototype.setItemWindow = function (itemWindow) {
		this._itemWindow = itemWindow;
	};
	Window_OptionCategory.prototype.setVoiceWindow = function (voiceWindow) {
		this._voiceWindow = voiceWindow;
	};

	// 変更があったらカテゴリーを更新する
	Window_OptionCategory.prototype.update = function () {
		Window_HorzCommand.prototype.update.call(this);
		if (this._itemWindow) {
			this._itemWindow.setCategory(this.currentSymbol());
		}
	};

	Window_OptionCategory.prototype._refreshAllParts = function () {
		this._padding = 0;
		//this._refreshBack();
		//this._refreshFrame();
		this._refreshCursor();
		this._refreshArrows();
		this._refreshPauseSign();
	};

	//カーソルの変更
	Window_OptionCategory.prototype.loadWindowskin = function () {
		this.windowskin = ImageManager.loadSystem("Window");
		this.menu_item_skin = ImageManager.loadSystem("menu_item_categoly_select");
		this.menu_cursor_skin = ImageManager.loadSystem("menu_item_categoly_cursor");

		if (!this.menu_item_skin.isReady()) {
			this.menu_item_skin.addLoadListener(() => {
				this.refresh(); // 画像がロードされたら再描画
			});
			return;
		}
	};

	Window_OptionCategory.prototype.lineHeight = function () {
		return 58;
	};

	Window_OptionCategory.prototype._refreshCursor = function () {
		const drect = this._cursorRect.clone();
		const srect = { x: 0, y: 0, width: 126, height: 58 };
		const m = 0;
		for (const child of this._cursorSprite.children) {
			child.bitmap = this.menu_cursor_skin;
		}
		this._setRectPartsGeometry(this._cursorSprite, srect, drect, m);
	};
	//カーソルを微調整、あとカーソルを常に不透明に
	Window_OptionCategory.prototype._updateCursor = function () {
		this._cursorSprite.alpha = 255;
		this._cursorSprite.visible = this.isOpen() && this.cursorVisible;
		this._cursorSprite.x = this._cursorRect.x;
		this._cursorSprite.y = this._cursorRect.y - 4;
	};
	//未選択コマンドの背景を画像に
	Window_OptionCategory.prototype.drawItemBackground = function (index) {
		const rect = this.itemRect(index);
		if (this.menu_item_skin.isReady()) {
			const bitmap = this.menu_item_skin;
			const dx = rect.x;
			const dy = rect.y;
			const dw = rect.width;
			const dh = rect.height;
			this.contentsBack.blt(bitmap, 0, 0, 126, 58, dx, dy - 4, dw, dh);
		}
	};

	//カーソルが来た時、アイテムの文字名の色を変更する
	Window_OptionCategory.prototype.drawItem = function (index) {
		const rect = this.itemLineRect(index);
		const align = this.itemTextAlign();
		this.resetTextColor();
		if (index == this._index) {
			this.changeTextColor("#000000");
		}
		this.changePaintOpacity(this.isCommandEnabled(index));
		//文字をちょっと下にする
		this.drawTextS(this.commandName(index), rect.x, rect.y + 8, rect.width, align);
	};

	//セレクトするたびに背景をリフレッシュ
	Window_OptionCategory.prototype.select = function (index) {
		this._index = index;
		if (this._voiceWindow) {
			if (index == 2) {
				this._voiceWindow.show();
			} else {
				this._voiceWindow.hide();
			}
		}

		this.contents.clear();
		this.contentsBack.clear();
		this.drawAllItems();

		this.refreshCursor();
		this.callUpdateHelp();
	};
	//↑のセレクトでの不具合を出ないようにする
	Window_OptionCategory.prototype.drawAllItems = function () {
		this.contents.fontFace = "serif";
		const topIndex = this.topIndex();
		for (let i = 0; i < this.maxVisibleItems(); i++) {
			const index = topIndex + i;

			if (this._list && index < this.maxItems()) {
				//選択ちゅうだけ背景なくす
				if (i != this._index) {
					this.drawItemBackground(index);
				}
				this.drawItem(index);
			}
		}
	};

	// Window_OptionCategory.prototype.playOkSound = function () {
	// 	SoundManager.playOk();
	// };

	// #######################################################
	// ################# オプション一覧 #######################
	// #######################################################

	const BASE_X = (Graphics.width || 1280) / 2;
	const BASE_Y = (Graphics.height || 720) / 2 + 200;
	const BASE_LINE_HEIGHT = 50;

	let bgm_show = false;
	Window_Options.prototype.initialize = function (rect) {
		Window_Selectable.prototype.initialize.call(this, rect);

		this._category = null;
		this.refresh();
		//this.select(0);
		//this.activate();

		// windowが重なっても透過させる
		this._isWindow = false;
	};

	Window_Options.prototype.loadWindowskin = function () {
		this.windowskin = ImageManager.loadSystem("Window");
		this.menu_item_skin = ImageManager.loadSystem("config_item_select");
		//this.menu_toggle_skin = ImageManager.loadSystem("config_toggle");

		if (!this.menu_item_skin.isReady()) {
			this.menu_item_skin.addLoadListener(() => {
				this.refresh(); // 画像がロードされたら再描画
			});
			return;
		}
	};

	Window_Options.prototype._refreshCursor = function () {
		const drect = this._cursorRect.clone();
		const srect = { x: 0, y: 40, width: 1027, height: 40 };
		const m = 0;
		for (const child of this._cursorSprite.children) {
			child.bitmap = this.menu_item_skin;
		}
		this._setRectPartsGeometry(this._cursorSprite, srect, drect, m);
	};
	Window_Options.prototype.refreshCursor = function () {
		if (this._cursorAll) {
			this.refreshCursorForAll();
		} else if (this.index() >= 0) {
			const rect = this.itemRect(this.index());
			this.setCursorRect(rect.x, rect.y, rect.width, rect.height);
		} else {
			this.setCursorRect(0, 0, 0, 0);
		}

		const index = this.index();
		if (index != -1) {
			const symbol = this.commandSymbol(index);
			var dom = document.querySelectorAll(`.optRange_wrap`);
			for (var i = 0; i < dom.length; i++) {
				dom[i].closest("div").style.backgroundPosition = "0px -32px";
			}

			var dom = document.querySelector(`#${symbol}`);
			if (dom) {
				dom.closest("div").style.backgroundPosition = "0px 0px";
			}
		}
	};

	Window_Options.prototype._createAllParts = function () {
		this._createContainer();
		this._createBackSprite();
		this._createFrameSprite();
		this._createClientArea();
		this._createContentsBackSprite();
		this._createCursorSprite();
		this._createToggleSprite();
		this._createContentsSprite();
		this._createArrowSprites();
		this._createPauseSignSprites();
	};
	Window_Options.prototype._createToggleSprite = function () {
		this._toggleSprite = [];
		for (var i = 0; i < 8; i++) {
			this._toggleSprite[i] = [];
			for (var k = 0; k < 3; k++) {
				this._toggleSprite[i][k] = new Sprite();
				this._toggleSprite[i][k].bitmap = ImageManager.loadSystem("config_toggle");
				this._toggleSprite[i][k].y = i * 54 + 11;
				this._toggleSprite[i][k].x = 470 + k * 170;
				this._toggleSprite[i][k].setFrame(0, 0, 0, 0);

				this._clientArea.addChild(this._toggleSprite[i][k]);
			}
		}
	};

	Window_Options.prototype.drawAllItems = function () {
		const topIndex = this.topIndex();
		for (let i = 0; i < this.maxVisibleItems(); i++) {
			const index = topIndex + i;
			if (index < this.maxItems()) {
				this.drawItemBackground(index);
				this.drawItem(index);
			}
		}

		for (var i = 0; i < 8; i++) {
			if (!this._list[i]) {
				this._toggleSprite[i][0].setFrame(0, 0, 0, 0);
				this._toggleSprite[i][1].setFrame(0, 0, 0, 0);
				this._toggleSprite[i][2].setFrame(0, 0, 0, 0);
				continue;
			}

			const symbol = this.commandSymbol(i);
			const value = this.getConfigValue(symbol);

			if (typeof value === "boolean") {
				this._toggleSprite[i][0].setFrame(0, value ? 0 : 32, 159, 32);
				this._toggleSprite[i][1].setFrame(0, value ? 32 : 0, 159, 32);
				this._toggleSprite[i][2].setFrame(0, 0, 0, 0);
			} else if (this.commandExt(i) === "tri") {
				this._toggleSprite[i][0].setFrame(0, value == 0 ? 0 : 32, 159, 32);
				this._toggleSprite[i][1].setFrame(0, value == 1 ? 0 : 32, 159, 32);
				this._toggleSprite[i][2].setFrame(0, value == 2 ? 0 : 32, 159, 32);
			} else {
				this._toggleSprite[i][0].setFrame(0, 0, 0, 0);
				this._toggleSprite[i][1].setFrame(0, 0, 0, 0);
				this._toggleSprite[i][2].setFrame(0, 0, 0, 0);
			}
		}
	};

	//未選択コマンドの背景を画像に
	Window_Options.prototype.drawItemBackground = function (index) {
		const rect = this.itemRect(index);
		if (this.menu_item_skin) {
			const bitmap = this.menu_item_skin;
			const dx = rect.x;
			const dy = rect.y;
			const dw = rect.width;
			const dh = rect.height;
			this.contentsBack.blt(bitmap, 0, 0, 1027, 40, dx, dy, dw, dh);
		}
	};
	Window_Options.prototype._refreshAllParts = function () {
		//this._refreshBack();
		//this._refreshFrame();
		this._refreshCursor();
		this._refreshArrows();
		this._refreshPauseSign();
	};

	Window_Options.prototype.rowSpacing = function () {
		return 4 + 10;
	};

	Window_Options.prototype.itemRect = function (index) {
		const maxCols = this.maxCols();
		const itemWidth = this.itemWidth();
		const itemHeight = this.itemHeight() + 10;
		const colSpacing = this.colSpacing();
		const rowSpacing = this.rowSpacing();
		const col = index % maxCols;
		const row = Math.floor(index / maxCols);
		const x = col * itemWidth + colSpacing / 2 - this.scrollBaseX();
		const y = row * itemHeight + rowSpacing / 2 - this.scrollBaseY();
		const width = itemWidth - colSpacing;
		const height = itemHeight - rowSpacing;
		return new Rectangle(x, y, width, height);
	};
	Window_Options.prototype.itemRectWithPadding = function (index) {
		const rect = this.itemRect(index);
		const padding = this.itemPadding();
		rect.x += padding + 70;
		rect.width -= padding * 2;
		return rect;
	};

	Window_Options.prototype.setCategory = function (category) {
		if (this._category !== category) {
			this._category = category;
			this.refresh();
			this.scrollTo(0, 0);

			var list = ["system_1", "system_2", "sound", "key_pad", "game_pad"];
			for (var i = 0; i < list.length; i++) {
				var doms = document.querySelectorAll(`.${list[i]}`);
				doms.forEach((e) => {
					if (e) {
						e.style.display = "none";
					}
				});
			}

			var doms = document.querySelectorAll(`.${this._category}`);
			doms.forEach((e) => {
				if (e) {
					e.style.display = "inline-block";
				}
			});
		}
	};
	Window_Options.prototype.makeCommandList = function () {
		if (this._category == "system_1") {
			this.addGeneralOptions();
		}
		if (this._category == "system_2") {
			this.addSystem_2Options();
		}
		if (this._category == "sound") {
			this.addVolumeOptions();
		}
		if (this._category == "key_pad" || this._category == "game_pad") {
		}
	};

	const ConfigManager_makeData = ConfigManager.makeData;
	ConfigManager.makeData = function () {
		const config = ConfigManager_makeData.call(this);
		config.screenEffects = this.screenEffects;
		$gameSwitches.setValue(502, config.screenEffects);

		config.battleEffects = this.battleEffects;
		$gameSwitches.setValue(503, config.battleEffects);

		config.autoDefeat = this.autoDefeat;
		// 戦闘→1 選択肢→0 自動敗北→2
		var ary = [1, 0, 2];
		$gameVariables.setValue(502, ary[config.autoDefeat]);

		config.hSkip = this.hSkip;
		$gameSwitches.setValue(504, config.hSkip);

		config.birthSkip = this.birthSkip;
		$gameSwitches.setValue(505, config.birthSkip);

		config.danmenSkip = this.danmenSkip;
		$gameSwitches.setValue(506, config.danmenSkip);

		config.msOpacityVolume = this.msOpacityVolume;
		config.msSpeed = this.msSpeed;
		config.autoMsSpeedVolume = this.autoMsSpeedVolume;
		config.selectLimit = this.selectLimit;
		$gameSwitches.setValue(507, config.selectLimit);

		return config;
	};

	const ConfigManager_applyData = ConfigManager.applyData;
	ConfigManager.applyData = function (config) {
		ConfigManager_applyData.call(this, config);

		this.screenEffects = this.readFlag(config, "screenEffects", true);
		this.battleEffects = this.readFlag(config, "battleEffects", true);
		// this.autoDefeat = this.triIndex(config.autoDefeat);
		this.hSkip = this.readFlag(config, "hSkip", true);
		this.birthSkip = this.readFlag(config, "birthSkip", true);
		this.danmenSkip = this.readFlag(config, "danmenSkip", true);

		// this.msOpacityVolume = this.readVolume(config, "msOpacityVolume");
		// this.msSpeed = this.triIndex(config.msSpeed);
		// this.autoMsSpeedVolume = this.readVolume(config, "autoMsSpeedVolume");
		this.selectLimit = this.readFlag(config, "selectLimit", true);
	};

	// コンフィグに新しい物を追加
	ConfigManager.screenEffects = true;
	ConfigManager.battleEffects = true;

	ConfigManager.hSkip = true;

	ConfigManager.danmenSkip = true; // スキップじゃなくて断面図を表示するって意味

	ConfigManager.selectLimit = true;

	// デフォルト値を設定
	// ConfigManager の元の関数を保存
	const _ConfigManager_applyData = ConfigManager.applyData;

	ConfigManager.applyData = function (config) {
		_ConfigManager_applyData.call(this, config);

		this.autoDefeat = config.autoDefeat ?? 1;
		this.birthSkip = config.birthSkip ?? false;

		this.msOpacityVolume = config.msOpacityVolume ?? 80;
		this.msSpeed = config.msSpeed ?? 1;
		this.autoMsSpeedVolume = config.autoMsSpeedVolume ?? 50;

		this.bgmVolume = config.bgmVolume ?? 50;
		this.bgsVolume = config.bgsVolume ?? 40;
		this.seVolume = config.seVolume ?? 50;
		this.meVolume = config.meVolume ?? 100;
	};

	ConfigManager.triIndex = function (index) {
		if (isNaN(index)) {
			return 0;
		}
		return Math.max(0, Math.min(2, index));
	};

	Window_Options.prototype.addGeneralOptions = function () {
		this.addCommand(TextManager.alwaysDash, "alwaysDash");
		this.addCommand(TextManager.commandRemember, "commandRemember");
		this.addCommand("Screen Effects", "screenEffects");
		this.addCommand("Battle Effects", "battleEffects");
		this.addCommand("Event Battle Outcome Setting", "autoDefeat", true, "tri");
		this.addCommand("Skip Previously Viewed H Scenes", "hSkip");
		this.addCommand("Skip Childbirth Scenes", "birthSkip");
		this.addCommand("Cross-section During H Scenes", "danmenSkip");
		//this.addCommand(TextManager.touchUI, "touchUI");
	};

	Window_Options.prototype.addSystem_2Options = function () {
		this.addCommand("Message Window Transparency", "msOpacityVolume");
		this.addCommand("Message Speed", "msSpeed", true, "tri");
		this.addCommand("Auto Mode Speed", "autoMsSpeedVolume");
		this.addCommand("Timed Choices", "selectLimit");
	};

	Window_Options.prototype.addVolumeOptions = function () {
		this.addCommand(TextManager.bgmVolume, "bgmVolume");
		this.addCommand("BGV Volume", "bgsVolume");
		this.addCommand(TextManager.seVolume, "seVolume");
		this.addCommand("Voice Volume", "meVolume");

		this.addCommand("Character Voice Settings", "charaVoice", true, "move");
	};

	const HIGHLIGHT_COLOR = 24; // 青
	const NORMAL_COLOR = 0;

	// statusText をオーバーライドして、boolean の場合は「ON / OFF」と表示する
	// const _Window_Options_statusText = Window_Options.prototype.statusText;
	// Window_Options.prototype.statusText = function (index, value) {
	// 	const ext = this.commandExt(index);

	// 	if (typeof value === "boolean") {
	// 		const onText = "オン";
	// 		const offText = "オフ";
	// 		return `${onText}            ${offText}`;
	// 	} else if (ext == "tri") {
	// 		const text_1 = "戦闘を行う";
	// 		const text_2 = "選択肢";
	// 		const text_3 = "自動敗北";
	// 		return `${text_1}   　　 ${text_2}   　　 ${text_3}`;
	// 	} else if (ext == "move") {
	// 		return;
	// 	}
	// 	return _Window_Options_statusText.call(this, index);
	// };

	// drawItem をオーバーライド。boolean の項目以外は元の描画処理に任せる
	const _Window_Options_drawItem = Window_Options.prototype.drawItem;
	Window_Options.prototype.drawItem = function (index) {
		const symbol = this.commandSymbol(index);
		// undefined や想定外の項目は元の処理で描画
		if (!symbol) {
			_Window_Options_drawItem.call(this, index);
			return;
		}
		const value = this.getConfigValue(symbol);
		this.contents.fontSize = 22;
		if (typeof value === "boolean") {
			// true,falseの場合
			const rect = this.itemLineRect(index);
			const name = this.commandName(index);
			const statusWidth = this.statusWidth();

			this.resetTextColor();
			this.changePaintOpacity(this.isCommandEnabled(index));
			// 名前部分の描画
			this.changeTextColor("#000000");
			this.drawTextS(name, rect.x, rect.y, rect.width - statusWidth, "left");
			// カスタムステータステキストの描画（制御文字により色変え）
			//onst statusText = this.statusText(index, value);
			this.drawTextS(" On", rect.x + rect.width - statusWidth - 440, rect.y);
			this.drawTextS(" Off", rect.x + rect.width - statusWidth - 268, rect.y);

			this._toggleSprite[index][0].setFrame(0, value ? 0 : 32, 159, 32);
			this._toggleSprite[index][1].setFrame(0, value ? 32 : 0, 159, 32);
		} else if (this.commandExt(index) == "tri") {
			// 1,2,3の場合
			const rect = this.itemLineRect(index);
			const name = this.commandName(index);
			const statusWidth = this.statusWidth();

			this.changeTextColor("#000000");
			this.changePaintOpacity(this.isCommandEnabled(index));
			// 名前部分の描画
			this.drawTextS(name, rect.x, rect.y, rect.width - statusWidth, "left");
			// カスタムステータステキストの描画（制御文字により色変え）
			//const statusText = this.statusText(index, value);
			if (symbol == "autoDefeat") {
				this.drawTextS("Fight", rect.x + rect.width - statusWidth - 440, rect.y);
				this.drawTextS("Choice", rect.x + rect.width - statusWidth - 274, rect.y);
				this.drawTextS("Auto-Defeat", rect.x + rect.width - statusWidth - 130, rect.y);
			} else {
				this.drawTextS("Slow", rect.x + rect.width - statusWidth - 434, rect.y);
				this.drawTextS("Normal", rect.x + rect.width - statusWidth - 268, rect.y);
				this.drawTextS("Bulk", rect.x + rect.width - statusWidth - 100, rect.y);
			}

			this._toggleSprite[index][0].setFrame(0, value == 0 ? 0 : 32, 159, 32);
			this._toggleSprite[index][1].setFrame(0, value == 1 ? 0 : 32, 159, 32);
			this._toggleSprite[index][2].setFrame(0, value == 2 ? 0 : 32, 159, 32);
		} else {
			const title = this.commandName(index);
			const status = this.statusText(index);
			const rect = this.itemLineRect(index);
			const statusWidth = this.statusWidth();
			const titleWidth = rect.width - statusWidth;
			this.changeTextColor("#000000");
			this.changePaintOpacity(this.isCommandEnabled(index));
			this.drawTextS(title, rect.x, rect.y, titleWidth, "left");
			this.drawTextS(status, rect.x + titleWidth, rect.y, statusWidth, "right");
		}
		this.contents.fontSize = $gameSystem.mainFontSize();
	};

	// onとoffの位置を逆にする
	Window_Options.prototype.cursorRight = function () {
		const index = this.index();
		const symbol = this.commandSymbol(index);
		if (this.isVolumeSymbol(symbol)) {
			this.changeVolume(symbol, true, false);
		} else if (this.commandExt(index) == "tri") {
			this.changeTri(symbol, 1, 2);
		} else if (this.commandExt(index) == "move") {
		} else {
			this.changeValue(symbol, false);
		}
	};

	Window_Options.prototype.cursorLeft = function () {
		const index = this.index();
		const symbol = this.commandSymbol(index);
		if (this.isVolumeSymbol(symbol)) {
			this.changeVolume(symbol, false, false);
		} else if (this.commandExt(index) == "tri") {
			this.changeTri(symbol, -1, 2);
		} else if (this.commandExt(index) == "move") {
		} else {
			this.changeValue(symbol, true);
		}
	};

	Window_Options.prototype.changeTri = function (symbol, add, max) {
		const lastValue = this.getConfigValue(symbol);
		if (add == "click") {
			this.changeValue(symbol, Math.floor((lastValue + 1) % (max + 1)));
			return;
		}
		const value = lastValue + add;

		this.changeValue(symbol, value.clamp(0, max));
	};

	Window_Options.prototype.changeVolume = function (symbol, forward, wrap) {
		const lastValue = this.getConfigValue(symbol);
		const offset = this.volumeOffset();
		const value = lastValue + (forward ? offset : -offset);
		if (value > 100 && wrap) {
			this.changeValue(symbol, 0);
		} else {
			this.changeValue(symbol, value.clamp(0, 100));
		}

		var dom = document.querySelector(`#${symbol}`);
		if (dom) {
			dom.value = value;
		}
	};

	Window_Options.prototype.processOk = function () {
		const index = this.index();
		const symbol = this.commandSymbol(index);
		if (this.isVolumeSymbol(symbol)) {
			// this.changeVolume(symbol, true, true);
		} else if (this.commandExt(index) == "tri") {
			this.changeTri(symbol, "click", 2);
		} else if (this.commandExt(index) == "move") {
			SoundManager.playOk();
			this._voiceWindow.select(0);
			this._voiceWindow.activate();
			//this._voiceWindow.show();
			this.deactivate();
		} else {
			this.changeValue(symbol, !this.getConfigValue(symbol));
		}
	};
	Window_Options.prototype.setVoiceWindow = function (voiceWindow) {
		this._voiceWindow = voiceWindow;
	};
	// バーのヤツ
	class InputRange {
		constructor(value, x, y, window2, symbol, id, clas) {
			this._div = document.createElement("div");
			this._div.className = `optRange_wrap ${clas}`;
			this._div.style.display = "none";
			this._div.style.left = `${x}px`;
			this._div.style.top = `${y}px`;

			this._input = document.createElement("input");
			this._input.type = "range";
			this._input.id = id;
			this._input.value = value.toString();
			this._input.min = "0";
			this._input.max = "100";
			this._input.step = "10";

			// Nothing right click.
			this._input.oncontextmenu = function () {
				return false;
			};

			function move(input, window2, symbol) {
				const value = Number(input.value);
				window2.changeValue(symbol, value);
			}

			// Mouse
			this._input.addEventListener(
				"mousemove",
				function (ev, win = window2, sbl = symbol) {
					move(this, win, sbl);
				},
				false
			);

			// マウスダウンの直後だと値が反映されないのでsettimeout
			this._input.addEventListener(
				"mousedown",
				function (ev, win = window2, sbl = symbol) {
					setTimeout(move, 0, this, win, sbl);
				},
				false
			);

			// Touch
			this._input.addEventListener(
				"touchmove",
				function (ev, win = window2, sbl = symbol) {
					move(this, win, sbl);
				},
				false
			);

			this._div.appendChild(this._input);

			if (typeof RangeTouch !== "undefined" && Utils.isMobileDevice()) {
				this._range = new RangeTouch(this._div);
				document.body.appendChild(this._range.element);
			} else {
				document.body.appendChild(this._div);
			}

			Graphics.zoomRange(id, x, y);
		}
	}

	const Graphics__updateRealScale = Graphics._updateRealScale;
	Graphics._updateRealScale = function () {
		Graphics__updateRealScale.apply(this, arguments);
		if (bgm_show) {
			const rangeId = ["bgmVolume", "bgsVolume", "seVolume", "meVolume", "msOpacityVolume", null, "autoMsSpeedVolume"];
			rangeId.forEach((id, index) => {
				if (!id) {
					return;
				}
				const x = BASE_X - 100;
				const y = BASE_Y - 427;
				const lineHeight = BASE_LINE_HEIGHT + 4;
				const y2 = y + lineHeight * (index % 4);
				this.zoomRange(id, x, y2);
			});
		}
	};

	Graphics.zoomRange = function (id, x, y) {
		const x2 = x * this._realScale;
		const y2 = y * this._realScale;
		const rw = Graphics.width * this._realScale;
		const rh = Graphics.height * this._realScale;
		const xSpace = Math.floor((this._stretchWidth() - rw) / 2);
		const ySpace = Math.floor((this._stretchHeight() - rh) / 2);
		const xx = x2 + xSpace;
		const yy = y2 + ySpace;
		const element = document.getElementById(id);
		// element.style.left = xx.toString() + "px";
		// element.style.top = yy.toString() + "px";

		element.parentElement.style.left = xx.toString() + "px";
		element.parentElement.style.top = yy.toString() + "px";

		// element.parentElement.style.scale = this._realScale; // なぜかscaleが働かない環境がある
		element.parentElement.style.transform = `scaleX(${this._realScale}) scaleY(${this._realScale})`;
	};

	// #######################################################
	// ################# ボイスウィンドウ #####################
	// #######################################################
	function Window_CharaVoice() {
		this.initialize(...arguments);
	}

	Window_CharaVoice.prototype = Object.create(Window_Command.prototype);
	Window_CharaVoice.prototype.constructor = Window_CharaVoice;

	Window_CharaVoice.prototype.initialize = function (rect) {
		this.v_list = [
			{ id: "sir", name: "Shirayuki", var: 503, img: null },
			{ id: "yoz", name: "Yazuru", var: 504, img: null },
			{ id: "rei", name: "Reina", var: 505, img: null },
			{ id: "kao", name: "Kaoruko", var: 506, img: null },
			{ id: "kur", name: "Kurumi", var: 507, img: null },
			{ id: "chi", name: "Chiage", var: 508, img: null },
			{ id: "aki", name: "Akira", var: 510, img: null },
			{ id: "nar", name: "Narumi", var: 511, img: null },
			{ id: "mir", name: "Miran", var: 509, img: null },
			{ id: "kag", name: "Kamiya", var: 512, img: null },
			{ id: "mob", name: "Other", var: 513, img: null }
		];

		Window_Command.prototype.initialize.call(this, rect);
		this.refresh();
		this.select(0);
		this.deactivate();
		this.hide();
	};

	Window_CharaVoice.prototype._refreshAllParts = function () {
		//this._refreshBack();
		//this._refreshFrame();
		this._refreshCursor();
		this._refreshArrows();
		this._refreshPauseSign();
	};

	Window_CharaVoice.prototype.loadWindowskin = function () {
		this.windowskin = ImageManager.loadSystem("Window");

		for (e of this.v_list) {
			e.img = ImageManager.loadSystem(`config_voice_toggle_${e.id}`);
			if (!e.img.isReady()) {
				e.img.addLoadListener(() => {
					this.refresh(); // 画像がロードされたら再描画
				});
			}
		}
		this.menu_cursor_skin = ImageManager.loadSystem("config_voice_cursor");

		if (!this.menu_cursor_skin.isReady()) {
			this.menu_cursor_skin.addLoadListener(() => {
				this.refresh(); // 画像がロードされたら再描画
			});
			return;
		}
	};
	Window_CharaVoice.prototype.maxCols = function () {
		return 6;
	};

	Window_CharaVoice.prototype.setItemWindow = function (itemWindow) {
		this._itemWindow = itemWindow;
	};

	Window_CharaVoice.prototype.makeCommandList = function () {
		for (e of this.v_list) {
			this.addCommand(e.name, e.id);
		}
	};
	Window_CharaVoice.prototype.colSpacing = function () {
		return 21;
	};
	Window_CharaVoice.prototype.itemHeight = function () {
		return 132;
	};
	Window_CharaVoice.prototype.drawItemBackground = function (index) {};
	Window_CharaVoice.prototype.itemRect = function (index) {
		const maxCols = this.maxCols();
		const itemHeight = this.itemHeight();
		const colSpacing = this.colSpacing();
		const rowSpacing = this.rowSpacing();
		const itemWidth = this.itemWidth();

		const col = index % maxCols;
		const row = Math.floor(index / maxCols);
		const x = col * itemWidth - this.scrollBaseX() + col * 4;
		const y = row * itemHeight + row * rowSpacing - this.scrollBaseY();
		const width = itemWidth - colSpacing;
		const height = itemHeight - rowSpacing;
		return new Rectangle(x, y, width, height);
	};

	// なし・1　→ On 2→off
	Window_CharaVoice.prototype.voice_toggle = function () {
		var idx = this.index();
		var d = this.v_list[idx];
		var val = $gameVariables.value(d.var);
		$gameVariables.setValue(d.var, val == 2 ? 1 : 2);

		AudioManager.stopVoice();
		AudioManager.playVoice({ name: `conf_voice_${d.id}_${val == 2 ? "on" : "off"}`, volume: 100, pitch: 100, pan: 0 });
	};

	Window_CharaVoice.prototype.processOk = function () {
		const index = this.index();

		SoundManager.playOk();
		this.voice_toggle();
		this.refresh();
	};

	Window_Command.prototype.callOkHandler = function () {
		const symbol = this.currentSymbol();
		if (this.isHandled(symbol)) {
			this.callHandler(symbol);
		} else if (this.isHandled("ok")) {
			Window_Selectable.prototype.callOkHandler.call(this);
		} else {
			this.activate();
		}
	};

	Window_OptionCategory.prototype.callOkHandler = function () {
		const symbol = this.currentSymbol();
		if (symbol == "key_pad") {
			SceneManager.push(Mano_InputConfig.Scene_KeyConfig);
		} else if (symbol == "game_pad") {
			SceneManager.push(Mano_InputConfig.Scene_GamepadConfig);
		} else {
			Window_Command.prototype.callOkHandler.call(this);
		}
	};

	Window_CharaVoice.prototype.drawItem = function (index) {
		this.contents.fontFace = "serif";
		this.contents.fontSize = 20;
		this.changeTextColor("#000000");

		const rect = this.itemLineRect(index);
		//const align = this.itemTextAlign();
		//this.resetTextColor();
		this.changePaintOpacity(this.isCommandEnabled(index));

		this.drawTextM(this.commandName(index), rect.x, rect.y + 48, rect.width, "left");
	};
	Window_CharaVoice.prototype.drawAllItems = function () {
		const topIndex = this.topIndex();
		for (let i = 0; i < this.maxVisibleItems(); i++) {
			const index = topIndex + i;
			if (index < this.maxItems()) {
				//this.drawItemBackground(index);
				this.drawItem(index);
			}
		}
		for (var i = 0; i < this.v_list.length; i++) {
			if (!$gameVariables.value(this.v_list[i].var) || $gameVariables.value(this.v_list[i].var) == 1) {
				this._toggleSprite[i].setFrame(0, 0, 166, 124);
			} else {
				this._toggleSprite[i].setFrame(0, 124, 166, 124);
			}
		}
	};
	Window_CharaVoice.prototype._createCursorSprite = function () {
		this._toggleSprite = [];
		for (var i = 0; i < this.v_list.length; i++) {
			this._toggleSprite[i] = [];

			this._toggleSprite[i] = new Sprite();
			this._toggleSprite[i].bitmap = ImageManager.loadSystem(`config_voice_toggle_${this.v_list[i].id}`);
			this._toggleSprite[i].y = Math.floor(i / 6) * 136;
			this._toggleSprite[i].x = (i % 6) * 190;
			this._toggleSprite[i].setFrame(0, 0, 155, 116);

			this._clientArea.addChild(this._toggleSprite[i]);
		}

		this._cursorSprite = new Sprite();
		for (let i = 0; i < 9; i++) {
			this._cursorSprite.addChild(new Sprite());
		}
		this._clientArea.addChild(this._cursorSprite);
	};
	//56×200にする
	Window_CharaVoice.prototype._refreshCursor = function () {
		const drect = this._cursorRect.clone();
		const srect = { x: 0, y: 0, width: 125, height: 24 };
		const m = 0;
		for (const child of this._cursorSprite.children) {
			child.bitmap = this.menu_cursor_skin;
		}
		//this._setRectPartsGeometry(this._cursorSprite, srect, drect, m);
	};
	Window_CharaVoice.prototype._updateCursor = function () {
		this._cursorSprite.alpha = this._makeCursorAlpha();
		this._cursorSprite.visible = this.isOpen() && this.cursorVisible;
		this._cursorSprite.x = this._cursorRect.x;
		this._cursorSprite.y = this._cursorRect.y + 100;
	};

	// メッセージ速度の反映
	Window_Message.prototype.updateMessage = function () {
		if (ConfigManager.msSpeed === 0) {
			if (this.meSpeed_flag) {
				this.meSpeed_flag = false;
				return true;
			} else {
				this.meSpeed_flag = true;
			}
		} else if (ConfigManager.msSpeed === 2) {
			this._showFast = true;
		}

		const textState = this._textState;
		if (textState) {
			while (!this.isEndOfText(textState)) {
				if (this.needsNewPage(textState)) {
					this.newPage(textState);
				}
				this.updateShowFast();
				this.processCharacter(textState);
				if (this.shouldBreakHere(textState)) {
					break;
				}
			}
			this.flushTextState(textState);
			if (this.isEndOfText(textState) && !this.isWaiting()) {
				this.onEndOfText();
			}
			return true;
		} else {
			return false;
		}
	};
})();

function Scene_Options_message() {
	this.initialize(...arguments);
}

function Window_Options_message() {
	this.initialize(...arguments);
}

Window_Options_message.prototype = Object.create(Window_Options.prototype);
Window_Options_message.prototype.constructor = Window_Options_message;

(function () {
	Scene_Options_message.prototype = Object.create(Scene_Options.prototype);
	Scene_Options_message.prototype.constructor = Scene_Options_message;

	Scene_Options_message.prototype.createOptionsWindow = function () {
		const rect = this.optionsWindowRect();
		this._itemWindow = new Window_Options_message(rect);
		this._itemWindow.setHandler("cancel", this.onItemCancel.bind(this));
		this.addWindow(this._itemWindow);
	};

	Window_Options_message.prototype.addGeneralOptions = function () {
		this.addCommand(TextManager.alwaysDash, "alwaysDash");
		this.addCommand(TextManager.commandRemember, "commandRemember");
		this.addCommand("Screen Effects", "screenEffects");
		this.addCommand("Battle Effects", "battleEffects");
		// this.addCommand("Event Battle Outcome Setting", "autoDefeat", true, "tri");
		// this.addCommand("Skip Previously Viewed H Scenes", "hSkip");
		// this.addCommand("Skip Childbirth Scenes", "birthSkip");
		// this.addCommand("Cross-section Display Setting During H Scenes", "danmenSkip");
		//this.addCommand(TextManager.touchUI, "touchUI");
	};

	Window_Options_message.prototype.addSystem_2Options = function () {
		this.addCommand("Message Window Transparency", "msOpacityVolume");
		this.addCommand("Message Speed", "msSpeed", true, "tri");
		this.addCommand("Auto Mode Speed", "autoMsSpeedVolume");
		// this.addCommand("Timed Choices", "selectLimit");
	};

	Window_Options_message.prototype.addVolumeOptions = function () {
		this.addCommand(TextManager.bgmVolume, "bgmVolume");
		this.addCommand("BGV Volume", "bgsVolume");
		this.addCommand(TextManager.seVolume, "seVolume");
		this.addCommand("Voice Volume", "meVolume");

		this.addCommand("Character Voice Settings", "charaVoice", true, "move");
	};
})();
