/*:
 * @plugindesc Allows for images in the Faces folder to be dynamically swapped out. 
 * Version 2.0
 * @author TomatoRadio
 * 
 * @help
 * =========================================================
 * FACESET GROUPS
 * =========================================================
 * FacesetGroups allow for faces to be changed with a Control Variable.
 * When a Faceset in a FacesetGroup is loaded, it checks the value of the Variable of the group,
 * and suffixes it at the end of the name.
 * Example: 
 * PRL_DW_AUBREY in FacesetGroup 1
 * FacesetGroup 1 Variable is 45
 * Variable 45 = 12
 * The game will call for PRL_DW_AUBREY12
 * 
 * =========================================================
 * EQUIPMENT AND STATES
 * =========================================================
 * Weapons, Charms, and States can now also change faces.
 * For States, KOFFIN_RefreshBattleSprites is advised and must be above this plugin in order to allow you to refresh the battle faces.
 * 
 * <Suffix: string> 
 * This will be suffixed to the end of a faceset's name on load.
 * The order of name suffixxing goes [FacesetGroup, Weapon, Charm, States in ID order]
 * The notetag will automatically add an underscore to the front of the suffix, so keep that in mind.
 * Example:
 * PRL_DW_KIM (normal)
 * PRL_DW_KIM3_Knife_Helmet_AtkUp2_Burning (Suffixed)
 * 
 * <IgnoreActors: actorID, actorID, actorID> 
 * The suffix will not be applied to any of these actors.
 * 
 * <IgnoreWeapons: weaponID, weaponID, weaponID>
 * The suffix will not be applied to the actor if any of these weapons are equipped.
 * 
 * <IgnoreCharms: charmID, charmID, charmID>
 * The suffix will not be applied to the actor is any of these charms are equipped.
 * 
 * =========================================================
 * GIRLMORI IS REAL
 * =========================================================
 * If you are using another one of my plugins, TR_GIRLMORI_IS_REAL, then be aware that the '_girl' suffix is placed after ALL of these.
 * 
 * =========================================================
 * TERMS OF USE & CONTACT INFO
 * =========================================================
 * This plugin is free to use for any purpose with or without credit, though credit would be appreciated.
 * If you are having issues with the plugin, you may ping me in the Omori Modding Hub Discord Server at 'tomatoradio'
 * 
 * 
 * @param FacesetGroup1
 * @text Faceset Group 1
 * @type []
 * @desc All of the facesets in Faceset Group 1
 * @parent ---Faceset Group 1---
 * @default ["FaceName","FaceName","FaceName"]
 * 
 * @param FacesetGroup1Var
 * @text Faceset Group 1 Variable
 * @desc The ID of the variable that determines the alt faceset.
 * @parent FacesetGroup1
 * @default 45
 * 
 * @param FacesetGroup2
 * @text Faceset Group 2
 * @type []
 * @desc All of the facesets in Faceset Group 2
 * @parent ---Faceset Group 2---
 * @default ["FaceName","FaceName","FaceName"]
 * 
 * @param FacesetGroup2Var
 * @text Faceset Group 2 Variable
 * @desc The ID of the variable that determines the alt faceset.
 * @parent FacesetGroup2
 * @default 46
 * 
 * @param FacesetGroup3
 * @text Faceset Group 3
 * @type []
 * @desc All of the facesets in Faceset Group 3
 * @parent ---Faceset Group 3---
 * @default ["FaceName","FaceName","FaceName"]
 * 
 * @param FacesetGroup3Var
 * @text Faceset Group 3 Variable
 * @desc The ID of the variable that determines the alt faceset.
 * @parent FacesetGroup3
 * @default 47
 * 
 * @param FacesetGroup4
 * @text Faceset Group 4
 * @type []
 * @desc All of the facesets in Faceset Group 4
 * @default ["FaceName","FaceName","FaceName"]
 * 
 * @param FacesetGroup4Var
 * @text Faceset Group 4 Variable
 * @desc The ID of the variable that determines the alt faceset.
 * @parent FacesetGroup4
 * @default 48
 * 
 * @param vbfActors
 * @text VBF Actors
 * @type []
 * @desc The ID of every actor that uses equip or state changes.
 * @default ["1","2","3","4"]
 * 
 * @param vbfActorsFaces
 * @text VBF Actors Faces
 * @type []
 * @desc The DIALOGUE face of every actor from the above list. Use the same order.
 * @parent vbfActors
 * @default ["01_OMORI_BATTLE","02_AUBREY_BATTLE","03_KEL_BATTLE","04_HERO_BATTLE"]
 * 
 * @param UseFacesetGroups
 * @text Use Faceset Groups?
 * @type boolean
 * @desc If ON, faceset groups will be checked. For optimization please turn OFF any of these you don't use.
 * @default false
 * 
 * @param UseEquipmentChanges
 * @text Use Equipment Changes?
 * @type boolean
 * @desc If ON, equipment will change faces.
 * @default false
 * 
 * @param UseStateChanges
 * @text Use State Changes?
 * @type boolean
 * @desc If ON, states will change faces. Reccomendded KOFFIN_RefreshBattleSprites
 * @default false
 * 
 * @param AffectMenuAndBattle
 * @text Affect Menu & Battle Portraits?
 * @type boolean
 * @desc If ON, Battle and Menu Portraits will also be affected by Equipment and State changes.
 * @default false
 * 
 * @param ConsoleLog
 * @text Log To Console?
 * @type boolean
 * @desc If ON, then the game will log rather verbose amounts of info to the console about this plugin.
 * @default false
 */

//Import Info
var Imported = Imported || {};
Imported.TR_VBF = true;
Imported.TR_VariableBasedFacesets = true;

var TR = TR || {};
TR.VBF = TR.VBF || {};

//Param Defining
TR.VBF.Param = PluginManager.parameters('TR_VariableBasedFacesetsV2');

TR.FacesetGroup1 = JSON.parse(TR.VBF.Param["FacesetGroup1"])
TR.FacesetGroup1Var = Math.floor(Number(TR.VBF.Param["FacesetGroup1Var"] || 0))

TR.FacesetGroup2 = JSON.parse(TR.VBF.Param["FacesetGroup2"])
TR.FacesetGroup2Var = Math.floor(Number(TR.VBF.Param["FacesetGroup2Var"] || 0))

TR.FacesetGroup3 = JSON.parse(TR.VBF.Param["FacesetGroup3"])
TR.FacesetGroup3Var = Math.floor(Number(TR.VBF.Param["FacesetGroup3Var"] || 0))

TR.FacesetGroup4 = JSON.parse(TR.VBF.Param["FacesetGroup4"])
TR.FacesetGroup4Var = Math.floor(Number(TR.VBF.Param["FacesetGroup4Var"] || 0))

TR.vbfActors = (JSON.parse(TR.VBF.Param["vbfActors"])).map((x) => parseInt(x))
TR.vbfActorsFaces = JSON.parse(TR.VBF.Param["vbfActorsFaces"])

TR.UseFacesetGroups = eval(TR.VBF.Param["UseFacesetGroups"])
TR.UseEquipmentChanges = eval(TR.VBF.Param["UseEquipmentChanges"])
TR.UseStateChanges = eval(TR.VBF.Param["UseStateChanges"])

TR.AffectMenuAndBattle = eval(TR.VBF.Param["AffectMenuAndBattle"])

TR.ConsoleLog = eval(TR.VBF.Param["ConsoleLog"])

ImageManager.UseStateChanges = function() {
	if (PluginManager._scripts.includes("KOFFIN_RefreshBattleSprites")) {
		//do nothing skill lmao
	} else { 
		if (TR.ConsoleLog) { console.log(`ImageManager.UseStateChanges: KOFFIN_RefreshBattleSprites not found. Bugs may be present.`); }
	}
	if (TR.UseStateChanges) {
		return true;
	} else { 
		return false;
	}
};

ImageManager.vbfGroupSet = function(filename) {
	let group = 0
	if (TR.FacesetGroup1.includes(filename)) {
		group = 1
	} else if (TR.FacesetGroup2.includes(filename)) {
		group = 2
	} else if (TR.FacesetGroup3.includes(filename)) {
		group = 3
	} else if (TR.FacesetGroup4.includes(filename)) {
		group = 4
	};
	if (TR.ConsoleLog) { console.log(`ImageManager.vbfGroupSet: ${filename} found as part of Group ${group}.`); }
	let suffix = 0
	switch (group) {
		case 0:
			suffix = 0
			break;
		case 1:
			suffix = $gameVariables.value(TR.FacesetGroup1Var);
			break;
		case 2:
			suffix = $gameVariables.value(TR.FacesetGroup2Var);
			break;
		case 3:
			suffix = $gameVariables.value(TR.FacesetGroup3Var);
			break;
		case 4:
			suffix = $gameVariables.value(TR.FacesetGroup4Var);
			break;
	};
	if (TR.ConsoleLog) { console.log(`ImageManager.vbfGroupSet: Group ${group} has a current value of ${suffix}.`); }
	if (suffix === 0) { 
		suffix = ''; 
		if (TR.ConsoleLog) { console.log(`ImageManager.vbfGroupSet: Suffix of 0 detected. Group Name is cleared.`); }
	};
	return suffix;
	};

ImageManager.vbfActorSet = function(faceName) {
	if (TR.vbfActorsFaces.includes(faceName)) {
		var FaceArrayPairing = (element) => element === faceName;
		let index = TR.vbfActorsFaces.findIndex(FaceArrayPairing)
		let id = TR.vbfActors[index]
		if (TR.ConsoleLog) { console.log(`ImageManager.vbfActorSet: ${faceName} has been found at Index ${index} and assigned to Actor ${id}.`); }
		return id;
	} else {
		if (TR.ConsoleLog) { console.log(`ImageManager.vbfActorSet: ${faceName} has no reference in the Actor Set.`); }
		return 0;
	}
}

ImageManager.vbfEquipName = function(actor, filename) {
	if (TR.ConsoleLog) { console.log(`ImageManager.vbfEquipName: ${actor}.`); }
	let weapon = $gameActors.actor(actor).weapons()[0];
	let charm = $gameActors.actor(actor).armors()[0];
	let states = $gameActors.actor(actor).states();
	if (TR.ConsoleLog) { console.log(`ImageManger.vbfEquipName: `+$gameActors.actor(actor).name()+` is equipped with `+charm+` and `+weapon+` and affected by `+states+`.`); }
			if (weapon === undefined) { weapon = $dataWeapons[1]; };
			if (charm === undefined) { charm = $dataArmors[1]; };
			if (weapon === $dataWeapons[1] && charm === $dataArmors[1]) { 
				if (TR.ConsoleLog) { console.log(`ImageManger.vbfEquipName: `+$gameActors.actor(actor).name()+` has no equips.`); }
				return '';
			};
	let WIgnoreActors = weapon.meta.IgnoreActors === undefined ? Array('InVaLiD') : ImageManager.vbfProcessRange(weapon.meta.IgnoreActors)
	let CIgnoreActors = charm.meta.IgnoreActors === undefined ? Array('InVaLiD') : ImageManager.vbfProcessRange(charm.meta.IgnoreActors)
	let IgnoreCharms = weapon.meta.IgnoreCharms === undefined ? Array('InVaLiD') : ImageManager.vbfProcessRange(weapon.meta.IgnoreCharms)
	let IgnoreWeapons = charm.meta.IgnoreWeapons === undefined ? Array('InVaLiD') : ImageManager.vbfProcessRange(charm.meta.IgnoreWeapons)
	//let WIgnoreStates = weapon.meta.IgnoreStates === undefined ? Array('InVaLiD') : ImageManager.vbfProcessRange(weapon.meta.IgnoreStates)
	//let CIgnoreStates = weapon.meta.IgnoreStates === undefined ? Array('InVaLiD') : ImageManager.vbfProcessRange(weapon.meta.IgnoreStates)
	//States are currently dummied out until a better system for these checks is made.
	if (TR.ConsoleLog) { console.log(`ImageManger.vbfEquipName: WeaponIgnoreActors: ${WIgnoreActors} CharmIgnoreActors: ${CIgnoreActors} IgnoreCharms: ${IgnoreCharms} IgnoreWeapons: ${IgnoreWeapons}`); }
		let wname = ''
		let cname = ''
			if ((!WIgnoreActors.includes(actor.toString()) && !IgnoreCharms.includes(charm.toString()) /*&& !WIgnoreStates.some((Element), states.includes(Element))*/) && (weapon.meta.Suffix)) {
				wname = `_${weapon.meta.Suffix.trim()}`;
			}
			if ((!CIgnoreActors.includes(actor.toString()) && !IgnoreWeapons.includes(weapon.toString()) /*&& !CIgnoreStates.some((x), states.includes(x))*/) && (charm.meta.Suffix)) {
				cname = `_${charm.meta.Suffix.trim()}`;
			}
		if (TR.ConsoleLog) { console.log(`ImageManger.vbfEquipName: ${wname}${cname}`); }
		return `${wname}${cname}`;
};

ImageManager.vbfProcessRange = function(string) {
	let str2 = string.replace(' ', '');
	let array = str2.split(',')
	return array;
}
ImageManager.vbfStateName = function(actor, filename) {
	let weapon = $gameActors.actor(actor).weapons()[0];
	let charm = $gameActors.actor(actor).armors()[0];
	let states = $gameActors.actor(actor).states();
	if (TR.ConsoleLog) { console.log(`ImageManger.vbfStateName: `+$gameActors.actor(actor).name()+` has states ${states}`); }
	let IgnoreActors = Array('InVaLiD')
	let IgnoreCharms = Array('InVaLiD')
	let IgnoreWeapons = Array('InVaLiD')
	//let IgnoreStates = Array('InVaLiD')
	let state = $dataStates[0]
	var array = Array()
	for (let i = 1; i < states.length; i++) {
		state = states[i]
		IgnoreActors = state.meta.IgnoreActors === undefined ? Array('InVaLiD') : ImageManager.vbfProcessRange(state.meta.IgnoreActors)
		IgnoreCharms = state.meta.IgnoreCharms === undefined ? Array('InVaLiD') : ImageManager.vbfProcessRange(state.meta.IgnoreCharms)
		IgnoreWeapons = state.meta.IgnoreWeapons === undefined ? Array('InVaLiD') : ImageManager.vbfProcessRange(state.meta.IgnoreWeapons)
		//IgnoreStates = state.meta.IgnoreStates === undefined ? Array('InVaLiD') : ImageManager.vbfProcessRange(state.meta.IgnoreStates)
		if (TR.ConsoleLog) { console.log(`ImageManger.vbfStateName: IgnoreActors: ${IgnoreActors} IgnoreCharms: ${IgnoreCharms} IgnoreWeapons: ${IgnoreWeapons}`); }
		if ((!IgnoreActors.includes(actor.toString()) && !IgnoreCharms.includes(charm.toString()) && !IgnoreWeapons.includes(weapon.toString()) /*&& !IgnoreStates.some((x), states.includes(x))*/) && (states[i].meta.Suffix)) {
			array.push(`_${states[i].meta.Suffix.trim()}`)
		}
	}
	return array;
}
Game_Message.prototype.setFaceImage = function(faceName, faceIndex) {
	//Group Check, if the group is 0 (no group) then stay blank
	let group = ''
	let ename = ''
	let sname = ''
	if (TR.UseFacesetGroups) { group = ImageManager.vbfGroupSet(faceName); };
	
	//ActorFace Check
	let actor = parseInt(ImageManager.vbfActorSet(faceName));
	if (TR.ConsoleLog) { console.log(`Game_Message.setFaceImage: Actor has been evaled as ${actor}.`); }

	if (actor > 0) {
		if (TR.UseEquipmentChanges) { ename = ImageManager.vbfEquipName(actor, faceName); };
		if (ImageManager.UseStateChanges) { sname = ImageManager.vbfStateName(actor, faceName); };
	};
	let newname = `${faceName}${group}${ename}${sname}`
	if (TR.ConsoleLog) { console.log(`Game_Message.setFaceImage: ${faceName} converted to ${newname}.`); }
    this._faceName = newname;
    this._faceIndex = faceIndex;
};

Game_Actor.prototype.battleStatusFaceName = function() {
	let faceName = this.actor().meta.BattleStatusFaceName.trim()
	if (faceName === undefined) { return; }
	if (!TR.AffectMenuAndBattle) { return faceName; }
	faceIndex = -1
  	//Group Check, if the group is 0 (no group) then stay blank
	let group = ''
	let ename = ''
	let sname = ''
  	if (TR.UseFacesetGroups) { group = ImageManager.vbfGroupSet(faceName); };
	
	if (TR.vbfActors.includes(this.actorId())) {
		let actor = this.actorId();
		if (TR.UseEquipmentChanges) { ename = ImageManager.vbfEquipName(actor, faceName); };
		if (ImageManager.UseStateChanges) { sname = ImageManager.vbfStateName(actor, faceName); };
	};
	let newname = `${faceName}${group}${ename}${sname}`
	if (TR.ConsoleLog) { console.log(`Game_Actor.battleStatusFaceName: ${faceName} converted to ${newname}.`); }
  return newname;
};

Game_Actor.prototype.menuStatusFaceName = function() {
	let faceName = this.actor().meta.MenuStatusFaceName
	if (faceName === undefined) { 
		return; 
	} else { 
		faceName = faceName.trim();
	}
	if (!TR.AffectMenuAndBattle) { return faceName; }
	faceIndex = -1
  	//Group Check, if the group is 0 (no group) then stay blank
	let group = ''
	let ename = ''
	let sname = ''
  	if (TR.UseFacesetGroups) { group = ImageManager.vbfGroupSet(faceName); };
	
	if (TR.vbfActors.includes(this.actorId())) {
		let actor = this.actorId();
		if (TR.UseEquipmentChanges) { ename = ImageManager.vbfEquipName(actor, faceName); };
		if (ImageManager.UseStateChanges) { sname = ImageManager.vbfStateName(actor, faceName); };
	};
	let newname = `${faceName}${group}${ename}${sname}`
	if (TR.ConsoleLog) { console.log(`Game_Actor.menuStatusFaceName: ${faceName} converted to ${newname}.`); }
  return newname;
};