using System;
using System.Collections.Generic;
using HarmonyLib;

namespace TerraTech {
    [HarmonyPatch]
    public class MinerPropertiesManager {
        private static Dictionary<ModuleItemProducer, float> area = new Dictionary<ModuleItemProducer, float>();
        private static Dictionary<ModuleItemProducer, float> speed = new Dictionary<ModuleItemProducer, float>();

        [HarmonyPrefix]
        [HarmonyPatch(typeof(ModuleItemProducer), "GetClosestResourceReservoirInRange")]
        static void PostfixCreate(ModuleItemProducer __instance) {
            // Console.WriteLine("ModuleItemProducer.GetClosestResourceReservoirInRange");
            if (!area.ContainsKey(__instance)) {
                area.Add(__instance, GetArea(__instance));
                speed.Add(__instance, GetSpeed(__instance));
                // Console.WriteLine("Patching {0}; m_ResourceGroundRadius: {1}; m_SecPerItemProduced: {2}", __instance.name, GetArea(__instance),
                // GetSpeed(__instance));
                DoPatchSingle(__instance);
                // Console.WriteLine("Patched {0}; m_ResourceGroundRadius: {1}; m_SecPerItemProduced: {2}", __instance.name, GetArea(__instance),
                // GetSpeed(__instance));
            } else {
                if (GetArea(__instance) == area[__instance]) {
                    // Console.WriteLine("{0} area reset, patching again... m_ResourceGroundRadius: {1}; m_SecPerItemProduced: {2}", __instance.name,
                    // GetArea(__instance), GetSpeed(__instance));
                    DoPatchSingle(__instance);
                    // Console.WriteLine("Patched {0}; m_ResourceGroundRadius: {1}; m_SecPerItemProduced: {2}", __instance.name, GetArea(__instance),
                    //  GetSpeed(__instance));
                }
                if (GetSpeed(__instance) == speed[__instance]) {
                    // Console.WriteLine("{0} speed reset, patching again... m_ResourceGroundRadius: {1}; m_SecPerItemProduced: {2}", __instance.name,
                    // GetArea(__instance), GetSpeed(__instance));
                    DoPatchSingle(__instance);
                    // Console.WriteLine("Patched {0}; m_ResourceGroundRadius: {1}; m_SecPerItemProduced: {2}", __instance.name, GetArea(__instance),
                    // GetSpeed(__instance));
                }
            }
        }

        [HarmonyPostfix]
        [HarmonyPatch(typeof(ModuleItemProducer), "OnDetaching")]
        static void PostfixDestroy(ModuleItemProducer __instance) {
            // Console.WriteLine("ModuleItemProducer.OnRecycle");
            DoRestoreSingle(__instance);
            area.Remove(__instance);
            speed.Remove(__instance);
        }

        public static void DoPatch() {
            // Console.WriteLine("Modifying {0} ModuleItemProducer", area.Count);
            foreach (KeyValuePair<ModuleItemProducer, float> keyValuePair in area) {
                DoRestoreSingle(keyValuePair.Key);
                DoPatchSingle(keyValuePair.Key);
            }
        }

        static void DoPatchSingle(ModuleItemProducer moduleItemProducer) {
            SetArea(moduleItemProducer, area[moduleItemProducer] * Main.minerGroundArea.Value);
            SetSpeed(moduleItemProducer, speed[moduleItemProducer] / Main.minerMiningSpeed.Value);
        }

        static void DoRestoreSingle(ModuleItemProducer moduleItemProducer) {
            if (area.ContainsKey(moduleItemProducer)) {
                SetArea(moduleItemProducer, area[moduleItemProducer]);
                SetSpeed(moduleItemProducer, speed[moduleItemProducer]);
            }
        }

        private static float GetArea(ModuleItemProducer moduleItemProducer) {
            return Traverse.Create(moduleItemProducer).Field("m_ResourceGroundRadius").GetValue() as float? ?? 0f;
        }

        private static void SetArea(ModuleItemProducer moduleItemProducer, float value) {
            Traverse.Create(moduleItemProducer).Field("m_ResourceGroundRadius").SetValue(value);
        }

        private static float GetSpeed(ModuleItemProducer moduleItemProducer) {
            return Traverse.Create(moduleItemProducer).Field("m_SecPerItemProduced").GetValue() as float? ?? 0f;
        }

        private static void SetSpeed(ModuleItemProducer moduleItemProducer, float value) {
            Traverse.Create(moduleItemProducer).Field("m_SecPerItemProduced").SetValue(value);
        }
    }
}