using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.Serialization;
using System;

public class FadeManager : SingletonMonoBehaviour<FadeManager> {

    [SerializeField, FormerlySerializedAs("fadeIn")]
    private bool isAutoFadeIn = true;
    public Color fadeColor = Color.black;
    public UnityEvent onFadeInEnd;
    public UnityEvent onFadeOutEnd;

    private Texture2D texture;
    private float fadeAlpha = 0.0f;
    private bool isFading = false;
    public bool IsFading{
        get{ return isFading; }
    }
    private float timer = 0.0f;
    private Action<float> fadeFunc = ActionExtensions.EmptyActionFloat;

    void Awake(){
        if(CheckInstance()) return ;

        if(isAutoFadeIn){
            isFading = true;
            fadeAlpha = 1.0f;
            this.CallWaitForFrame(2, () => FadeIn(0.5f));
        }

        texture = new Texture2D(2, 2, TextureFormat.ARGB32, false);
        texture.SetPixel(0, 0, Color.white);
        texture.SetPixel(0, 1, Color.white);
        texture.SetPixel(1, 0, Color.white);
        texture.SetPixel(1, 1, Color.white);
        texture.Apply();
    }

    void OnGUI(){
        if(isFading){
            timer += Time.unscaledDeltaTime;
            fadeFunc(timer);
            fadeColor.a = fadeAlpha;
        }
        if(fadeAlpha > 0.0f){
            DrawTexture(fadeColor);
        }
    }

    // alpha 1 to 0
    public void FadeIn(float interval = 1.0f){
        FadeIn(interval, ActionExtensions.EmptyAction);
    }
    public void FadeIn(float interval, Action callback){
        isFading = true;
        timer = 0.0f;
        fadeFunc = (t) => {
            fadeAlpha = Mathf.Lerp (1.0f, 0.0f, t / interval);
            if(t >= interval){
                isFading = false;
                onFadeInEnd.Invoke();
                callback();
            }
        };
    }

    // alpha 0 to 1
    public void FadeOut(float interval, Action callback){
        FadeOut(interval, callback, fadeColor);
    }
    public void FadeOut(float interval, Action callback, Color color){
        fadeColor = color;
        isFading = true;
        timer = 0.0f;
        fadeFunc = (t) => {
            fadeAlpha = Mathf.Lerp (0.0f, 1.0f, t / interval);
            if(t >= interval){
                isFading = false;
                onFadeOutEnd.Invoke();
                callback();
            }
        };
    }

    private void DrawTexture(Color color){
        GUI.color = color;
        GUI.DrawTexture(new Rect(0, 0, Screen.width, Screen.height), texture);
    }

    public void FadeOutToTransition(float interval, string sceneName){
        FadeOut(interval, () => SceneManager.LoadScene(sceneName));
    }

    public void Show(){
        fadeAlpha = 1.0f;
    }
    public void Hide(){
        fadeAlpha = 0.0f;
    }
}