using HarmonyLib;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using UnityEngine;

public class MinEventActionOverrideZoomFOV : MinEventActionBase
{
    private int fov = 0;
    //private static Type zoomDataType = typeof(ItemActionZoom).GetNestedType("ItemActionDataZoom", System.Reflection.BindingFlags.NonPublic);
    //private static FieldInfo fldZoomInProgress = AccessTools.Field(zoomDataType, "bZoomInProgress");
    //private static FieldInfo fldTimeZoomStarted = AccessTools.Field(zoomDataType, "timeZoomStarted");
    //private static FieldInfo fldCurrentZoom = AccessTools.Field(zoomDataType, "CurrentZoom");
    //private static FieldInfo fldMaxZoomOut = AccessTools.Field(zoomDataType, "MaxZoomOut");
    //private static FieldInfo fldMaxZoomIn = AccessTools.Field(zoomDataType, "MaxZoomIn");
    //private static FieldInfo fldEndLerpFov = AccessTools.Field(typeof(EntityPlayerLocal), "lerpCameraEndFOV");
    //private static MethodInfo mtdUpdateCameraPosition = AccessTools.Method(typeof(EntityAlive), "updateCameraPosition");

    public override bool CanExecute(MinEventTypes _eventType, MinEventParams _params)
    {
        if (!base.CanExecute(_eventType, _params))
            return false;

        return _params.Self is EntityPlayerLocal player && player?.inventory != null && player.inventory.holdingItemData?.actionData[1] is ItemActionZoom.ItemActionDataZoom;
    }

    public override void Execute(MinEventParams _params)
    {
        base.Execute(_params);
        var target = (EntityPlayerLocal)_params.Self;
        var zoomActionData = (ItemActionZoom.ItemActionDataZoom)target.inventory.holdingItemData.actionData[1];
        int targetFov = fov;
        int targetMax = fov;
        int targetMin = fov;
        //restore min max fov
        if (fov <= 0)
        {
            float fovSetting = (float)GamePrefs.GetInt(EnumGamePrefs.OptionsGfxFOV);
            ItemAction action = target.inventory.holdingItem.Actions[1];
            if (action.Properties != null && action.Properties.Values.ContainsKey("Zoom_max_out"))
            {
                targetMax = StringParsers.ParseSInt32(target.inventory.holdingItemData.itemValue.GetPropertyOverride("Zoom_max_out", action.Properties.Values["Zoom_max_out"]), 0, -1, NumberStyles.Integer);
            }
            else
            {
                targetMax = StringParsers.ParseSInt32(target.inventory.holdingItemData.itemValue.GetPropertyOverride("Zoom_max_out", fovSetting.ToString()), 0, -1, NumberStyles.Integer);
            }
            if (action.Properties != null && action.Properties.Values.ContainsKey("Zoom_max_in"))
            {
                targetMin = StringParsers.ParseSInt32(target.inventory.holdingItemData.itemValue.GetPropertyOverride("Zoom_max_in", action.Properties.Values["Zoom_max_in"]), 0, -1, NumberStyles.Integer);
            }
            else
            {
                targetMin = StringParsers.ParseSInt32(target.inventory.holdingItemData.itemValue.GetPropertyOverride("Zoom_max_in", fovSetting.ToString()), 0, -1, NumberStyles.Integer);
            }
            targetFov = targetMax;
        }

        zoomActionData.MaxZoomIn = targetMin;
        zoomActionData.MaxZoomOut = targetMax;
        zoomActionData.CurrentZoom = targetFov;
        //Log.Out($"setting zoom override max {targetMax} min {targetMin} cur {targetFov}");
        //if is aiming, lerp towards the final result
        if (target.AimingGun)
        {
            //if lerp not in progress, start lerp
            if (!target.bLerpCameraFlag)
            {
                zoomActionData.bZoomInProgress = true;
                zoomActionData.timeZoomStarted = Time.time;
                target.updateCameraPosition(true);
            }
            //if already in progress, set end value
            else
            {
                target.lerpCameraEndFOV = targetFov;
            }

            //Log.Out($"begin lerp camera");
        }
    }

    public override bool ParseXmlAttribute(XAttribute _attribute)
    {
        if(base.ParseXmlAttribute(_attribute))
            return true;

        switch(_attribute.Name.LocalName)
        {
            case "value":
                fov = StringParsers.ParseSInt32(_attribute.Value);
                return true;
        }
        return false;
    }
}
