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

namespace Level
{
    public class LevelManager : MonoBehaviour
    {
        private static LevelManager _instance = null;
        public static LevelManager Instance
        {
            get
            {
                if (_instance == null)
                {
                    GameObject gameObject = new GameObject("Level Manager");
                    _instance = gameObject.AddComponent<LevelManager>();
                    _instance.Initialize();
                }

                return _instance;
            }
        }

        private Dictionary<int, Level> _levels = null;
        public Dictionary<int, Level> Levels
        {
            get
            {
                if (_levels == null)
                    Initialize();

                return _levels;
            }
        }

        private Level currentLevel = null;
        public Level CurrentLevel => currentLevel;

        private void Awake()
        {
            if (_instance == null)
                _instance = this;

            if (_instance != this)
                Destroy(this);
        }

        public GameObject Player { get; private set; } = null;

        private void Initialize()
        {
            GameObject[] levelPrefabs = Resources.LoadAll<GameObject>("Levels/");
            Transform levelContainer = new GameObject("Levels").transform;
            _levels = new Dictionary<int, Level>(levelPrefabs.Length);

            System.Array.Sort(levelPrefabs, (x, y) => Int32.Parse(x.name).CompareTo(Int32.Parse(y.name)));

            GameObject levelInstance = null;
            Level level = null;
            foreach (GameObject levelPrefab in levelPrefabs)
            {
                levelInstance = new GameObject(levelPrefab.gameObject.name);
                levelInstance.transform.SetParent(levelContainer);
                level = levelInstance.AddComponent<Level>();
                level.SetLevel(System.Int32.Parse(levelPrefab.name));
                _levels.Add(System.Int32.Parse(levelPrefab.gameObject.name), level);
            }

            Player = GameObject.FindWithTag("Player");
            if (Player == null)
                Player = (GameObject)Instantiate(Resources.Load("Playable/Player"), transform.position, Quaternion.identity);
            Player.SetActive(false);
        }

        public void SwitchToLevel(int levelNumber)
        {
            DisableAllLevels();

            if (!Levels.ContainsKey(levelNumber))
            {
                UIManager.Instance.SwitchToCanvas("Level Selection Menu");
                return;
            }

            currentLevel = Levels[levelNumber];
            currentLevel.Enable();

            Player.SetActive(true);
            Player.transform.position = currentLevel.StartingPoint.position;
            Player.GetComponent<Rigidbody2D>().velocity = Vector2.zero;

            UIManager.Instance.CloseAllCanvases();
        }

        private void DisableAllLevels()
        {
            Player.SetActive(false);
            foreach (Level level in Levels.Values)
                level.Disable();
        }

        public bool IsLevelUnlocked(int levelNumber)
        {
            levelNumber -= 1;

            if (levelNumber == 0)
                return true;

            return PlayerPrefs.GetInt(levelNumber.ToString(), 0) != 0;
        }

        [ContextMenu("Lock All Levels")]
        public void LockAllLevels() => PlayerPrefs.DeleteAll();
    }
}
