using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using QFrameworkCP;
using JXSoft;
using System;
using System.Threading;
using UnityEngine.UI;

namespace JXSoft { 
    public class TCPMangerArchitecture : Architecture<TCPMangerArchitecture>
    {
        protected override void Init()
        {
            this.RegisterUtility(new TCPUtility());
            this.RegisterModel(new TCPEventModel());
        }
    }
    public class TCPClientView : MonoBehaviour,IController,ICanRegisterEvent
    {
        //Printer&MsgGetter
        private TCPUtility tcpUtil;
        public Transform tcpMsgContent;
        public GameObject tcpMsgItem;

        public UnityEvent onRecievedOpenDevice;
        public UnityEvent onTCPLinkSuccess;
        public UnityEvent onTCPLinkFaild;
        public UnityEvent onServerConnected;
        public UnityEvent onTCPReLink;

        private string tcpAddress;
        private int tcpPort;
        private int deviceId;
        // Start is called before the first frame update
        void Awake()
        {
            initTCPService();
            DontDestroyOnLoad(this);
            tcpUtil = GetArchitecture().GetUtility<TCPUtility>();
        }

        public void initTCPService() {
            tcpAddress = "127.0.0.1";
            tcpPort = 20000;
            deviceId = 1;

            this.RegisterEvent<LinkStateChangedEvent>(e => {
                if (e.linkState == (int)TCPLinkState.Linking)
                {
                    Debug.Log("TCP��ʼ����");
                    this.GetModel<TCPEventModel>().linkServer();
                }
                if (e.linkState == (int)TCPLinkState.LinkSucess)
                {
                    Debug.Log("TCP���ӳɹ�");
                    this.GetModel<TCPEventModel>().onReceive<LinkSuccessResponse>();
                    this.GetModel<TCPEventModel>().sendRequestCommand(new LinkTCPRequest(deviceId));
                    onTCPLinkSuccess.Invoke();
                }
                if (e.linkState == (int)TCPLinkState.LinkFaild)
                {
                    Debug.Log("TCP����ʧ�ܣ�����ϵ�豸�������Ա");
                    onTCPLinkFaild.Invoke();
                }
            });

            this.RegisterEvent<ResponseMsgEvent>(e =>
            {
                if (e.res.GetType() == typeof(LinkSuccessResponse))
                {
                    Debug.Log("Link Server success");
                    this.GetModel<TCPEventModel>().offReceive<LinkSuccessResponse>();
                    onServerConnected.Invoke();
                }
            });

            this.GetModel<TCPEventModel>().setLinkState((int)TCPLinkState.NoIp);
            this.GetModel<TCPEventModel>().setIP(tcpAddress, tcpPort);
        }

        public void restartTCPService() {
            onTCPReLink.Invoke();
            this.GetModel<TCPEventModel>().closeServer();
            StartCoroutine(waitTwoSecond());
        }
        public IEnumerator waitTwoSecond() {
            yield return new WaitForSeconds(2.0f);
            this.GetModel<TCPEventModel>().setLinkState((int)TCPLinkState.Linking);
        }

        // Update is called once per frame
        void Update()
        {
            //Debug.Log(tcpUtil.Read_TCPClient());
            if (tcpUtil != null && !"".Equals(tcpUtil.getReceivedValue()))
            {
                GameObject item = Instantiate(tcpMsgItem, tcpMsgContent);
                item.GetComponentInChildren<Text>().text = tcpUtil.receivedData;
                this.GetModel<TCPEventModel>().onDataRecived.Invoke(tcpUtil.receivedData);
            }
            if (tcpUtil.getTimeOutState() && tcpUtil.isOpenTCP)
            {
                this.SendEvent(new onLinkException(tcpUtil.exceptionData));
                tcpUtil.isOpenTCP = false;
            }
        }
        private void OnDestroy()
        {
            if (tcpUtil.reciveT != null && tcpUtil.reciveT.ThreadState == ThreadState.Running)
            {
                tcpUtil.reciveT.Abort();
            }
        }

        public IArchitecture GetArchitecture()
        {
            return TCPMangerArchitecture.Interface;
        }
    }
    public class LinkSuccessResponse : AbstractResponse
    {
        public string code;
        public string data;
        public string msg;
        public LinkSuccessResponse() {
            this.code = "";
            this.data = "";
            this.msg = "";
        }
    }

    public class LinkTCPRequest :IRequest{
        public string id;
        public int type;
        public LinkTCPRequest(int id) {
            this.id = id.ToString();
            this.type = 1;
        }
        public string toProtocolData()
        {
            return JsonUtility.ToJson(this);
        }
    }
}