using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using RimWorld;
using Verse;
using HarmonyLib;
using rjw;
using Verse.AI;

namespace SCE
{
    [HarmonyPatch]
    static class WorkGiver_InteractAnimal_ReduceNutritionRequiredByIdeo
    {
        public static IEnumerable<MethodBase> TargetMethods()
        {
            yield return AccessTools.Method(typeof(WorkGiver_InteractAnimal), "HasFoodToInteractAnimal");
            yield return AccessTools.Method(typeof(WorkGiver_InteractAnimal), "TakeFoodForAnimalInteractJob");
            yield return AccessTools.Method(typeof(WorkGiver_Tame), nameof(WorkGiver_Tame.JobOnThing));
        }

        public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase original)
        {
            MethodInfo requiredNutritionPerFeed = AccessTools.Method(typeof(JobDriver_InteractAnimal),
                                                    nameof(JobDriver_InteractAnimal.RequiredNutritionPerFeed));

            Type thisType = typeof(WorkGiver_InteractAnimal_ReduceNutritionRequiredByIdeo);

            bool patched = false;

            foreach (var instruction in instructions)
            {
                yield return instruction;

                if (instruction.Calls(requiredNutritionPerFeed))
                {
                    yield return new CodeInstruction(OpCodes.Ldarg_1);
                    yield return new CodeInstruction(OpCodes.Ldarg_2);
                    yield return CodeInstruction.Call(thisType, nameof(IdeoFactor));
                    yield return new CodeInstruction(OpCodes.Mul);
                    patched = true;
                }
            }

            if (!patched)
            {
                Log.Error($"SCE: Transpiler patch {thisType} failed to find a call to {requiredNutritionPerFeed.DeclaringType}:" +
                        $"{requiredNutritionPerFeed.Name} on {original.ReflectedType}:{original.Name}");
            }
        }

        private static float IdeoFactor(Pawn tamer, Pawn tamee)
        {
            if (BestialityUtility.CanDoLewdAnimalWork(tamer, tamee))
            {
                return 0.5f;
            }

            return 1f;
        }
    }

    [HarmonyPatch(typeof(WorkGiver_Tame), nameof(WorkGiver_Tame.JobOnThing))]
    static class WorkGiver_Tame_GiveLewdTameJobIfPossible
    {
        public static void Postfix(Job __result, Pawn pawn, Thing t)
        {
            if (__result?.def != JobDefOf.Tame)
            {
                return;
            }

            if (BestialityUtility.CanDoLewdAnimalWork(pawn, (Pawn)t))
            {
                __result.def = SCEJobDefOf.TameLewd_Feed;
            }
        }
    }

    [HarmonyPatch(typeof(WorkGiver_Train), nameof(WorkGiver_Train.JobOnThing))]
    static class WorkGiver_Train_GiveLewdTrainJobIfPossible
    {
        public static void Postfix(Job __result, Pawn pawn, Thing t)
        {
            if (__result?.def != JobDefOf.Train)
            {
                return;
            }
            if (BestialityUtility.CanDoLewdAnimalWork(pawn, (Pawn)t))
            {
                __result.def = SCEJobDefOf.TrainLewd_Feed;
            }
        }
    }
}