using XGame.Framework.Asyncs;
using System;

namespace XGame.Framework.Asset
{
    /// <summary>
    /// 该类也继承IAssetPreloadAsync，少创建一个对象
    /// 业务禁止将IAssetPreloadAsync强转为IAssetLoadAsync<TResult>
    /// </summary>
    /// <typeparam name="TResult"></typeparam>
    internal sealed class AssetLoadAsync<TResult> : IAssetLoadAsync<TResult>, IAssetEventListenerSetter, IAssetPreloadAsync
    {
        private AsyncListenerOperation _operation;


        private IAssetAsync _assetAsync;
        private IAssetCacheHandle _cacheHandle;
        private IAssetEventListener _eventListener;
        IAssetEventListener IAssetEventListenerSetter.AssetEventListener { set => _eventListener = value; }
        internal AssetLoadAsync(string addressableName, IAssetAsync assetAsync, IAssetCacheHandle handle)
        {
            AddressableName = addressableName;
            _assetAsync = assetAsync;
            _cacheHandle = handle;
            if (assetAsync != null && assetAsync.IsCompleted == false)
            {
                assetAsync.On(OnAsyncCompleted);
            }
        }

        private void OnAsyncCompleted(IAsync aAsync)
        {
            _operation.OnCompleted(this);
            PreRelease();
        }
        private void PreRelease()
        {
            if (_operation.HaveListener)
                return;
            RemoveAll();
        }
        #region 接口实现
        object IAsync.State
        {
            set
            {
                var assetAsync = _assetAsync;
                if (assetAsync != null)
                    assetAsync.State = value;
            }
            get => _assetAsync?.State;
        }

        public Exception Exception => _assetAsync?.Exception;

        public bool IsCompleted => _assetAsync?.IsCompleted ?? true;
        /// <summary>
        /// 返回加载进度
        /// async为空时默认加载完成
        /// </summary>
        public float Progress => _assetAsync?.Progress ?? 1;
        public string AddressableName { get; private set; }
        

        public IAsync On(OnAsyncCompleted action)
        {
            if (action != null)
            {
                if (IsCompleted)
                {
                    action.SaveInvoke(this);
                    PreRelease();
                }
                else
                {
                    _operation.On(action);
                }
            }
            return this;
        }

        public IAsync On(IAsyncListener listener, int order = 0)
        {
            if (listener == null) return this;
            if (IsCompleted)
            {
                listener.SaveInvoke(this);
                PreRelease();
                return this;
            }
            _operation.On(listener, order);
            return this;
        }

        public IAsync RemoveOn(OnAsyncCompleted action)
        {
            _operation.RemoveOn(action);
            return this;
        }

        public IAsync RemoveOn(IAsyncListener listener)
        {
            _operation.RemoveOn(listener);
            return this;
        }

        public IAsync RemoveAll()
        {
            //Log.Debug($"AssetLoadAsync RemoveAll Name:{AddressableName}");
            if (!IsCompleted)
                _assetAsync?.RemoveOn(OnAsyncCompleted);
            _assetAsync = null;
            _cacheHandle?.ReleaseAsync(this);
            _cacheHandle = null;
            _eventListener?.ReleaseAsync(this);
            _eventListener = null;
            _operation.Clear();
            return this;
        }

        public TResult Result
        {
            get
            {
                TResult result = default;
                var addressableName = AddressableName;
                if (_cacheHandle != null)
                    result = _cacheHandle.GetAssetFromCache(addressableName).Convert<TResult>(addressableName);
                //先 Convert， 保证getResultCallback和最终返回的是同一个对象
                if (result != null)
                {
                    _eventListener?.OnGetResult(addressableName, result);
                }
                return result;
            }
        }
        #endregion
#if UNITY_EDITOR
        public override string ToString()
        {
            return $"AssetLoadAsync Type:{typeof(TResult)} Name:{AddressableName} IsCompleted:{IsCompleted}";
        }
#endif
    }
}

