using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace YooAsset
{
	internal abstract class BundleLoaderBase
	{
		public enum EStatus
		{
			None = 0,
			Succeed,
			Failed
		}
		/// 
		/// 所属资源系统
		/// 
		public AssetSystemImpl Impl { private set; get; }
		/// 
		/// 资源包文件信息
		/// 
		public BundleInfo MainBundleInfo { private set; get; }
		/// 
		/// 引用计数
		/// 
		public int RefCount { private set; get; }
		/// 
		/// 加载状态
		/// 
		public EStatus Status { protected set; get; }
		/// 
		/// 最近的错误信息
		/// 
		public string LastError { protected set; get; }
		/// 
		/// 是否已经销毁
		/// 
		public bool IsDestroyed { private set; get; } = false;
		private readonly List _providers = new List(100);
		internal AssetBundle CacheBundle { set; get; }
		internal string FileLoadPath { set; get; }
		internal float DownloadProgress { set; get; }
		internal ulong DownloadedBytes { set; get; }
		public BundleLoaderBase(AssetSystemImpl impl, BundleInfo bundleInfo)
		{
			Impl = impl;
			MainBundleInfo = bundleInfo;
			RefCount = 0;
			Status = EStatus.None;
		}
		/// 
		/// 添加附属的资源提供者
		/// 
		public void AddProvider(ProviderBase provider)
		{
			if (_providers.Contains(provider) == false)
				_providers.Add(provider);
		}
		/// 
		/// 引用(引用计数递加)
		/// 
		public void Reference()
		{
			RefCount++;
		}
		/// 
		/// 释放(引用计数递减)
		/// 
		public void Release()
		{
			RefCount--;
		}
		/// 
		/// 是否完毕(无论成功或失败)
		/// 
		public bool IsDone()
		{
			return Status == EStatus.Succeed || Status == EStatus.Failed;
		}
		/// 
		/// 是否可以销毁
		/// 
		public bool CanDestroy()
		{
			if (IsDone() == false)
				return false;
			if (RefCount > 0)
				return false;
			// 检查引用链上的资源包是否已经全部销毁
			// 注意:互相引用的资源包无法卸载!
			foreach (var bundleID in MainBundleInfo.Bundle.ReferenceIDs)
			{
				if (Impl.CheckBundleDestroyed(bundleID) == false)
					return false;
			}
			return true;
		}
		/// 
		/// 在满足条件的前提下,销毁所有资源提供者
		/// 
		public void TryDestroyAllProviders()
		{
			if (IsDone() == false)
				return;
			// 条件1:必须等待所有Provider可以销毁
			foreach (var provider in _providers)
			{
				if (provider.CanDestroy() == false)
					return;
			}
			// 条件2:除了自己没有其它引用
			if (RefCount > _providers.Count)
				return;
			// 销毁所有Providers
			{
				foreach (var provider in _providers)
				{
					provider.Destroy();
				}
				Impl.RemoveBundleProviders(_providers);
				_providers.Clear();
			}
		}
		/// 
		/// 轮询更新
		/// 
		public abstract void Update();
		/// 
		/// 销毁
		/// 
		public virtual void Destroy(bool forceDestroy)
		{
			IsDestroyed = true;
			// Check fatal
			if (forceDestroy == false)
			{
				if (RefCount > 0)
					throw new Exception($"Bundle file loader ref is not zero : {MainBundleInfo.Bundle.BundleName}");
				if (IsDone() == false)
					throw new Exception($"Bundle file loader is not done : {MainBundleInfo.Bundle.BundleName}");
			}
			if (CacheBundle != null)
			{
				CacheBundle.Unload(true);
				CacheBundle = null;
			}
		}
		/// 
		/// 主线程等待异步操作完毕
		/// 
		public abstract void WaitForAsyncComplete();
	}
}