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

/// <summary>
/// 이 인터페이스를 구현한 오브젝트가 데미지를 받는것에 대해서 나타내기 위함
/// </summary>
public interface IDamageable
{
    void TakeDamage(float damage);
}

/// <summary>
/// 무기나 투사체에 붙여 동작에 대한 트리거를 ON/OFF 하는 컴포넌트.
/// 
/// <!--Collider(Is Trigger(ON)) + Script 설정해둘것-->
/// <!-- 역할
/// 1. Collider를 공격 순간에만 ON/OFF 하는 판정 관리자 역할(인데 매니저라고 하기엔 그 역할이 약함)
/// 2. 충돌 처리하는 대상을 필터링 및 히트 쿨다운 정책 관리, 정보 전달
/// -->
/// <!-- 책임
/// 1. 데미지를 유발하는 것 (충돌 감지 및 데이터 전달)
/// -->
/// </summary>
public abstract class Damage : MonoBehaviour
{
    [SerializeField] public LayerMask _targetlayer; // 공격 가능한 레이어 마스크
    
    Collider _weaponCollider; // 공격 가능 시간만 활성화 되는 히트 센서로 활용하기 위해서 사용
    protected readonly HashSet<GameObject> hitTargets = new HashSet<GameObject>();
    
    // ToDo: 무기에 대한 여러 설정에 대한건 후에 Data_* 로 따로 관리
    // 데미지, 다단히트, 히트 쿨타임, 넉백 등등
    [SerializeField] private float _damage = 0f;
    
    protected bool isActive = false; // 활성화 상태
    
    public event Action<IDamageable, Collider> OnHit;

    protected virtual void Awake()
    {
        if (_weaponCollider == null) _weaponCollider = GetComponent<Collider>();
        
        if (_weaponCollider != null)
        {
            _weaponCollider.isTrigger = true;
            _weaponCollider.enabled = false;
        }
    }
    protected virtual bool LayerPassed(Collider target)
    {
        int layer = target.gameObject.layer;
        return (_targetlayer.value & (1 << layer)) != 0;
    }
    
    protected void ApplyDamage(Collider target)
    {
        if(!isActive) return;
        if(!LayerPassed(target)) return;

        GameObject go = target.gameObject;
        if(hitTargets.Contains(go)) return;

        if (target.TryGetComponent(out IDamageable damagebable))
        {
            hitTargets.Add(go);
            damagebable.TakeDamage(_damage);
            OnHit?.Invoke(damagebable, target);
            OnDamageApplied(target);
        }
    }

    public void SetTriggerActive(bool active)
    {
        isActive = active;
        if (_weaponCollider != null) _weaponCollider.enabled = active;
        if (active) ResetHitCache();
    }
    protected void ResetHitCache() => hitTargets.Clear();

    private void OnTriggerEnter(Collider other)
    {
        HandleCollision(other);
    }
    
    // 데미지 적용 후의 특화 동작 오버라이드 하기
    protected virtual void OnDamageApplied(Collider target)
    { 
        // 예: 피격 효과, 사운드 재생 등
        // 투사체면 충돌시 파괴, 근접 무기면 히트 이펙트 재생이나 연속 공격 위해 아무것도 안하기
    }

    protected abstract void HandleCollision(Collider other);



}
