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

namespace TerraTech {
    [HarmonyPatch]
    public class MagnetPropertiesManager {
        private static Dictionary<ModuleItemHolderMagnet, float> strenghts = new Dictionary<ModuleItemHolderMagnet, float>();
        private static Dictionary<ModuleItemHolderMagnet, float> radii = new Dictionary<ModuleItemHolderMagnet, float>();

        [HarmonyPrefix]
        [HarmonyPatch(typeof(ModuleItemHolderMagnet), "OnAttached")]
        static void PostfixCreate(ModuleItemHolderMagnet __instance) {
            // Console.WriteLine("ModuleItemHolderMagnet.OnAttached");
            if (!strenghts.ContainsKey(__instance)) {
                strenghts.Add(__instance, GetStrength(__instance));
                radii.Add(__instance, GetRadius(__instance));
                // Console.WriteLine("Patching {0}; m_Strength: {1}; m_Pickup.m_PickupRange: {2}", __instance.name, GetStrength(__instance), GetRadius(__instance));
                DoPatchSingle(__instance);
                // Console.WriteLine("Patched {0}; m_Strength: {1}; m_Pickup.m_PickupRange: {2}", __instance.name, GetStrength(__instance), GetRadius(__instance));
            }
        }

        [HarmonyPrefix]
        [HarmonyPatch(typeof(ModuleItemHolderMagnet), "OnDetaching")]
        static void PostfixDestroy(ModuleItemHolderMagnet __instance) {
            // Console.WriteLine("ModuleItemHolderMagnet.OnDetaching");
            // Console.WriteLine("Restoring {0}; m_Strength: {1}; m_Pickup.m_PickupRange: {2}", __instance.name, GetStrength(__instance), GetRadius(__instance));
            DoRestoreSingle(__instance);
            // Console.WriteLine("Restored {0}; m_Strength: {1}; m_Pickup.m_PickupRange: {2}", __instance.name, GetStrength(__instance), GetRadius(__instance));
            strenghts.Remove(__instance);
            radii.Remove(__instance);
        }

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

        static void DoPatchSingle(ModuleItemHolderMagnet moduleItemHolderMagnet) {
            SetStrength(moduleItemHolderMagnet, strenghts[moduleItemHolderMagnet] * Main.magnetStrenghtMultiplier.Value);
            SetRadius(moduleItemHolderMagnet, radii[moduleItemHolderMagnet] * Main.magnetRadiusMultiplier.Value);
        }

        static void DoRestoreSingle(ModuleItemHolderMagnet moduleItemHolderMagnet) {
            if (strenghts.ContainsKey(moduleItemHolderMagnet)) {
                SetStrength(moduleItemHolderMagnet, strenghts[moduleItemHolderMagnet]);
            }
            if (radii.ContainsKey(moduleItemHolderMagnet)) {
                SetRadius(moduleItemHolderMagnet, radii[moduleItemHolderMagnet]);
            }
        }

        private static float GetStrength(ModuleItemHolderMagnet moduleItemHolderMagnet) {
            return Traverse.Create(moduleItemHolderMagnet).Field("m_Strength").GetValue() as float? ?? 0f;
        }

        private static void SetStrength(ModuleItemHolderMagnet moduleItemHolderMagnet, float value) {
            Traverse.Create(moduleItemHolderMagnet).Field("m_Strength").SetValue(value);
        }

        private static float GetRadius(ModuleItemHolderMagnet moduleItemHolderMagnet) {
            ModuleItemPickup moduleItemPickup = Traverse.Create(moduleItemHolderMagnet).Field("m_Pickup").GetValue() as ModuleItemPickup;
            if (moduleItemPickup) {
                float radius = Traverse.Create(moduleItemPickup).Field("m_PickupRange").GetValue() as float? ?? 0f;
                return radius;
            }
            return 0f;
        }

        private static void SetRadius(ModuleItemHolderMagnet moduleItemHolderMagnet, float value) {
            ModuleItemPickup moduleItemPickup = Traverse.Create(moduleItemHolderMagnet).Field("m_Pickup").GetValue() as ModuleItemPickup;
            if (moduleItemPickup) {
                Traverse.Create(moduleItemPickup).Field("m_PickupRange").SetValue(value);
            }
        }
    }
}