using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using BepInEx.Harmony;
using ChaCustom;
using HarmonyLib;
using Illusion.Game;
using Object = UnityEngine.Object;
namespace KKAPI.Maker
{
///
/// API for modifying the process of saving cards in maker.
///
public static class MakerCardSave
{
private static readonly Harmony _harmony;
static MakerCardSave()
{
_harmony = new Harmony(nameof(MakerCardSave));
HarmonyWrapper.PatchAll(typeof(MakerCardSave), _harmony);
}
///
/// Used for modifying card save paths. Parameter is the original path, return the changed path.
///
public delegate string DirectoryPathModifier(string currentDirectoryPath);
///
/// Used for modifying card file names. Parameter is the original name, return the changed name.
///
public delegate string CardNameModifier(string currentCardName);
private static readonly List> _modifiers = new List>();
///
/// Add a function that can modify the path of the saved cards.
/// Use sparingly and insert/replace parts of the path instead of overwriting the whole path to keep compatibility with other plugins.
///
/// Modifier for the directory the card is saved to. Set to null if no change is required.
/// Modifier for the name the card file itself. Set to null if no change is required.
public static void RegisterNewCardSavePathModifier(DirectoryPathModifier directoryPathModifier, CardNameModifier filenameModifier)
{
_modifiers.Add(new KeyValuePair(directoryPathModifier, filenameModifier));
}
[HarmonyTranspiler, HarmonyPatch(typeof(CustomControl), "Start")]
internal static IEnumerable FindSaveMethod(IEnumerable instructions)
{
var codes = instructions.ToList();
bool buttonFound = false;
for (int i = 0; i < codes.Count; i++)
{
var code = codes[i];
if (!buttonFound && code.opcode == OpCodes.Ldfld && code.operand == AccessTools.Field(typeof(CustomControl), "btnSave"))
buttonFound = true;
if (buttonFound)
{
if (code.opcode == OpCodes.Ldftn)
{
if (code.operand is MethodInfo methodInfo)
{
var patchMethod = AccessTools.Method(typeof(MakerCardSave), nameof(CardSavePatch));
_harmony.Patch(methodInfo, new HarmonyMethod(patchMethod));
KoikatuAPI.Logger.LogDebug("Save method found for patching MakerCardSave - " + methodInfo.Name);
}
break;
}
}
}
return codes;
}
private static bool CardSavePatch(CustomControl __instance)
{
if (!MakerAPI.InsideMaker || !_modifiers.Any(x => x.Key != null || x.Value != null)) return true;
try
{
Utils.Sound.Play(SystemSE.ok_s);
var instanceChaCtrl = Singleton.Instance.chaCtrl;
var isMale = instanceChaCtrl.sex == 0;
var folder = UserData.Path + (isMale ? "chara/male/" : "chara/female/");
var fileName = __instance.saveNew ?
#if KK
$"Koikatu_{(isMale ? "M" : "F")}_{DateTime.Now:yyyyMMddHHmmssfff}"
#elif EC
$"Emocre_{(isMale ? "M" : "F")}_{DateTime.Now:yyyyMMddHHmmssfff}"
#endif
: __instance.saveFileName;
foreach (var kvp in _modifiers)
{
if (kvp.Key != null)
folder = kvp.Key(folder);
// Keep old filename if not saving as new file
if (kvp.Value != null && __instance.saveNew)
fileName = kvp.Value(fileName);
}
var fullPath = Path.Combine(folder, fileName);
instanceChaCtrl.chaFile.SaveCharaFile(fullPath);
if (__instance.saveFileListCtrl != null)
{
var listCtrl = Object.FindObjectOfType();
if (listCtrl != null)
RefreshThumbs(listCtrl);
}
__instance.saveMode = false;
return false;
}
catch (Exception ex)
{
KoikatuAPI.Logger.LogError(ex);
return true;
}
}
private static void RefreshThumbs(CustomCharaFile listCtrl)
{
var traverse = Traverse.Create(listCtrl);
// KKP - private bool Initialize(bool isDefaultDataAdd, bool reCreate)
var target = traverse.Method("Initialize", true, false);
if (target.MethodExists())
target.GetValue();
else
// KK/EC - private bool Initialize()
traverse.Method("Initialize").GetValue();
}
}
}