using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
namespace YooAsset
{
	internal abstract class ProviderBase
	{
		public enum EStatus
		{
			None = 0,
			CheckBundle,
			Loading,
			Checking,
			Succeed,
			Failed,
		}
		/// 
		/// 资源提供者唯一标识符
		/// 
		public string ProviderGUID { private set; get; }
		/// 
		/// 所属资源系统
		/// 
		public AssetSystemImpl Impl { private set; get; }
		/// 
		/// 资源信息
		/// 
		public AssetInfo MainAssetInfo { private set; get; }
		/// 
		/// 获取的资源对象
		/// 
		public UnityEngine.Object AssetObject { protected set; get; }
		/// 
		/// 获取的资源对象集合
		/// 
		public UnityEngine.Object[] AllAssetObjects { protected set; get; }
		/// 
		/// 获取的场景对象
		/// 
		public UnityEngine.SceneManagement.Scene SceneObject { protected set; get; }
		/// 
		/// 原生文件路径
		/// 
		public string RawFilePath { protected set; get; }
		/// 
		/// 当前的加载状态
		/// 
		public EStatus Status { protected set; get; } = EStatus.None;
		/// 
		/// 最近的错误信息
		/// 
		public string LastError { protected set; get; } = string.Empty;
		/// 
		/// 加载进度
		/// 
		public float Progress { protected set; get; } = 0f;
		/// 
		/// 引用计数
		/// 
		public int RefCount { private set; get; } = 0;
		/// 
		/// 是否已经销毁
		/// 
		public bool IsDestroyed { private set; get; } = false;
		/// 
		/// 是否完毕(成功或失败)
		/// 
		public bool IsDone
		{
			get
			{
				return Status == EStatus.Succeed || Status == EStatus.Failed;
			}
		}
		protected BundleLoaderBase OwnerBundle { private set; get; }
		protected DependAssetBundles DependBundles { private set; get; }
		protected bool IsWaitForAsyncComplete { private set; get; } = false;
		private readonly List _handles = new List();
		public ProviderBase(AssetSystemImpl impl, string providerGUID, AssetInfo assetInfo)
		{
			Impl = impl;
			ProviderGUID = providerGUID;
			MainAssetInfo = assetInfo;
			// 创建资源包加载器
			if (impl != null)
			{
				OwnerBundle = impl.CreateOwnerAssetBundleLoader(assetInfo);
				OwnerBundle.Reference();
				OwnerBundle.AddProvider(this);
				var dependList = impl.CreateDependAssetBundleLoaders(assetInfo);
				DependBundles = new DependAssetBundles(dependList);
				DependBundles.Reference();
			}
		}
		/// 
		/// 轮询更新方法
		/// 
		public abstract void Update();
		/// 
		/// 销毁资源对象
		/// 
		public virtual void Destroy()
		{
			IsDestroyed = true;
			// 释放资源包加载器
			if (OwnerBundle != null)
			{
				OwnerBundle.Release();
				OwnerBundle = null;
			}
			if (DependBundles != null)
			{
				DependBundles.Release();
				DependBundles = null;
			}
		}
		/// 
		/// 是否可以销毁
		/// 
		public bool CanDestroy()
		{
			if (IsDone == false)
				return false;
			return RefCount <= 0;
		}
		/// 
		/// 是否为场景提供者
		/// 
		public bool IsSceneProvider()
		{
			if (this is BundledSceneProvider || this is DatabaseSceneProvider)
				return true;
			else
				return false;
		}
		/// 
		/// 创建操作句柄
		/// 
		public T CreateHandle() where T : OperationHandleBase
		{
			// 引用计数增加
			RefCount++;
			OperationHandleBase handle;
			if (typeof(T) == typeof(AssetOperationHandle))
				handle = new AssetOperationHandle(this);
			else if (typeof(T) == typeof(SceneOperationHandle))
				handle = new SceneOperationHandle(this);
			else if (typeof(T) == typeof(SubAssetsOperationHandle))
				handle = new SubAssetsOperationHandle(this);
			else if (typeof(T) == typeof(AllAssetsOperationHandle))
				handle = new AllAssetsOperationHandle(this);
			else if (typeof(T) == typeof(RawFileOperationHandle))
				handle = new RawFileOperationHandle(this);
			else
				throw new System.NotImplementedException();
			_handles.Add(handle);
			return handle as T;
		}
		/// 
		/// 释放操作句柄
		/// 
		public void ReleaseHandle(OperationHandleBase handle)
		{
			if (RefCount <= 0)
				YooLogger.Warning("Asset provider reference count is already zero. There may be resource leaks !");
			if (_handles.Remove(handle) == false)
				throw new System.Exception("Should never get here !");
			// 引用计数减少
			RefCount--;
		}
		/// 
		/// 等待异步执行完毕
		/// 
		public void WaitForAsyncComplete()
		{
			IsWaitForAsyncComplete = true;
			// 注意:主动轮询更新完成同步加载
			Update();
			// 验证结果
			if (IsDone == false)
			{
				YooLogger.Warning($"WaitForAsyncComplete failed to loading : {MainAssetInfo.AssetPath}");
			}
		}
		/// 
		/// 处理特殊异常
		/// 
		protected void ProcessCacheBundleException()
		{
			if (OwnerBundle.IsDestroyed)
				throw new System.Exception("Should never get here !");
			if (OwnerBundle.MainBundleInfo.Bundle.IsRawFile)
			{
				Status = EStatus.Failed;
				LastError = $"Cannot load asset bundle file using {nameof(ResourcePackage.LoadRawFileAsync)} method !";
				YooLogger.Error(LastError);
				InvokeCompletion();
			}
			else
			{
				Status = EStatus.Failed;
				LastError = $"The bundle {OwnerBundle.MainBundleInfo.Bundle.BundleName} has been destroyed by unity bugs !";
				YooLogger.Error(LastError);
				InvokeCompletion();
			}
		}
		/// 
		/// 异步操作任务
		/// 
		public Task Task
		{
			get
			{
				if (_taskCompletionSource == null)
				{
					_taskCompletionSource = new TaskCompletionSource