using System;
using System.Collections;
using System.Data;
using System.Linq;
using Unity.VisualScripting;
using UnityEditor;
using UnityEngine;


[Serializable]
public class PlayerJumpHandler {
  private Player Player;
  public Transform Transform;
  private Vector2 Position => Transform.position;


  [Header("FakeZ and Jump Attributes")]
  public float GroundFakeZ = 0;
  public float CurrentFakeZ = 0;
  public float Height = 2.5f;
  public float AirTime = 0.7f;
  public float FreeFallSpeedPerSec = 13.5f;
  public bool Active { get; set; }
  public bool Paused { get; set; }
  public bool IsFalling => TimeElapsedNormalized > 0.5;
  public bool IsFreeFalling => TimeElapsedNormalized > 1;
  public float LastJump { get; private set; }
  public float PauseTimeStamp { get; private set; }
  public float PauseTime { get; private set; } = 0;
  public float TimeElapsedNormalized => (Time.time - LastJump) / AirTime;
  public float TimeLeftNormalized => 1 - TimeElapsedNormalized;
  public bool IsNonBlocking => !Active || (Time.time - LastJump > 0.03f);

  private int JumpCount = 0;
  private float Yref = 0;

  [Header("Jump Curve Parameters")]
  public float a = 1.2f;
  public float b = 1.4f;
  public float c = 1;



  public PlayerJumpHandler(Player player) {
    Player = player;
    Transform = player.transform.Find("Visuals").Find("CharacterPos");
    player.DoUpdate += SetHeight;
  }


  private void SetHeight() {
    if (!Active || Paused) return;

    if (!IsFreeFalling) {
      var shift = (TimeElapsedNormalized < 0.5) ? 0 : AirTime;
      var elapsed = Math.Abs(TimeElapsedNormalized * AirTime - shift) / (AirTime / 2);
      var min = Math.Min(elapsed, 1);
      var t = Math.Max(min, 0);
      var u = 1 - t;
      var h1 = 4 * u * u * u * t * a;
      var h2 = 4 * u * u * t * t * b;
      var h3 = 4 * u * t * t * t * c;
      var h4 = t * t * t * t;
      var h = (Height * (h1 + h2 + h3 + h4)) / JumpCount + GroundFakeZ + Yref;
      CurrentFakeZ = h;
    } else {
      Yref -= (TimeElapsedNormalized - 1) * FreeFallSpeedPerSec;
      if (Yref < 0) Yref = 0;
      CurrentFakeZ = Yref;
    }

    if (TimeLeftNormalized <= 0 && Yref == 0)
      Stop();
    else
      SetTransformYPos(CurrentFakeZ);
  }

  public void Pause() {
    if (!Active) return;
    PauseTimeStamp = Time.time;
    Paused = true;
  }

  public void Unpause() {
    if (!Active) return;
    PauseTime = Time.time - PauseTimeStamp;
    LastJump = Time.time - (AirTime * TimeLeftNormalized);
    Paused = false;
  }

  public void Start() {
    if (JumpCount++ > 2) return;
    if (Player.SkillInUse) return;

    if (JumpCount > 1) {
      var pos = Player.transform.position;
      pos.y += Transform.localPosition.y - 0.7f;
      Player.VfxAirJumpPool.Get(pos);
    }

    Yref = Transform.localPosition.y;
    Active = true;
    LastJump = Time.time;
    PauseTime = 0;
  }

  public void Stop() {
    Active = false;
    JumpCount = 0;
    SetTransformYPos(0);
  }

  public void SetTransformYPos(float yPos) {
    var pos = Transform.localPosition;
    pos.y = Math.Max(yPos, 0);
    Transform.localPosition = pos;
    Yref = Math.Min(Yref, pos.y);
  }

}
