using System;

namespace ET.Client
{
    [FriendOf(typeof (PingComponent))]
    public static class PingComponentSystem
    {
        [Invoke(TimerInvokeType.ClientPing)]
        public class Ping: ATimer<PingComponent>
        {
            protected override void Run(PingComponent self)
            {
                self.PingAsync().Coroutine();
            }
        }

        [ObjectSystem]
        public class PingComponentAwakeSystem: AwakeSystem<PingComponent>
        {
            protected override void Awake(PingComponent self)
            {
                self.Timer = TimerComponent.Instance.NewRepeatedTimer( Math.Max( 3000, 5 ), TimerInvokeType.ClientPing, self);
            }
        }

        [ObjectSystem]
        public class PingComponentDestroySystem: DestroySystem<PingComponent>
        {
            protected override void Destroy(PingComponent self)
            {
                self.Ping = default;
            }
        }

        private static async ETTask PingAsync(this PingComponent self)
        {
            Session session = self.GetParent<Session>();
            long instanceId = self.InstanceId;

            if (self.InstanceId != instanceId)
            {
                return;
            }

            long time1 = TimeHelper.ClientNow();
            try
            {
                G2C_Ping response = await session.Call(new C2G_Ping()) as G2C_Ping;

                if (self.InstanceId != instanceId)
                {
                    return;
                }

                long time2 = TimeHelper.ClientNow();
                self.Ping = time2 - time1;

                TimeInfo.Instance.ServerMinusClientTime = response.Time + (time2 - time1) / 2 - time2;

                await TimerComponent.Instance.WaitAsync(2000);
            }
            catch (RpcException e)
            {
                // session断开导致ping rpc报错,记录一下即可,不需要打成error
                Log.Info($"ping error: {self.Id} {e.Error}");
            }
            catch (Exception e)
            {
                Log.Error($"ping error: \n{e}");
            }
        }
    }
}