using ABI_RC.Core.Savior;
using ABI_RC.Systems.InputManagement;
using NAK.AvatarScaleMod.AvatarScaling;
using UnityEngine;

namespace NAK.AvatarScaleMod.GestureReconizer;

public static class ScaleReconizer
{
    public static bool Enabled = true;

    // Require triggers to be down while doing fist - Exteratta
    public static bool RequireTriggers = true;

    // Initial values when scale gesture is started
    private static float _initialModifier;
    private static float _initialTargetHeight;
    
    public static void Initialize()
    {
        // This requires arms far outward- pull inward with fist and triggers.
        // Release triggers while still holding fist to readjust.
        
        CVRGesture gesture = new CVRGesture
        {
            name = "avatarScaleIn",
            type = CVRGesture.GestureType.Hold
        };
        gesture.steps.Add(new CVRGestureStep
        {
            firstGesture = CVRGestureStep.Gesture.Fist,
            secondGesture = CVRGestureStep.Gesture.Fist,
            startDistance = 1f,
            endDistance = 0.25f,
            direction = CVRGestureStep.GestureDirection.MovingIn,
            needsToBeInView = true,
        });
        gesture.onStart.AddListener(OnScaleStart);
        gesture.onStay.AddListener(OnScaleStay);
        gesture.onEnd.AddListener(OnScaleEnd);
        CVRGestureRecognizer.Instance.gestures.Add(gesture);

        gesture = new CVRGesture
        {
            name = "avatarScaleOut",
            type = CVRGesture.GestureType.Hold
        };
        gesture.steps.Add(new CVRGestureStep
        {
            firstGesture = CVRGestureStep.Gesture.Fist,
            secondGesture = CVRGestureStep.Gesture.Fist,
            startDistance = 0.25f,
            endDistance = 1f,
            direction = CVRGestureStep.GestureDirection.MovingOut,
            needsToBeInView = true,
        });
        gesture.onStart.AddListener(OnScaleStart);
        gesture.onStay.AddListener(OnScaleStay);
        gesture.onEnd.AddListener(OnScaleEnd);
        CVRGestureRecognizer.Instance.gestures.Add(gesture);
    }

    private static void OnScaleStart(float modifier, Transform transform1, Transform transform2)
    {
        if (!Enabled)
            return;
        
        // Store initial modifier so we can get difference later
        _initialModifier = Mathf.Max(modifier, 0.01f); // no zero
        _initialTargetHeight = AvatarScaleManager.Instance.GetHeight();
    }

    private static void OnScaleStay(float modifier, Transform transform1, Transform transform2)
    {
        if (!Enabled)
            return;

        modifier = Mathf.Max(modifier, 0.01f); // no zero

        // Allow user to release triggers to reset "world grip"
        if (RequireTriggers && !AreBothTriggersDown())
        {
            _initialModifier = modifier;
            _initialTargetHeight = AvatarScaleManager.Instance.GetHeight();
            return;
        }
        
        // Invert so the gesture is more of a world squish instead of happy hug
        float modifierRatio = 1f / (modifier / _initialModifier);

        // Determine the adjustment factor for the height, this will be >1 if scaling up, <1 if scaling down.
        float heightAdjustmentFactor = (modifierRatio > 1) ? 1 + (modifierRatio - 1) : 1 - (1 - modifierRatio);

        // Apply the adjustment to the target height
        AvatarScaleManager.Instance.SetTargetHeight(_initialTargetHeight * heightAdjustmentFactor);
    }

    private static void OnScaleEnd(float modifier, Transform transform1, Transform transform2)
    {
        // Unused, needed for mod network?
    }
    
    private static bool AreBothTriggersDown()
    {
        // Maybe it should be one trigger? Imagine XSOverlay scaling but for player.
        return CVRInputManager.Instance.interactLeftValue > 0.75f && CVRInputManager.Instance.interactRightValue > 0.75f;
    }
}