using System;
using Cysharp.Threading.Tasks;
using DotRecast.Core.Collections;
using Game.Input;
using Game.JNGFrame.Logic;
using Game.JNGFrame.Logic.Entity;
using Game.JNGFrame.View;
using Game.JNGState.Logic.Data;
using Game.Logic.System.Logic;
using Game.Logic.System.Usual;
using JNGame.Sync.Entity;
using JNGame.Sync.Frame;
using JNGame.Sync.System;
using JNGame.Sync.System.Data;
using Plugins.JNGame.Network.Action;
using UnityEngine;

namespace AppGame.Sync
{
    /// <summary>
    /// 帧同步游戏
    /// </summary>
    public class JNGFrameSystem : JNSyncFrameService
    {

        public override SLogicSystem[] NewLogicSystems()
        {
            return new SLogicSystem[]
            {

                //基础数据
                new DInputSystem(),         //游戏输入
                new DDataSystem(),          //游戏数据
                
                //帧同步逻辑层
                new DMapSystem(),           //游戏地图
                new DWorldSystem(),         //游戏逻辑
                
            };
        }

        public override SDataSystemBase[] NewDataSystems()
        {
            return new SDataSystemBase[] {
                new EDNodeDataSystem(SStateDataEnum.ServerClient),     //游戏数据
            };
        }

        public override SViewSystem[] NewViewSystems()
        {
            return new SViewSystem[]
            {
                //视图层
                new DViewSystem(),  //游戏视图
            };
        }

        public override bool IsStartGame => true;

        public override JNContexts CreateContexts()
        {
            return new EDContexts();
        }

        protected override void OnRunSimulate()
        {
            if (!(NFrameQueue.TryDequeue(out var frame))) return;
            //插入当前输入
            frame.Messages.ForEach(child =>
            {
                GetSystem<DInputSystem>().Enqueue(child);
            });
            Simulate();
        }

        /// <summary>
        /// 获取输入
        /// </summary>
        /// <returns></returns>
        protected override JNFrameInputs GetInputs()
        {
            return GetSystem<DInputSystem>().Dequeue();
        }

        /// <summary>
        /// 发送输入
        /// </summary>
        /// <param name="inputs"></param>
        protected override void OnSendInput(JNFrameInputs inputs)
        {
            //发送帧数据给服务端
            App.Socket.Send((int)NActionEnum.NSyncFrameInput,inputs);
        }

        /// <summary>
        /// 追帧
        /// </summary>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <returns></returns>
        protected override async UniTask<JNFrameInfos> OnServerData(int start, int end)
        {
            Debug.Log($"OnServerData - {start}");
            try
            {
                var data = (await App.API.GetByte($"/sync/frame?start={start}"));
                if (data is { Length: > 0 })
                {
                    JNFrameInfos info = JNFrameInfos.Parser.ParseFrom(data);
                    Debug.Log($"OnServerData - {start} {end} 结束");
                    return info;
                }
            }
            catch(Exception e)
            {
                // ignored
                Debug.LogError(e.Message);
            }
            return new JNFrameInfos();
        }
        
    }
}