using UnityEngine;

/// <summary>
/// ϰ   ̱ ̽.
/// - ù    ãƺ  GameObject  
/// - ߺ   ڵ ı
/// - DontDestroyOnLoad (Ŭ   Override)
/// -    (_applicationIsQuitting)
/// </summary>
public abstract class MonoSingleton<T> : MonoBehaviour where T : MonoSingleton<T>
{
    private static T _instance;
    private static bool _applicationIsQuitting;

    /// <summary> ̹ ϸ װ ,  մϴ.</summary>
    public static T Instance
    {
        get
        {
            if (_applicationIsQuitting) return null;

            if (_instance == null)
            {
                // Unity 2022+ : FindFirstObjectByType /   FindObjectOfType
#if UNITY_2022_2_OR_NEWER
                _instance = FindFirstObjectByType<T>();
#else
                _instance = FindObjectOfType<T>();
#endif
                if (_instance == null)
                {
                    var go = new GameObject($"[Singleton] {typeof(T).Name}");
                    _instance = go.AddComponent<T>();

                    if (_instance.DontDestroy) 
                        DontDestroyOnLoad(go);
                }
            }
            return _instance;
        }
    }

    /// <summary>̹ ϴ( ʰ) Ȯ.</summary>
    public static bool HasInstance => _instance != null && !_applicationIsQuitting;

    /// <summary> ʰ ⸦ õ.</summary>
    public static bool TryGet(out T inst)
    {
        inst = HasInstance ? _instance : null;
        return inst != null;
    }

    /// <summary>Ŭ false ٲٸ  ȯ  ı˴ϴ.</summary>
    protected virtual bool DontDestroy => true;

    /// <summary>̱    1ȸ ȣǴ .</summary>
    protected virtual void OnInitialized() { }

    protected virtual void Awake()
    {
        if (_instance == null)
        {
            _instance = (T)this;

            if (DontDestroy) DontDestroyOnLoad(gameObject);
            OnInitialized();
        }
        else if (_instance != this)
        {
            // ߺ νϽ ı
            Destroy(gameObject);
        }
    }

    protected virtual void OnApplicationQuit()
    {
        _applicationIsQuitting = true;
    }

    protected virtual void OnDestroy()
    {
        // ڱ ڽ ̸̱  
        if (_instance == this) _instance = null;
    }

//#if UNITY_EDITOR
//    // "Domain Reload Ȱ(Enter Play Mode Options)" ȯ  ʱȭ
//    [UnityEditor.InitializeOnEnterPlayMode]
//    private static void OnEnterPlayModeInEditor(UnityEditor.EnterPlayModeOptions _)
//    {
//        _applicationIsQuitting = false;
//        _instance = null;
//    }
//#endif
}
