using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Unity.VisualScripting;
using UnityEditor;
using UnityEngine;
using UnityEngine.AI;
using static EnemySpawnerData;


[SerializeField]
public class Enemy : AttackerAndDamageable {
  [Header("Mechanics Attributes")]
  [SerializeField] public float ChaseDistance = 10f;
  [SerializeField] public float ChaseDistanceBuffer = 1f;
  [SerializeField] public float AttackDistance = 1.5f;
  [SerializeField] public float AttackMaskDiameter = 1f;

  [Header("Enemy Attributes")]
  [SerializeField] public float Attack = 10f;
  [SerializeField] public float Speed = 5f;
  [SerializeField] public float Health = 10f;
  [SerializeField] public float Energy = 10f;

  protected FloatingTextSpawner TextPopUp;


  protected Player Player { get { return Player.Instance; } }
  protected Transform PlayerTransform { get { return Player.transform; } }
  protected Vector2 PlayerPos { get { return PlayerTransform.position; } }
  protected Vector2 CrystalPos { get { return GameManager.Crystal.transform.position; } }

  protected GameObject Owner;
  protected Rigidbody2D Rigidbody;
  protected Transform MyTransform { get { return Owner.transform; } }
  protected Vector2 MyPos { get { return MyTransform.position; } set { MyTransform.position = value; } }

  protected NavMeshAgent PathAgent;

  protected Material MaterialColorOverlay;

  protected bool IsUpdating;
  protected bool IsSettingNewState;

  public float DistFromPlayer { get; protected set; }
  public float DistFromCrystal { get; protected set; }
  protected bool CanAttackPlayer => DistFromPlayer <= AttackDistance && CanAttack;
  protected bool CanAttackCrystal => DistFromCrystal <= AttackDistance && CanAttack;
  public bool AggroOnPlayer { get; protected set; }
  public bool AggroOnCrystal { get; protected set; }

  public State CurrentState;
  public State PrevState;
  public enum State {
    None,
    GoToCrystal,
    AttackCrystal,
    ChasePlayer,
    AttackPlayer,
    PrepareAttack,
    FinalizeAttack,
    TakeDamage,
    Die
  }

  public Enemy(GameObject owner) {
    Owner = owner;

    PathAgent = Owner.GetComponent<NavMeshAgent>();
    PathAgent.updatePosition = false;
    PathAgent.updateRotation = false;
    PathAgent.updateUpAxis = false;
    PathAgent.speed = Speed;
    IsUpdating = false;
    IsSettingNewState = false;

    TextPopUp = new FloatingTextSpawner(Owner.transform, 1);

    OnTakeDamage += (damage, direction) => { QueueUpdate(); SetState(State.TakeDamage); IsUpdating = false; };
    OnDeath += () => { QueueUpdate(); SetState(State.Die); UnsubscribeToEvent(); IsUpdating = false; };

    Rigidbody = Owner.GetComponent<Rigidbody2D>();
    foreach (var material in Owner.GetComponentsInChildren<SpriteRenderer>().Select(x => x.material).ToList()) {
      switch (material.name.Split(' ')[0]) {
        case "DamageFlashMat": MaterialColorOverlay = material; break;
      }
    }
  }

  private Action cachedUpdate;
  protected void SubscribeToEvent() {
    cachedUpdate = () => {
      if (PathAgent == null || Owner == null) return;
      PathAgentHandler.UpdatePositionIso(PathAgent, Owner.transform);
      Update();
    };

    EnemyManagers[Enemies.Gobler].UpdateTick += cachedUpdate;
    EnemyManagers[Enemies.Gobler].GizmoTick += OnDrawGizmos;
  }

  protected void UnsubscribeToEvent() {
    EnemyManagers[Enemies.Gobler].UpdateTick -= cachedUpdate;
    EnemyManagers[Enemies.Gobler].GizmoTick -= OnDrawGizmos;
  }

  protected virtual void SetPriorityState() { }

  protected void QueueUpdate() {
    while (IsUpdating) System.Threading.Thread.Sleep(100);
    IsUpdating = true;
  }

  protected virtual void DoUpdate() { }
  protected void Update() {
    if (Owner == null) return;
    if (GameManager.Crystal == null) return;
    if (IsSettingNewState) return;
    if (IsUpdating) return;
    IsUpdating = true;

    DistFromPlayer = Vector2.Distance(MyPos, PlayerPos);
    DistFromCrystal = Vector2.Distance(MyPos, CrystalPos);
    SetPriorityState();

    DoUpdate();

    IsUpdating = false;
  }

  protected void SetState(State newState) {
    IsSettingNewState = true;
    DoSetState(newState);
    IsSettingNewState = false;
  }

  protected virtual void DoSetState(State newState) { }

  protected virtual void OnDrawGizmos() { }
}
