﻿#if UNITY_EDITOR
using System;
using System.Collections;
using UnityEngine;
using Object = UnityEngine.Object;

namespace JLGames.RocketDriver.Actions.Loaderx
{
    internal sealed class EditorAssetLoader : BaseAssetLoader, IAssetLoader
    {
        private readonly LoaderBaseInfo m_BaseInfo;

        internal EditorAssetLoader(LoaderBaseInfo baseInfo)
        {
            m_BaseInfo = baseInfo;
        }

        //同步资源加载------------------------------------------------------------

        /// <summary>
        /// Load asset from bundle synchronously with relative path
        /// 使用相对路径从Bundle中加载资源
        /// </summary>
        /// <param name="assetPath">"Resources+ProjectBasePath"的相对路径</param>
        /// <param name="bundle"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public override T LoadAssetSync<T>(string assetPath, AssetBundle bundle)
        {
            if (string.IsNullOrEmpty(assetPath))
            {
                throw LoaderErrors.ErrorPathEmpty;
            }

            var fullPath = m_BaseInfo.GetAssetRelativeFullPath(assetPath);
            return EditorUtils.LoadAsset<T>(fullPath);
        }

        /// <summary>
        /// Load asset from bundle synchronously with full path
        /// 使用完整路径从Bundle中加载资源
        /// The full path：refers to the relative path after removing ProjectBasePath
        /// 完整路径：指的是去除ProjectBasePath后的相对路径
        /// </summary>
        /// <param name="fullPath">路径由当前工程开始</param>
        /// <param name="bundle"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public override T LoadAssetSyncFull<T>(string fullPath, AssetBundle bundle)
        {
            if (string.IsNullOrEmpty(fullPath))
            {
                throw LoaderErrors.ErrorPathEmpty;
            }

            return EditorUtils.LoadAsset<T>(fullPath);
        }

        //--同步子资源(全部)

        public Object[] LoadSubAssetsSync(string path, AssetBundle bundle)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw LoaderErrors.ErrorPathEmpty;
            }

            var fullPath = m_BaseInfo.GetAssetRelativeFullPath(path);
            return EditorUtils.LoadSubAssets(fullPath);
        }

        public Object[] LoadSubAssetsSync(string path, Type type, AssetBundle bundle)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw LoaderErrors.ErrorPathEmpty;
            }

            var fullPath = m_BaseInfo.GetAssetRelativeFullPath(path);
            return EditorUtils.LoadSubAssets(fullPath, type);
        }

        public T[] LoadSubAssetsSync<T>(string path, AssetBundle bundle) where T : Object
        {
            if (string.IsNullOrEmpty(path))
            {
                throw LoaderErrors.ErrorPathEmpty;
            }

            var fullPath = m_BaseInfo.GetAssetRelativeFullPath(path);
            return EditorUtils.LoadSubAssets<T>(fullPath);
        }

        //--同步子资源(名称)
        
        public Object LoadSubAssetSync(string path, string subName, AssetBundle ab)
        {
            var subAssets = LoadSubAssetsSync(path, ab);
            return Internal.FindAsset(subAssets, subName);
        }

        public Object LoadSubAssetSync(string path, string subName, Type type, AssetBundle ab)
        {
            var subAssets = LoadSubAssetsSync(path, type, ab);
            return Internal.FindAsset(subAssets, subName);
        }

        public T LoadSubAssetSync<T>(string path, string subName, AssetBundle ab) where T : Object
        {
            var subAssets = LoadSubAssetsSync<T>(path, ab);
            return Internal.FindAsset(subAssets, subName);
        }

        //--同步子资源(多个名称)
        
        public Object[] LoadSubAssetsSync(string path, string[] subNames, AssetBundle bundle)
        {
            if (null == subNames)
            {
                throw LoaderErrors.ErrorSubPathEmpty;
            }

            var all = LoadSubAssetsSync(path, bundle);
            return Internal.FindAssets(all, subNames);
        }

        public Object[] LoadSubAssetsSync(string path, string[] subNames, Type type, AssetBundle ab)
        {
            if (null == subNames)
            {
                throw LoaderErrors.ErrorSubPathEmpty;
            }

            var all = LoadSubAssetsSync(path, ab);
            return Internal.FindAssets(all, subNames, type);
        }

        public T[] LoadSubAssetsSync<T>(string path, string[] subNames, AssetBundle bundle) where T : Object
        {
            if (null == subNames)
            {
                throw LoaderErrors.ErrorSubPathEmpty;
            }

            var all = LoadSubAssetsSync<T>(path, bundle);
            return Internal.FindAssets(all, subNames);
        }

        //异步资源加载------------------------------------------------------------

        public IEnumerator LoadAssetAsync<T>(string assetPath, AssetBundle bundle,
            LoaderDelegate.OnAssetLoaded<T> onAssetLoaded)
            where T : Object
        {
            if (string.IsNullOrEmpty(assetPath))
            {
                throw LoaderErrors.ErrorPathEmpty;
            }

            var asset = LoadAssetSync<T>(assetPath, bundle);


            if (null == asset)
            {
                Internal.ApplyAssetCallback(onAssetLoaded, null, false);
            }
            else
            {
                Internal.ApplyAssetCallback(onAssetLoaded, asset, true);
            }

            yield break;
        }

        public IEnumerator LoadMulitAssetAsync<T>(string[] assetPaths, AssetBundle bundle,
            LoaderDelegate.OnMultiAssetLoaded<T> onMultiAssetLoaded) where T : Object
        {
            if (null == bundle)
            {
                throw LoaderErrors.ErrorBundleNull;
            }

            if (null == assetPaths || 0 == assetPaths.Length)
            {
                Internal.ApplyMultiAssetCallback(onMultiAssetLoaded, null, false);
                yield break;
            }

            var assets = new T[assetPaths.Length];
            for (var i = 0; i < assets.Length; i++)
            {
                assets[i] = LoadAssetSync<T>(assetPaths[i], bundle);
            }

            Internal.ApplyMultiAssetCallback(onMultiAssetLoaded, assets, true);
        }

        public IEnumerator LoadSubAssetsAsync<T>(string assetPath, AssetBundle buundle,
            LoaderDelegate.OnMultiAssetLoaded<T> onAssetsLoaded) where T : Object
        {
            if (string.IsNullOrEmpty(assetPath))
            {
                throw LoaderErrors.ErrorPathEmpty;
            }

            var asset = LoadSubAssetsSync<T>(assetPath, buundle);
            if (null == asset)
            {
                Internal.ApplyMultiAssetCallback(onAssetsLoaded, null, false);
            }
            else
            {
                Internal.ApplyMultiAssetCallback(onAssetsLoaded, asset, true);
            }

            yield break;
        }

        public IEnumerator LoadSubAssetAsync<T>(string assetPath, string subName, AssetBundle bundle,
            LoaderDelegate.OnAssetLoaded<T> onAssetLoaded) where T : Object
        {
            if (string.IsNullOrEmpty(assetPath))
            {
                throw LoaderErrors.ErrorPathEmpty;
            }

            var asset = LoadSubAssetSync<T>(assetPath, subName, bundle);
            if (null == asset)
            {
                Internal.ApplyAssetCallback(onAssetLoaded, null, false);
            }
            else
            {
                Internal.ApplyAssetCallback(onAssetLoaded, asset, true);
            }

            yield break;
        }
    }
}
#endif