using System;
using Cysharp.Threading.Tasks;
using SHFrame;
using SHFrame.FSM;
using UnityEngine;
using YooAsset;
using EventArgs = SHFrame.EventArgs;

namespace HotMain.SHGame.Procedure
{
    public class ProcedurePackageDownloader : ProcedureBase
    {
        
        private int launcherPatchCount = 0;

        private int totalDownloadCount = 0;
        private long totalDownloadBytes = 0;

        private IFsm<IProcedureManager> Procedure;
        private bool isStartDownloader = false;
        
        protected override void OnEnter(IFsm<IProcedureManager> procedureOwner)
        {
            
            Procedure = procedureOwner;
            
            base.OnEnter(procedureOwner);
            
            launcherPatchCount = 0;
            totalDownloadCount = 0;
            totalDownloadBytes = 0;
            
            //监听开始下载
            EventUtil.AddListener(HotMainEvent.StartDownloader,OnStartDownloader);
            
            //打开Launcher
            RunLauncher().Forget();
            
        }

        protected override void OnLeave(IFsm<IProcedureManager> procedureOwner, bool isShutdown)
        {
            base.OnLeave(procedureOwner, isShutdown);
            
            EventUtil.RemoveListener(HotMainEvent.StartDownloader,OnStartDownloader);
        }

        public async UniTask RunLauncher()
        {
            
            //打开LauncherMain
            var package = YooAssets.GetPackage(ProcedureInitializePackage.DefaultPackageName);
            var handle = package.LoadAssetAsync<GameObject>("HotLauncher");
            await handle.ToUniTask();
            var hotLauncher = handle.InstantiateSync();
            hotLauncher.name = $"HotLauncher_{package.GetPackageVersion()}";
            
        }
        

        private void OnStartDownloader(EventArgs eventargs)
        {
            Download(Procedure);
        }
        
        
        private async void Download(IFsm<IProcedureManager> procedureOwner)
        {

            if (isStartDownloader) return;
            
            isStartDownloader = true;
            
            //检查launcher标签的资源
            launcherPatchCount += TryGetTagPatchCount(ProcedureInitializePackage.RawFilePackageName, "Launcher");
            launcherPatchCount += TryGetTagPatchCount(ProcedureInitializePackage.DefaultPackageName, "Launcher");
            
            if (launcherPatchCount > 0)
            {
                Log.Warning("launcher资源需要更新,下载完成后需要重启游戏");
                totalDownloadCount += launcherPatchCount;
            }

            // 完全通过远端获取的资源,每次启动游戏都检查是否需要更新
            //TODO 把这个玩意拆分成 1、获取下载文件大小,2、提示总的下载大小,提示确认,3、开始下载
            ResourcePackage rawFilePackage = YooAssets.GetPackage(ProcedureInitializePackage.RawFilePackageName);
            totalDownloadBytes += TryDownloadPatch(rawFilePackage);
            ResourcePackage defaultPackage = YooAssets.GetPackage(ProcedureInitializePackage.DefaultPackageName);
            totalDownloadBytes += TryDownloadPatch(defaultPackage);

            if (totalDownloadCount > 0 || totalDownloadBytes > 0)
            {

                Log.Warning("开始下载资源");

                //进行下载
                var result = await GetDownload(rawFilePackage);
                if (!result) return;

                //进行下载
                result = await GetDownload(defaultPackage);
                if (!result) return;

                //判断launcher资源是否有更新,有就弹窗重启游戏
                if (launcherPatchCount > 0)
                {
                    Log.Warning("launcher资源有更新,需要重启游戏");
                    return;
                }

                // 资源下载完毕
                Log.Warning("资源下载完毕");
            }
            else
            {
                Log.Warning("没有资源需要更新");
                
            }

            //切换到加载热更包入口
            ChangeState<ProcedureLoadHot>(procedureOwner);
            
        }
        
        private int TryGetTagPatchCount(string packageName, string tag)
        {
            ResourcePackage package = YooAssets.GetPackage(packageName);
            //4.下载补丁包信息,反馈到弹窗
            var downloader = package.CreateResourceDownloader(tag, 10, 3, 60);
            //没有需要下载的资源
            if (downloader.TotalDownloadCount == 0)
            {
                Log.Warning($"{package.PackageName} tag {tag} 没有资源更新");
                return 0;
            }

            //需要下载的文件总数和总大小
            Log.Warning($"{package.PackageName} tag {tag} 文件总数:{downloader.TotalDownloadCount}:::总大小:{downloader.TotalDownloadBytes}");
            return totalDownloadCount;
        }
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="package"></param>
        private long TryDownloadPatch(ResourcePackage package)
        {
            //4.下载补丁包信息,反馈到弹窗
            var downloader = package.CreateResourceDownloader(10, 3, 60);
            //没有需要下载的资源
            if (downloader.TotalDownloadCount == 0)
            {
                Log.Warning($"{package.PackageName} all 没有资源更新");
                return 0;
            }

            totalDownloadCount++;
            //需要下载的文件总数和总大小
            Log.Warning($"{package.PackageName} 文件总数:{downloader.TotalDownloadCount}:::总大小:{downloader.TotalDownloadBytes}");
            return downloader.TotalDownloadBytes;
        }
        
        private async UniTask<bool> GetDownload(ResourcePackage package)
        {
            var downloader = package.CreateResourceDownloader(10, 3, 60);

            //注册回调方法
            downloader.OnDownloadErrorCallback = OnDownloadErrorFunction;
            downloader.OnDownloadProgressCallback = OnDownloadProgressUpdateFunction;
            downloader.OnDownloadOverCallback = OnDownloadOverFunction;
            downloader.OnStartDownloadFileCallback = OnStartDownloadFileFunction;

            //开启下载
            downloader.BeginDownload();
            await downloader.ToUniTask();
            //检测下载结果
            if (downloader.Status == EOperationStatus.Succeed)
            {
                Log.Debug("更新完成!");
                return true;
            }
            else
            {
                //下载失败
                Log.Error("更新失败!");
                return false;
            }
        }
        
        
        
        #region yooasset下载回调函数

        /// <summary>
        /// 下载数据大小
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="sizeBytes"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void OnStartDownloadFileFunction(string fileName, long sizeBytes)
        {
            Log.Debug($"开始下载:文件名:{fileName}, 文件大小:{sizeBytes}");
        }

        /// <summary>
        /// 下载完成与否
        /// </summary>
        /// <param name="isSucceed"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void OnDownloadOverFunction(bool isSucceed)
        {
            Log.Debug("下载" + (isSucceed ? "成功" : "失败"));
        }

        /// <summary>
        /// 更新中
        /// </summary>
        /// <param name="totalCount"></param>
        /// <param name="currentCount"></param>
        /// <param name="totalBytes"></param>
        /// <param name="currentBytes"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void OnDownloadProgressUpdateFunction(int totalCount, int currentCount, long totalBytes, long currentBytes)
        {
            EventUtil.DispatchEvent(HotMainEvent.DownloaderProgressUpdate,totalCount,currentCount,totalBytes,currentBytes);
            Log.Debug($"文件总数:{totalCount}, 已下载文件数:{currentCount}, 下载总大小:{totalBytes}, 已下载大小:{currentBytes}");
        }

        /// <summary>
        /// 下载出错
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="error"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void OnDownloadErrorFunction(string fileName, string error)
        {
            Log.Error($"下载出错:文件名:{fileName}, 错误信息:{error}");
        }

        #endregion
        
    }
}