using IFramework.Net;
using IFramework.Net.Udp;
using Rokid.MRC;
using System;
using System.Collections;
using System.Text;
using UnityEngine;

namespace IFramework.Custom
{
    //客户端连接
    public class UDPClientProvider : MonoBehaviour
    {
        private IUdpClientProvider clientProvider;

        private bool isConnect = false;
        public int port = 16898;
        private string lastIP = "127.0.0.1";

        private bool receivedMsg;
        private float receivedTime;
        private float curTime;
        private float heartBeatInterval = 5;
        private float reconnectInterval = 3;
        private float sendMsgInterval = 2;

        private void Awake()
        {
            Init(ClientCallback);

            StartCoroutine(TryConnect());

            StartCoroutine(CheckSendIP());
        }

        //初始化客户端
        private void Init( Action<SegmentToken> ReceiveCallback = null)
        {
            clientProvider = NetTool.CreateUdpClient(4096, 4);
            
            clientProvider.ReceivedOffsetHandler = new OnReceivedSegmentHandler((SegmentToken session) =>
            {
                ReceiveCallback?.Invoke(session);
            });
        }

        private IEnumerator CheckSendIP()
        {
            yield return new WaitForSeconds(sendMsgInterval);

            if(clientProvider != null)
            {
                Send(SystemInfo.deviceName);
            }

            StartCoroutine(CheckSendIP());

            //if(!receivedServerMsg)
            //{
            //}
        }

        private void Connect(int port)
        {
            //clientProvider.Disconnect();

            string curIP = SDKManager.Instance.GetConnectedDeviceIP();

            //todo，检查是否已经连接，目前有问题。可以先移除，不管报错
            //if(CheckConnected() && curIP == lastIP)
            //{
            //    return;
            //}

            //try
            //{
            //    clientProvider.Connect(port, curIP);
            //}
            //catch(Exception)
            //{
            //}

            clientProvider.Connect(port, curIP);

            receivedMsg = false;

            lastIP = curIP;

            isConnect = true;

            //Debug.LogError($"Trying Connecting To Server {lastIP} : {port}");
        }

        private IEnumerator TryConnect()
        {
            //yield return new WaitWhile(() => 
            //{ 
            //    return true; 
            //});

            Connect(port);

            yield return new WaitForSeconds(reconnectInterval);

            if(!receivedMsg)
            {
                StartCoroutine(TryConnect());
            }
            else
            {
                //收到消息了，开启心跳超时检查
                StartCoroutine(HeartBeat());
            }
        }

        private IEnumerator HeartBeat()
        {
            yield return new WaitUntil(() =>
            {
                if(!receivedMsg || (receivedMsg && (curTime - receivedTime) > heartBeatInterval))
                {
                    //超时了，重连一下
                    return true;
                }

                return false;
            });

            StartCoroutine(TryConnect());
        }

        private void ClientCallback(SegmentToken session)
        {
            string msg = Encoding.UTF8.GetString(session.Data.buffer, session.Data.offset, session.Data.size);

            //Debug.LogError("Client Received Msg ：" + msg);

            if(msg == "OK")
            {
                receivedMsg = true;
                receivedTime = curTime;
            }
        }

        //检查是否连接着。目前测试结果，一旦连接后，即使服务端关闭了，也会一直返回true
        private bool CheckConnected()
        {
            UdpClientProvider provider = (UdpClientProvider)clientProvider;

            if(provider == null || provider.socket == null)
            {
                return false;
            }

            bool connected = provider.socket.Connected;

            Debug.Log($"Socket Connected : {connected}");

            return connected;
        }

        public void SendMsgTest(string msg)
        {
            //DataFromSDK data = GetHDMPoseData();
            //data.timestamp = GetTimeStampSecond();
            //data.virtualkey = virtualkey;
            //data.hand_points = null;
            //string json = JsonUtil.Serialize(data);

            //string json = JsonUtility.ToJson(msg);
            
            Send(msg);
        }

        public void Send(string message)
        {
            if(isConnect)
            {
                //Debug.LogError($"Client Send Msg ：{message}");

                clientProvider.Send(new SegmentOffset(Encoding.UTF8.GetBytes(message)));
            }
            else
            {
                Debug.LogWarning("未连接");
            }
        }

        private void Update()
        {
            curTime = Time.realtimeSinceStartup;
        }

        private void OnDestroy()
        {
            Dispose();
        }

        public void Dispose()
        {
            clientProvider?.Dispose();
            clientProvider = null;

            receivedMsg = false;
        }

        //当跳出设置Wifi后（连接到热点），重新连接
        public void OnApplicationPause(bool pause)
        {
            if(!pause)
            {
                //Connect(port);
            }
        }
    }
}
