﻿using System;
using System.Collections;
using UnityEngine;
using Object = UnityEngine.Object;

namespace JLGames.RocketDriver.Actions.Loaderx
{
    [Flags]
    public enum AssetBundleStatus
    {
        Init = 1,
        Loading = 2,
        Loaded = 4,
        Unload = 8,
    }

    public interface IAssetLoader
    {
        // Synchronized load resource--------------------------------------------
        // 同步资源加载------------------------------------------------------------

        /// <summary>
        /// Load asset from bundle synchronously with relative path
        /// 使用相对路径从Bundle中加载资源
        /// </summary>
        /// <param name="assetPath">资源路径</param>
        /// <param name="bundle">资源包</param>
        /// <typeparam name="T">资源类型</typeparam>
        /// <returns></returns>
        T LoadAssetSync<T>(string assetPath, AssetBundle bundle) where T : Object;

        /// <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">完整资源路径,忽略设置的ProjectBasePath</param>
        /// <param name="bundle">资源包</param>
        /// <typeparam name="T">资源类型</typeparam>
        /// <returns></returns>
        T LoadAssetSyncFull<T>(string fullPath, AssetBundle bundle) where T : Object;

        /// <summary>
        /// Synchronized load resources from bundle in batches
        /// 同步批量从资源包中加载资源
        /// </summary>
        /// <param name="assetPaths">资源路径</param>
        /// <param name="bundle">资源包</param>
        /// <typeparam name="T">资源类型</typeparam>
        /// <returns></returns>
        T[] LoadAssetsSync<T>(string[] assetPaths, AssetBundle bundle) where T : Object;

        /// <summary>
        /// Synchronized load resources from bundle in batches
        /// 同步批量从资源包中加载资源
        /// </summary>
        /// <param name="fullPaths">完整资源路径,忽略设置的ProjectBasePath</param>
        /// <param name="bundle">资源包</param>
        /// <typeparam name="T">资源类型</typeparam>
        /// <returns></returns>
        T[] LoadAssetsSyncFull<T>(string[] fullPaths, AssetBundle bundle) where T : Object;

        // Synchronized all sub-resource loading
        // 同步全部子资源加载

        /// <summary>
        /// Load all sub-resources (sprites, prefabs, etc.)
        /// 加载子资源(子图、预置等)
        /// </summary>
        /// <param name="path"></param>
        /// <param name="bundle"></param>
        /// <returns></returns>
        Object[] LoadSubAssetsSync(string path, AssetBundle bundle);

        /// <summary>
        /// Load all sub-resources (sprites, prefabs, etc.)
        /// 加载子资源(子图、预置等)
        /// </summary>
        /// <param name="path"></param>
        /// <param name="type"></param>
        /// <param name="bundle"></param>
        /// <returns></returns>
        Object[] LoadSubAssetsSync(string path, Type type, AssetBundle bundle);

        /// <summary>
        /// Load all sub-resources (sprites, prefabs, etc.)
        /// 加载子资源(子图、预置等)
        /// </summary>
        /// <param name="path"></param>
        /// <param name="bundle"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        T[] LoadSubAssetsSync<T>(string path, AssetBundle bundle) where T : Object;

        // Synchronized sub-resource loading
        // 同步子资源加载

        /// <summary>
        /// Load sub-resources (sprites, prefabs, etc.)
        /// 加载子资源(子图、预置等)
        /// </summary>
        /// <param name="path"></param>
        /// <param name="subName"></param>
        /// <param name="ab"></param>
        /// <returns></returns>
        Object LoadSubAssetSync(string path, string subName, AssetBundle ab);

        /// <summary>
        /// Load sub-resources (sprites, prefabs, etc.)
        /// 加载子资源(子图、预置等)
        /// </summary>
        /// <param name="path"></param>
        /// <param name="subName"></param>
        /// <param name="type"></param>
        /// <param name="ab"></param>
        /// <returns></returns>
        Object LoadSubAssetSync(string path, string subName, Type type, AssetBundle ab);

        /// <summary>
        /// Load sub-resources (sprites, prefabs, etc.)
        /// 加载子资源(子图、预置等)
        /// </summary>
        /// <param name="path"></param>
        /// <param name="subName"></param>
        /// <param name="ab"></param>
        /// <returns></returns>
        T LoadSubAssetSync<T>(string path, string subName, AssetBundle ab) where T : Object;

        // Batch synchronized sub-resource loading
        // 批量同步子资源加载

        /// <summary>
        /// Load sub-resources (sprites, prefabs, etc.)
        /// 加载子资源(子图、预置等)
        /// </summary>
        /// <param name="path"></param>
        /// <param name="subNames"></param>
        /// <param name="bundle"></param>
        /// <returns></returns>
        Object[] LoadSubAssetsSync(string path, string[] subNames, AssetBundle bundle);

        /// <summary>
        /// Load sub-resources (sprites, prefabs, etc.)
        /// 加载子资源(子图、预置等)
        /// </summary>
        /// <param name="path"></param>
        /// <param name="subNames"></param>
        /// <param name="type"></param>
        /// <param name="ab"></param>
        /// <returns></returns>
        Object[] LoadSubAssetsSync(string path, string[] subNames, Type type, AssetBundle ab);

        /// <summary>
        /// Load sub-resources (sprites, prefabs, etc.)
        /// 加载子资源(子图、预置等)
        /// </summary>
        /// <param name="path"></param>
        /// <param name="subNames"></param>
        /// <param name="bundle"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        T[] LoadSubAssetsSync<T>(string path, string[] subNames, AssetBundle bundle) where T : Object;

        //异步资源加载------------------------------------------------------------
        //Asynchronously resource loading----------------------------------------

        /// <summary>
        /// Asynchronously load resources from bundle
        /// 异步从资源包中加载资源
        /// </summary>
        /// <param name="assetPath">资源路径</param>
        /// <param name="bundle">资源包</param>
        /// <param name="onAssetLoaded">回调</param>
        /// <typeparam name="T">资源类型</typeparam>
        /// <returns></returns>
        IEnumerator LoadAssetAsync<T>(string assetPath, AssetBundle bundle, LoaderDelegate.OnAssetLoaded<T> onAssetLoaded)
            where T : Object;

        /// <summary>
        /// Batch asynchronously load resources from bundle
        /// 异步从资源包中批量加载资源
        /// </summary>
        /// <param name="assetPaths">路径数组</param>
        /// <param name="bundle">资源包</param>
        /// <param name="onMultiAssetLoaded">回调</param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        IEnumerator LoadMulitAssetAsync<T>(string[] assetPaths, AssetBundle bundle, LoaderDelegate.OnMultiAssetLoaded<T> onMultiAssetLoaded)
            where T : Object;

        /// <summary>
        /// Load sub-resources (sprites, prefabs, etc.) from bundles asynchronously
        /// 异步从资源包中加载加载子资源(子图、预置等)
        /// </summary>
        /// <param name="assetPath">资源路径</param>
        /// <param name="buundle">资源包</param>
        /// <param name="onAssetsLoaded">Callback(回调)</param>
        /// <typeparam name="T">Resource type(资源类型)</typeparam>
        /// <returns></returns>
        IEnumerator LoadSubAssetsAsync<T>(string assetPath, AssetBundle buundle, LoaderDelegate.OnMultiAssetLoaded<T> onAssetsLoaded)
            where T : Object;

        /// <summary>
        /// Load sub-resources (sprites, prefabs, etc.) from bundles asynchronously
        /// 异步从资源包中加载加载子资源(子图、预置等)
        /// </summary>
        /// <param name="assetPath">资源路径</param>
        /// <param name="subName"></param>
        /// <param name="bundle">资源包</param>
        /// <param name="onAssetLoaded">Callback(回调)</param>
        /// <typeparam name="T">Resource type(资源类型)</typeparam>
        /// <returns></returns>
        IEnumerator LoadSubAssetAsync<T>(string assetPath, string subName, AssetBundle bundle, LoaderDelegate.OnAssetLoaded<T> onAssetLoaded)
            where T : Object;
    }

    public interface IBundleLoader
    {
        /// <summary>
        /// Whether to enable version caching
        /// 是否开启版本缓存
        /// </summary>
        /// <returns></returns>
        bool UnderVersionCache { get; }

        /// <summary>
        /// Version Information
        /// 版本信息
        /// </summary>
        LoaderVersion BundleVersion { get; }

        /// <summary>
        /// Initialize version information
        /// Version information is not allowed to be cached
        /// 初始化版本信息
        /// 版本信息获取不允许进行缓存
        /// </summary>
        /// <param name="onVersionAssetBundleLoaded"></param>
        IEnumerator InitVersion(LoaderDelegate.OnAssetLoaded<AssetBundleManifest> onVersionAssetBundleLoaded);

        //Bundle加载------------------------------------------------------------
        //Bundle Loading-------------------------------------------------------

        /// <summary>
        /// Asynchronous download bundle
        /// 异步下载资源包
        /// </summary>
        /// <param name="bundleName">资源包名称</param>
        /// <param name="onBundleLoaded">回调</param>
        /// <param name="autoRelease">是否自动释放资源包</param>
        /// <param name="unloadObjects">是否全部释放实例化的资源</param>
        /// <returns></returns>
        IEnumerator LoadBundleAsync(string bundleName, LoaderDelegate.OnBundleLoaded onBundleLoaded,
            bool autoRelease = true, bool unloadObjects = false);

        /// <summary>
        /// Asynchronous download bundle
        /// 异步下载资源包
        /// Including download dependent bundles
        /// 包括下载依赖的资源包
        /// The last element of assets in the onMultiAssetLoaded callback is the current resource bundle
        /// onMultiAssetLoaded回调中assets最后一个元素为当前资源包
        /// </summary>
        /// <param name="bundleName"></param>
        /// <param name="onBundleLoaded"></param>
        /// <param name="autoRelease"></param>
        /// <param name="unloadObjects"></param>
        /// <returns></returns>
        IEnumerator LoadBundleWithDependenciesAsync(string bundleName,
            LoaderDelegate.OnBundleLoaded onBundleLoaded, bool autoRelease = true, bool unloadObjects = false);

        /// <summary>
        /// Asynchronous batch download bundles
        /// 异步批量下载资源包
        /// </summary>
        /// <param name="bundleNames"></param>
        /// <param name="onMultiBundleLoaded"></param>
        /// <param name="autoRelease"></param>
        /// <param name="unloadObjects"></param>
        /// <returns></returns>
        IEnumerator LoadMultiBundleAsync(string[] bundleNames, LoaderDelegate.OnMultiBundleLoaded onMultiBundleLoaded,
            bool autoRelease = true, bool unloadObjects = false);
    }

    public interface ILoader : IBundleLoader, IAssetLoader
    {
        /// <summary>
        /// Get settings ref.
        /// 获取设置引用
        /// </summary>
        LoaderSettings OriginalSettings { get; }

        /// <summary>
        /// init
        /// 初始化
        /// </summary>
        /// <param name="settings"></param>
        void InitLoader(LoaderSettings settings);

        /// <summary>
        /// Set base uri
        /// 设置基础路径
        /// </summary>
        /// <param name="baseReqUri"></param>
        /// <param name="baseLocUri"></param>
        void SetBaseUri(string baseReqUri, string baseLocUri);

        /// <summary>
        /// Set cache
        /// 设置缓存
        /// </summary>
        void SetCacheSetting(string cacheName, string cachePath);

        //Multi-layer asynchronous resource loading---------------------------------
        //多层异步资源加载------------------------------------------------------------

        /// <summary>
        /// Load resources asynchronously
        /// Asynchronous includes
        ///     1. Bundle download
        ///     2. Resource loading
        /// 异步加载资源
        /// 异步包括：
        ///     1.Bundle下载
        ///     2.资源加载
        /// </summary>
        /// <param name="bundleName">资源包名称</param>
        /// <param name="assetPath">资源路径</param>
        /// <param name="onLoaded">Callback(回调)</param>
        /// <param name="autoRelease">是否自动释放资源包</param>
        /// <param name="unloadObjects">是否全部释放实例化的资源</param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        IEnumerator LoadAssetAsync<T>(string bundleName, string assetPath, LoaderDelegate.OnAssetWithBundleLoaded<T> onLoaded,
            bool autoRelease = true, bool unloadObjects = false) where T : Object;
    }
}