//=============================================================================
// RPGツクールMZ - LL_OutlineColorAuto.js v1.0.2 (Modified)
//-----------------------------------------------------------------------------
// ルルの教会 (Lulu's Church)
// https://nine-yusha.com/
//
// URL below for license details.
// https://nine-yusha.com/plugin/
//=============================================================================

/*:
 * @target MZ
 * @plugindesc Auto-detects and switches text outline color. (Modified: width, glow, on/off)
 * @author Lulu's Church (Modified)
 * @url https://nine-yusha.com/plugin-autooutlinecolor/
 *
 * @help LL_OutlineColorAuto.js
 *
 * Automatically determines and switches text outline color.
 * Uses black outline for light text, white for dark text.
 *
 * [Modified features]
 * - Added outline width parameter.
 * - Added glow mode (soft shadow instead of hard stroke).
 * - Added plugin commands to toggle outline on/off.
 *
 * About brightness threshold:
 * Higher value increases the range of "light" colors. (0-100)
 * * Setting to 100 makes all outlines white.
 *
 * Plugin Commands:
 *   outlineOn  - Enable outline display.
 *   outlineOff - Disable outline display.
 *
 * Terms of use:
 *   - No copyright notice required.
 *   - No report needed for use.
 *   - Free for commercial and non-commercial.
 *   - No restriction for adult works.
 *   - You may modify freely for your game.
 *   - Redistribution as plugin material (incl. modified) prohibited.
 *
 * Author: Lulu's Church
 * Date: 2021/8/1
 *
 * @param brightEvaluation
 * @text Brightness Threshold
 * @desc Threshold to treat text as light. (0-100, Default: 60)
 * Higher values increase detection range for white outlines.
 * @default 60
 * @min 0
 * @max 100
 * @type number
 *
 * @param outlineColorBlack
 * @text Outline Color (Black)
 * @desc Outline color for light text.
 * @default rgba(0, 0, 0, 0.6)
 * @type string
 *
 * @param outlineColorWhite
 * @text Outline Color (White)
 * @desc Outline color for dark text.
 * @default rgba(255, 255, 255, 0.9)
 * @type string
 *
 * @param outlineWidth
 * @text Outline Width
 * @desc Width of text outline. (Default: 4.0)
 * @default 4.0
 * @type number
 * @decimals 1
 *
 * @param outlineMode
 * @text Outline Mode
 * @desc Stroke = hard outline, Glow = soft shadow effect.
 * @default glow
 * @type select
 * @option Stroke (Hard)
 * @value stroke
 * @option Glow (Soft)
 * @value glow
 *
 * @param glowIntensity
 * @text Glow Intensity
 * @desc Number of draw passes in glow mode. Higher = stronger glow. (1-5, Default: 2)
 * @default 2
 * @min 1
 * @max 5
 * @type number
 *
 * @command outlineOn
 * @text Outline ON
 * @desc Enable outline display.
 *
 * @command outlineOff
 * @text Outline OFF
 * @desc Disable outline display.
 */

/*:ja
 * @target MZ
 * @plugindesc 文字の縁取り色を自動で判定して切替します。(改造版: 太さ・グロウ・ON/OFF)
 * @author ルルの教会 (改造版)
 * @url https://nine-yusha.com/plugin-autooutlinecolor/
 *
 * @help LL_OutlineColorAuto.js
 *
 * 文字の縁取り色を自動で判定して切替します。
 * 白に近い色の時は黒、黒に近い色の時は白で表示します。
 *
 * 【改造追加機能】
 * ・フチの太さをパラメータで変更可能。
 * ・グロウモード（ソフトなぼかし影）を追加。
 * ・プラグインコマンドでアウトラインのON/OFF切替が可能。
 *
 * 明度のしきい値について:
 *   数値を大きくすると白と判定される範囲が大きくなります。(0～100で調整)
 *   ※100にすると全ての縁取り色が白色になります。
 *
 * プラグインコマンド:
 *   アウトラインON  - アウトラインを有効にします。
 *   アウトラインOFF - アウトラインを無効にします。
 *
 * 利用規約:
 *   ・著作権表記は必要ございません。
 *   ・利用するにあたり報告の必要は特にございません。
 *   ・商用・非商用問いません。
 *   ・R18作品にも使用制限はありません。
 *   ・ゲームに合わせて自由に改変していただいて問題ございません。
 *   ・プラグイン素材としての再配布（改変後含む）は禁止させていただきます。
 *
 * 作者: ルルの教会
 * 作成日: 2021/8/1
 *
 * @param brightEvaluation
 * @text 明度のしきい値
 * @desc 縁取り色を白と判定するしきい値です。(0～100、初期: 60)
 * 数値を大きくすると白で表示される判定が大きくなります。
 * @default 60
 * @min 0
 * @max 100
 * @type number
 *
 * @param outlineColorBlack
 * @text 縁取り色(黒)
 * @desc 文字の縁取り色(黒)です。
 * @default rgba(0, 0, 0, 0.6)
 * @type string
 *
 * @param outlineColorWhite
 * @text 縁取り色(白)
 * @desc 文字の縁取り色(白)です。
 * @default rgba(255, 255, 255, 0.9)
 * @type string
 *
 * @param outlineWidth
 * @text フチの太さ
 * @desc 文字の縁取りの太さです。グロウモード時はぼかし半径になります。(デフォルト: 4.0)
 * @default 4.0
 * @type number
 * @decimals 1
 *
 * @param outlineMode
 * @text アウトラインモード
 * @desc Stroke=くっきりフチ、Glow=ソフトグロウ（ぼかし影）
 * @default glow
 * @type select
 * @option くっきりフチ (Stroke)
 * @value stroke
 * @option ソフトグロウ (Glow)
 * @value glow
 *
 * @param glowIntensity
 * @text グロウ強度
 * @desc グロウモード時の描画回数。大きいほど濃いグロウになります。(1～5、初期: 2)
 * @default 2
 * @min 1
 * @max 5
 * @type number
 *
 * @command outlineOn
 * @text アウトラインON
 * @desc アウトラインを有効にします。
 *
 * @command outlineOff
 * @text アウトラインOFF
 * @desc アウトラインを無効にします。
 */

(() => {
	"use strict";
	const pluginName = "LL_OutlineColorAuto";

	const parameters = PluginManager.parameters(pluginName);
	const brightEvaluation = Number(parameters["brightEvaluation"] || 60);
	const outlineColorBlack = String(parameters["outlineColorBlack"] || "rgba(0, 0, 0, 0.6)");
	const outlineColorWhite = String(parameters["outlineColorWhite"] || "rgba(255, 255, 255, 0.9)");
	const outlineWidth = Number(parameters["outlineWidth"] || 4);
	const outlineMode = String(parameters["outlineMode"] || "glow");
	const glowIntensity = Number(parameters["glowIntensity"] || 2);

	// -------------------------------------------------------
	// アウトライン ON/OFF 状態管理（セーブデータ対応）
	// -------------------------------------------------------
	const _Game_System_initialize = Game_System.prototype.initialize;
	Game_System.prototype.initialize = function() {
		_Game_System_initialize.apply(this, arguments);
		this._outlineEnabled = true;
	};

	Game_System.prototype.isOutlineEnabled = function() {
		if (this._outlineEnabled === undefined) this._outlineEnabled = true;
		return this._outlineEnabled;
	};

	Game_System.prototype.setOutlineEnabled = function(flag) {
		this._outlineEnabled = flag;
	};

	// -------------------------------------------------------
	// プラグインコマンド登録
	// -------------------------------------------------------
	PluginManager.registerCommand(pluginName, "outlineOn", () => {
		$gameSystem.setOutlineEnabled(true);
	});

	PluginManager.registerCommand(pluginName, "outlineOff", () => {
		$gameSystem.setOutlineEnabled(false);
	});

	// -------------------------------------------------------
	// ヘルパー関数
	// -------------------------------------------------------
	const getEffectiveOutlineWidth = function() {
		if (typeof $gameSystem !== "undefined" && $gameSystem && $gameSystem.isOutlineEnabled) {
			return $gameSystem.isOutlineEnabled() ? outlineWidth : 0;
		}
		return outlineWidth;
	};

	// 明度自動判定
	const getBright = function(color) {
		if (color.slice(0, 1) == "#") color = color.slice(1);
		if (color.length == 3) {
			color = color.slice(0, 1) + color.slice(0, 1) + color.slice(1, 2) + color.slice(1, 2) + color.slice(2, 3) + color.slice(2, 3);
		}
		const rgb = [color.slice(0, 2), color.slice(2, 4), color.slice(4, 6)].map(function(str) {
			return parseInt(str, 16);
		});
		return Math.max(rgb[0], rgb[1], rgb[2]) / 255;
	};

	// -------------------------------------------------------
	// グロウモード: Bitmap._drawTextOutline をオーバーライド
	// strokeText → shadowBlur + fillText に差し替え
	// -------------------------------------------------------
	if (outlineMode === "glow") {
		Bitmap.prototype._drawTextOutline = function(text, tx, ty, maxWidth) {
			const context = this.context;
			const effectiveWidth = getEffectiveOutlineWidth();
			if (effectiveWidth <= 0) return;

			context.save();
			// shadowでソフトグロウを表現
			context.shadowColor = this.outlineColor;
			context.shadowBlur = effectiveWidth;
			context.shadowOffsetX = 0;
			context.shadowOffsetY = 0;
			// strokeを無効化してshadowのみで描画
			context.lineWidth = 0;
			context.fillStyle = this.outlineColor;
			context.globalAlpha = 0.8;
			// 複数回描画でグロウを濃くする
			for (let i = 0; i < glowIntensity; i++) {
				context.fillText(text, tx, ty, maxWidth);
			}
			context.restore();
		};
	} else {
		// ストロークモード: 従来のstrokeTextにoutlineWidth適用
		const _Bitmap_drawTextOutline = Bitmap.prototype._drawTextOutline;
		Bitmap.prototype._drawTextOutline = function(text, tx, ty, maxWidth) {
			const effectiveWidth = getEffectiveOutlineWidth();
			if (effectiveWidth <= 0) return;
			this.outlineWidth = effectiveWidth;
			_Bitmap_drawTextOutline.apply(this, arguments);
		};
	}

	// -------------------------------------------------------
	// 自動色判定（Window_Base）
	// -------------------------------------------------------
	const _Window_Base_resetTextColor = Window_Base.prototype.resetTextColor;
	Window_Base.prototype.resetTextColor = function() {
		_Window_Base_resetTextColor.apply(this, arguments);
		this.changeOutlineColorAuto(ColorManager.normalColor());
	};

	const _Window_Base_changeTextColor = Window_Base.prototype.changeTextColor;
	Window_Base.prototype.changeTextColor = function(color) {
		_Window_Base_changeTextColor.apply(this, arguments, color);
		this.changeOutlineColorAuto(color);
	};

	Window_Base.prototype.changeOutlineColorAuto = function(color) {
		const bright = getBright(color) <= (brightEvaluation / 100);
		this.contents.outlineColor = !bright ? outlineColorBlack : outlineColorWhite;
		this.contents.outlineWidth = getEffectiveOutlineWidth();
	};

	// -------------------------------------------------------
	// Sprite系（ゲージ・名前）
	// -------------------------------------------------------
	Sprite_Gauge.prototype.labelOutlineColor = function() {
		const bright = getBright(this.labelColor()) <= (brightEvaluation / 100);
		return !bright ? outlineColorBlack : outlineColorWhite;
	};

	Sprite_Gauge.prototype.labelOutlineWidth = function() {
		return getEffectiveOutlineWidth();
	};

	Sprite_Gauge.prototype.valueOutlineColor = function() {
		const bright = getBright(this.valueColor()) <= (brightEvaluation / 100);
		return !bright ? "rgba(0, 0, 0, 1)" : outlineColorWhite;
	};

	Sprite_Gauge.prototype.valueOutlineWidth = function() {
		return getEffectiveOutlineWidth();
	};

	Sprite_Name.prototype.outlineColor = function() {
		const bright = getBright(this.textColor()) <= (brightEvaluation / 100);
		return !bright ? outlineColorBlack : outlineColorWhite;
	};

	Sprite_Name.prototype.outlineWidth = function() {
		return getEffectiveOutlineWidth();
	};
})();
