using Cysharp.Threading.Tasks;
using System;
using System.Collections;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.SceneManagement;

namespace WS
{
    [ObjectSystem]
    public class SceneChangeUpdate : UpdateSystem<SceneChange>
    {
        public override void Update(SceneChange self)
        {
            self.Update();
        }
    }

    ///<summary>场景切换组件</summary>
    public class SceneChange : WSComponent
    {
        ///<summary>场景加载完成回调</summary>
        public Action OnCallback;

        //Unity场景加载回调
        private AsyncOperation loadMapOperation;

        //异步
        private TaskCompletionSource<bool> tcs;

        //加载进度
        private float lastProgress = 0;

        //加载时间
        private float loadTime = 0;

        //progress大于0.9时的加载时间
        private float loadTimeor = 0;

        //等待
        private bool isWaitCallback;

        ///<summary>加载进度</summary>
        public float Process
        {
            get { return lastProgress; }
        }

        public void Update()
        {
            if (loadMapOperation != null)
            {
                if (loadTimeor < 0)
                {
                    loadTime += Time.deltaTime;
                    if (lastProgress >= 0.9f)
                    {
                        lastProgress = 0.9f;
                        loadTime += loadTime / 9;
                        loadTimeor = 0;
                        if (loadTime < 2)
                            loadTime = 2;
                    }
                    else
                    {
                        lastProgress = loadMapOperation.progress;
                    }
                }
                else
                {
                    loadTimeor += Time.deltaTime;
                    if (!isWaitCallback)
                    {
                        if (loadTimeor >= loadTime)
                        {
                            loadMapOperation.allowSceneActivation = true;
                            lastProgress = 1;
                            tcs?.SetResult(true);
                            isWaitCallback = true;
                        }
                        else
                        {
                            lastProgress += Time.deltaTime / loadTime * 0.1f;
                        }
                    }
                    else
                    {
                        try
                        {
                            if (loadMapOperation.isDone)
                                OnCallback?.Invoke();
                        }
                        catch (Exception e)
                        {
                            Log.LogError(e);
                        }
                    }
                }
            }
        }

        ///<summary>加载场景</summary>
        public void LoadScene(string name, Action oncallback)
        {
            OnCallback = oncallback;
            lastProgress = 0;
            loadTime = 0;
            loadTimeor = -1;
            SceneManager.LoadScene("Loading");
            TimerComponent.Instance.StartCoroutine(LoadSceneEnumerator(name));
            // LoadSceneAsync(name).Forget();
        }

        ///<summary>加载场景</summary>
        private IEnumerator LoadSceneEnumerator(string name)
        {
            yield return null;
            loadMapOperation = SceneManager.LoadSceneAsync(name);
            loadMapOperation.allowSceneActivation = false;
            yield return loadMapOperation;
        }

        ///<summary>加载场景</summary>
        private async UniTask LoadSceneAsync(string name)
        {
            await UniTask.DelayFrame(50);
            var loadS = SceneManager.LoadSceneAsync(name);
            loadS.allowSceneActivation = false;
            await loadS;
            loadS.allowSceneActivation = true;
        }

        ///<summary>加载场景异步</summary>
        public Task<bool> LoadSceneAsync(string name, Action oncallback)
        {
            OnCallback = oncallback;
            lastProgress = 0;
            loadTime = 0;
            loadTimeor = -1;
            SceneManager.LoadScene("Loading");
            tcs = new TaskCompletionSource<bool>();
            loadMapOperation = SceneManager.LoadSceneAsync(name);
            loadMapOperation.allowSceneActivation = false;
            return tcs.Task;
        }

        public override void Dispose()
        {
            base.Dispose();
            OnCallback = null;
            loadMapOperation = null;
            tcs = null;
            lastProgress = 0;
            loadTime = 0;
            loadTimeor = 0;
            isWaitCallback = false;
        }
    }
}
