﻿using System.Collections.Generic;
using UnityEngine;

namespace JLGames.RocketDriver.Actions.Loaderx
{
    public static class LoaderManager
    {
        public const string DefaultName = "LoaderSettings";
        private static readonly Dictionary<string, ILoader> m_Loaders = new Dictionary<string, ILoader>();

        private static MonoBehaviour m_Mono;
        private static ILoader m_DefaultLoader;

        public static ILoader DefaultLoader => m_DefaultLoader;

        /// <summary>
        /// Initialize an instance of ILoader
        /// 初始化ILoader的实例
        /// </summary>
        /// <param name="loaderName"></param>
        /// <param name="settingsName"></param>
        /// <returns></returns>
        public static ILoader InitLoader(string loaderName = DefaultName, string settingsName = DefaultName)
        {
            if (string.IsNullOrEmpty(settingsName)) return null;
            var settings = LoadLoaderSettings(settingsName);
            return InitLoader(loaderName, settings);
        }

        /// <summary>
        /// Initialize an instance of ILoader
        /// 初始化ILoader的实例
        /// </summary>
        /// <param name="loaderName"></param>
        /// <param name="settings"></param>
        /// <returns></returns>
        public static ILoader InitLoader(string loaderName, LoaderSettings settings)
        {
            if (string.IsNullOrEmpty(loaderName) || null == settings) return null;
            if (m_Loaders.ContainsKey(loaderName)) return m_Loaders[loaderName];
            var loader = InitLoader(settings);
            if (null == loader) return null;
            m_Loaders[loaderName] = loader;
            if (DefaultName == loaderName)
            {
                m_DefaultLoader = loader;
            }

            return loader;
        }

        /// <summary>
        /// Find an instance of ILoader
        /// 查找ILoader的实例
        /// </summary>
        /// <param name="loaderName"></param>
        /// <returns></returns>
        public static ILoader FindLoader(string loaderName)
        {
            if (string.IsNullOrEmpty(loaderName) || m_Loaders.ContainsKey(loaderName)) return null;
            return m_Loaders[loaderName];
        }

        /// <summary>
        /// Set the instance of ILoader as default.
        /// 把ILoader的实例设置为默认
        /// </summary>
        /// <param name="loader"></param>
        public static void SetDefault(ILoader loader)
        {
            m_DefaultLoader = loader;
        }

        /// <summary>
        /// Clear the default ILoader instance reference
        /// 清除默认ILoader实例引用
        /// </summary>
        public static void ClearDefault()
        {
            m_DefaultLoader = null;
        }

        /// <summary>
        /// Delete the ILoader instance in the manager
        /// 删除管理器中的ILoader实例
        /// </summary>
        /// <param name="loaderName"></param>
        /// <returns></returns>
        public static ILoader RemoveLoader(string loaderName)
        {
            if (string.IsNullOrEmpty(loaderName) || !m_Loaders.ContainsKey(loaderName)) return null;
            var rs = m_Loaders[loaderName];
            m_Loaders.Remove(loaderName);
            return rs;
        }

        /// <summary>
        /// Delete all ILoader instances in the manager
        /// 删除管理器中全部ILoader实例
        /// </summary>
        public static void RemoveLoaders()
        {
            m_Loaders.Clear();
            m_DefaultLoader = null;
        }

        /// <summary>
        /// Load LoaderSettings configuration instance
        /// 加载LoaderSettings配置实例
        /// </summary>
        /// <param name="settingName"></param>
        /// <returns></returns>
        /// <exception cref="System.Exception"></exception>
        public static LoaderSettings LoadLoaderSettings(string settingName = DefaultName)
        {
            var settings = Resources.Load<LoaderSettings>(settingName);
            if (null == settings)
            {
                throw LoaderErrors.ErrorSettingsNotFound;
            }

            return Object.Instantiate(settings);
        }

        /// <summary>
        /// Mono component, used for starting coroutine
        /// Mono组件，用于开户协程
        /// </summary>
        public static MonoBehaviour Mono
        {
            get
            {
                if (null != m_Mono) return m_Mono;
                InitMonoObject();
                return m_Mono;
            }
        }

        // --------------------------------

        private static void InitMonoObject()
        {
            var monoObj = new GameObject("MonoLoaderCoroutine") {name = "MonoLoaderCoroutine"};
            var mono = monoObj.AddComponent<LoaderMonoBehaviour>();
            m_Mono = mono;
            Object.DontDestroyOnLoad(monoObj);
        }

        private static ILoader InitLoader(LoaderSettings settings)
        {
            if (settings == null)
            {
                throw LoaderErrors.ErrorSettingsNotFound;
            }

            Debug.Log($"Init Settings: RunMode({settings.RunMode}) LoadMode({settings.DefaultLoadMode})");
            ILoader loader = null;
            switch (settings.DefaultLoadMode)
            {
                case LoaderSettings.LoaderAssetMode.Bundle:
                    loader = new AbLoader();
                    break;
                case LoaderSettings.LoaderAssetMode.Resources:
                    loader = new ResLoader();
                    break;
#if UNITY_EDITOR
                case LoaderSettings.LoaderAssetMode.Editor:
                    loader = new EditorLoader();
                    break;
#endif
            }

            loader?.InitLoader(settings);
            return loader;
        }
    }
}