using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum EnemyType { Melee, Shooter, Mage }

public class Enemy : MonoBehaviour
{
    [Header("General")]
    [SerializeField] private EnemyType type;

    [SerializeField] private int health;

    [SerializeField] private int damage;
    [SerializeField] private float moveSpeed;

    private GameObject target;

    [Header("Weapon")]
    [SerializeField] private float attackRate;
    private float attackTimer;
    [SerializeField] private float attackRange;

    [SerializeField] private float meleeRecoil;

    [SerializeField] private float projectileSpeed;
    [SerializeField] private GameObject projectilePrefab;

    [SerializeField] private Transform firePoint;

    [SerializeField] private bool rotateWeapon;
    [SerializeField] private Transform weaponPos;
    [SerializeField] private float rotationSpeed;

    [Header("GFX")]
    [SerializeField] private Transform GFXPos;
    [Space]

    [Header("Animator")]
    [SerializeField] private Animator anim;

    [Header("FX")]
    [SerializeField] private GameObject hitParticleEffect;
    [SerializeField] private GameObject deathParticleEffect;
    [SerializeField] private GameObject deadObject;

    [Header("Other")]
    [SerializeField] private Rigidbody2D rig;

    void Start()
    {
        rig = GetComponent<Rigidbody2D>();

        health = Mathf.RoundToInt(health * Game.game.difficult);
        damage = Mathf.RoundToInt(damage * Game.game.difficult);
    }

    void Update()
    {
        attackTimer += Time.deltaTime;

        //anim.SetFloat("moveSpeed", Mathf.Abs(rig.velocity.magnitude));

        // Если у врага есть цель
        if (target != null)
        {
            // Если враг дальше чем его радиус атаки, то враг догоняет цель.
            if (Vector3.Distance(transform.position, target.transform.position) > attackRange)
            {
                ChaseTarget();
                anim.SetFloat("moveSpeed", 1f);
            }
            // Если ближе то атакует.
            else
            {
                if (attackTimer >= attackRate)
                {
                    attackTimer = 0.0f;
                    Attack();
                }
                anim.SetFloat("moveSpeed", 0f);
            }
        }
        // Если цели нет, то игрок становится целью.
        else
        {
            if (Game.game.player)
            {
                target = Game.game.player.gameObject;
            }
            // Если игрока нет, то враг останавливается.
            else
            {
                rig.simulated = false;
            }
        }
    }

    void FixedUpdate()
    {
        if (target != null)
        {
            // То враг поворачивается на цель (правильное отображение графики)
            EnemyFlip();

            if (rotateWeapon == true)
            {
                weaponPos.rotation = Quaternion.Lerp(weaponPos.rotation, WeaponRotation(), rotationSpeed * Time.deltaTime);
            }
        }
    }

    // Получаем угол между позицией врага и цели
    float GetAngle()
    {
        Vector3 dir = target.transform.position - transform.position;
        float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;

        return angle;
    }

    // Разворачивание врага в сторону цели
    void EnemyFlip()
    {
        Vector3 rotationVector = transform.rotation.eulerAngles;
        float angle = GetAngle();

        if (angle > 90f || angle < -90f)
        {
            rotationVector.y = 180f;
            GFXPos.transform.rotation = Quaternion.Euler(rotationVector);
        }
        else if (angle < 90f || angle > -90f)
        {
            rotationVector.y = 0f;
            GFXPos.transform.rotation = Quaternion.Euler(rotationVector);
        }
    }

    // Поворот оружия в сторону цели
    Quaternion WeaponRotation()
    {
        float angle = GetAngle();

        if (angle > 90f || angle < -90f)
        {
            weaponPos.localScale = new Vector3(1f, -1f, 0f);
        }
        else if (angle < 90f || angle > -90f)
        {
            weaponPos.localScale = new Vector3(1f, 1f, 0f);
        }

        return Quaternion.AngleAxis(angle, Vector3.forward);
    }

    public void SetTarget()
    {
        if (Game.game.player.gameObject != null)
        {
            target = Game.game.player.gameObject;
        }
    }

    // Двигаемся к цели
    void ChaseTarget()
    {
        transform.position = Vector3.MoveTowards(transform.position, target.transform.position, moveSpeed * Time.deltaTime);
    }

    // Устанавливаем цель
    public void SetTarget(GameObject trg)
    {
        target = trg;
    }

    // Если враг стрелок, то выстреливает пулю. Если рукопашник, то ударяет цель.
    void Attack()
    {
        if (type == EnemyType.Shooter || type == EnemyType.Mage)
        {
            Shoot();
        }
        else if (type == EnemyType.Melee)
        {
            Melee();
        }
    }

    // Выстреливает проджектайл
    void Shoot()
    {
        GameObject proj = Instantiate(projectilePrefab, firePoint.position, firePoint.rotation);
        Projectile projScript = proj.GetComponent<Projectile>();

        projScript.damage = damage;

        if (type != EnemyType.Mage)
        {
            projScript.rig.velocity = (target.transform.position - transform.position).normalized * projectileSpeed;
        }
        else
        {
            projScript.followSpeed = projectileSpeed;
        }
    }

    // Ближний бой
    void Melee()
    {
        Game.game.player.TakeDamage(damage);
        rig.AddForce((target.transform.position - transform.position).normalized * -meleeRecoil * Time.deltaTime);
    }

    // Принятие урона
    public void TakeDamage(int dmg)
    {
        if (health - dmg <= 0)
        {
            Die();
        }
        else
        {
            Instantiate(hitParticleEffect, transform.position, transform.rotation);
            health -= dmg;
        }
    }

    // Погибель
    void Die()
    {
        Game.game.waveManager.curEnemies.Remove(gameObject);
        GameObject pe = Instantiate(deathParticleEffect, transform.position, Quaternion.identity);
        Destroy(pe, 2f);

        GameObject corpse = Instantiate(deadObject, transform.position, Quaternion.identity);
        Destroy(corpse, 1f);

        Destroy(gameObject);
    }
}