using XGame.Framework.Asyncs;

namespace XGame.Framework.Loadable
{
    /// <summary>
    /// 异步加载器
    /// </summary>
    public class AsyncLoadable : ILoadAsync
    {
        public LoadState State { get; protected set; }
        private AsyncGroup _loadGroup;
        private AsyncGroup _unloadGroup;

        public IAsync LoadingAsync => _loadGroup;

        public IAsync UnloadingAsync => _unloadGroup;

        public IAsync LoadAsync()
        {
            Assert.IsTrue(State == LoadState.None || State == LoadState.Unloaded, $"Connot LoadAsync On State {State} Loadable: {this} ");

            State = LoadState.Loading;

            var loadGroup = new AsyncGroup();
            _loadGroup = loadGroup;
            try
            {
                OnLoadAsync(loadGroup);
            }
            catch (System.Exception e)
            {
                Log.Exception($"AsyncLoadable.OnLoadAsync Error: \n", e);
            }
            loadGroup.On(OnLoadGroupCompleted);
            loadGroup.End();

            return loadGroup;
        }

        public IAsync UnloadAsync()
        {
            Assert.IsFalse(State != LoadState.Loading && State != LoadState.Loaded, $"Connot UnloadAsync On State {State}  Loadable: {this} ");

            if (State == LoadState.Loading)
            {
                _loadGroup?.RemoveAll();
                _loadGroup = null;
            }
            State = LoadState.Unloading;

            var unloadGroup = new AsyncGroup();
            _unloadGroup = unloadGroup;
            try
            {
                OnUnloadAsync(unloadGroup);
            }
            catch (System.Exception e)
            {
                Log.Exception($"AsyncLoadable.OnUnloadAsync Error: \n", e);
            }
            unloadGroup.On(OnUnloadGroupCompleted);
            unloadGroup.End();
            return unloadGroup;
        }

        private void OnLoadGroupCompleted(IAsync async = null)
        {
            State = LoadState.Loaded;
            _loadGroup = null;
            try
            {
                OnLoaded();
            }
            catch (System.Exception e)
            {
                Log.Exception($"AsyncLoadable.OnLoaded Error: \n", e);
            }

        }

        private void OnUnloadGroupCompleted(IAsync async = null)
        {
            State = LoadState.Unloaded;
            _unloadGroup = null;
            try
            {
                OnUnloaded();
            }
            catch (System.Exception e)
            {
                Log.Exception($"AsyncLoadable.OnUnloaded Error: \n", e);
            }

        }
        public void ClearAsyncs()
        {
            State = LoadState.None;
            _loadGroup?.RemoveAll();
            _loadGroup = null;
            _unloadGroup?.RemoveAll();
            _unloadGroup = null;
        }

        protected virtual void OnLoaded() { }
        protected virtual void OnUnloaded() { }
        protected virtual void OnLoadAsync(IAsyncGroup group) { }
        protected virtual void OnUnloadAsync(IAsyncGroup group) { }
    }
}
