using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using NaughtyAttributes;
using Variables;

public class LevelManager : MonoBehaviour
{
    [SerializeField, Header("References")]
    Reference<bool> m_isPlayerDead;

    [SerializeField]
    Reference<bool> m_freezePlayer;

    [SerializeField]
    Reference<bool> m_isVictory;

    [SerializeField]
    Reference<float> m_timer;

    [SerializeField]
    Reference<float> m_light;

    [SerializeField]
    Reference<bool> m_manualDarkness;

    [SerializeField]
    private Image m_backGround;


    [SerializeField, BoxGroup("Level Settings")]
    public string levelName = "Level 1";

    [SerializeField, BoxGroup("Level Settings")]
    private float m_timeInLevel = 10;

    [SerializeField, BoxGroup("Level Settings")]
    public string levelPrompt = "Get to the Chest";

    [SerializeField,BoxGroup("Default Settings")]
    private float m_resetTime = 1;

    [SerializeField, BoxGroup("Default Settings")]
    private float m_nextSceneWaitTime = 3;

    [SerializeField, BoxGroup("Level Settings")]
    private string m_nextSceneToLoad = "Level 2";


    private IResettable[] m_allResetable;

    private void Start()
    {
        m_allResetable = FindObjectsOfType<MonoBehaviour>().OfType<IResettable>().ToArray();
        m_timer.Value = m_timeInLevel;

        m_isVictory.Value = false;

        foreach (IResettable resettable in m_allResetable)
        {
            resettable.OnLevelLoad();
        }
    }

    private void Update()
    {
        if (!m_freezePlayer)
            m_timer.Value -= Time.deltaTime;

        if (m_timer <= 0 && !m_isPlayerDead)
        {
            m_isPlayerDead.Value = true;
        }

    }



    private void OnEnable()
    {
        m_isPlayerDead.OnValueChanged += OnPlayerDeadChange;
        m_isVictory.OnValueChanged += OnPlayerVictoryChange;
    }

    private void OnDisable()
    {
        m_isPlayerDead.OnValueChanged -= OnPlayerDeadChange;
        m_isVictory.OnValueChanged -= OnPlayerVictoryChange;
    }


    private IEnumerator DeathRoutine()
    {
        m_freezePlayer.Value = true;

        yield return new WaitForSeconds(1);



        m_timer.Value = m_timeInLevel;
        foreach (IResettable resettable in m_allResetable)
            StartCoroutine(resettable.OnResetStart(m_resetTime));

        yield return new WaitForSeconds(m_resetTime);

        foreach (IResettable resettable in m_allResetable)
            resettable.OnResetEnd();


        m_freezePlayer.Value = false;
    }


    private IEnumerator VictoryRoutine()
    {
        yield return new WaitForSeconds(m_nextSceneWaitTime);

        m_manualDarkness.Value = true;

        float elapsedTime = 0;
        float fadeTime = 1;
        while (elapsedTime < fadeTime)
        {
            m_light.Value = 1 - elapsedTime / fadeTime;
            yield return new WaitForEndOfFrame();
            elapsedTime += Time.deltaTime;
        }
        m_light.Value = 0;

        yield return new WaitForSeconds(1);

        elapsedTime = 0;
        fadeTime = 2;

        
        Color color = m_backGround.color;
        m_backGround.gameObject.SetActive(true);

        while (elapsedTime < fadeTime)
        {
           color.a = elapsedTime / fadeTime;
            m_backGround.color = color;
            Debug.Log(color.a);
            yield return new WaitForEndOfFrame();
            elapsedTime += Time.deltaTime;
        }

        yield return new WaitForSeconds(1);


        m_manualDarkness.Value = false;
        SceneManager.LoadScene(m_nextSceneToLoad);
        

    }



    private void OnPlayerDeadChange(bool value)
    {
        if (value)
        {
            StartCoroutine(DeathRoutine());
        }


    }

    private void OnPlayerVictoryChange(bool value)
    {
        if (value)
        {
            StartCoroutine(VictoryRoutine());
        }
    }








}
