using GatherAndDefend.Events;
using System.Collections;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

/// <summary>
/// manages the logic of loading
/// </summary>
public class LoadingManager : MonoBehaviour
{
    public const string LevelToLoad = nameof(LevelToLoad);
    public const string SceneToLoad = nameof(SceneToLoad);
    public const int NoLevel = -1;
    
    private LoadingScreen loadingScreen;

    void Start()
    {
        loadingScreen = GetComponent<LoadingScreen>();
        EventAggregator.Instance.GetEvent<ScreenActivatedEvent>().Attach(LoadTargetSceneAndCloseOthers);
        loadingScreen.ShowLoadingScreen();
    }
    void Update()
    {
        foreach (var button in FindObjectsOfType<Button>())
        {
            button.enabled = false;
        }
    }
    void OnDestroy()
    {
        foreach (var button in FindObjectsOfType<Button>())
        {
            button.enabled = true;
        }
    }

    /// <summary>
    /// loads the target scene after given time
    /// </summary>
    private void LoadTargetSceneAndCloseOthers()
    {
        StartCoroutine(LoadSceneAfterTime());

        IEnumerator LoadSceneAfterTime()
        {
            yield return new WaitForSeconds(GlobalConfig.Instance.Current.loadingAddedTime);

            EventAggregator.Instance.GetEvent<ScreenActivatedEvent>().Detach(LoadTargetSceneAndCloseOthers);
            SceneManager.sceneLoaded += StartHidingLoadingScreen;

            var sceneToLoad = PlayerPrefs.GetString(SceneToLoad);

            //unload all scenes except loading screen
            for (int i = 0; i < SceneManager.sceneCount; i++)
            {
                var scene = SceneManager.GetSceneAt(i);
                if (scene.name == gameObject.scene.name) continue;
                SceneManager.UnloadSceneAsync(scene.name);
            }

            SceneManager.LoadScene(sceneToLoad, LoadSceneMode.Additive);
        }
    }

    /// <summary>
    /// hide loading screen after target scene has finished loading
    /// </summary>
    /// <param name="arg0">unused</param>
    /// <param name="arg1">unused</param>
    private void StartHidingLoadingScreen(Scene arg0, LoadSceneMode arg1)
    {
        SceneManager.sceneLoaded -= StartHidingLoadingScreen;
        EventAggregator.Instance.GetEvent<ScreenDeactivatedEvent>().Attach(StartLoadingLevel);
        loadingScreen.HideLoadingScreen();
    }

    /// <summary>
    /// when loading screen is hidden, we load the level if we have a level to load (might not, if we have loaded another scene than the Game scene)
    /// </summary>
    private void StartLoadingLevel()
    {
        EventAggregator.Instance.GetEvent<ScreenDeactivatedEvent>().Detach(StartLoadingLevel);

        var levelToLoad = PlayerPrefs.GetInt(LevelToLoad, NoLevel);
        if(levelToLoad != NoLevel)
        {
            string lvlName = $"Level{levelToLoad}";
            _ = LevelManager.Instance.LoadLevel(lvlName, LevelManagerScript.PlacementAnimation);
        }
        UnloadLoadingScreenScene();
    }

    /// <summary>
    /// close the loading screen scene and start playing! w00t w00t
    /// </summary>
    /// <param name="level"></param>
    private void UnloadLoadingScreenScene()
    {
        SceneManager.UnloadSceneAsync(gameObject.scene.name);
    }
}