﻿using System.Text;
using JLGames.RocketDriver.Actions.Utils;
using JLGames.RocketDriver.CSharp.Event;
using JLGames.RocketDriver.Games.NetManager;
using JLGames.RocketDriver.Games.NetManager.Virtual;
using UnityEngine;
using UnityEngine.UI;

namespace JLGames.RocketDriver.Samples.NetManagerDemo
{
    public class NetManagerVirtualDemo : MonoBehaviour
    {
        [Header("Left")] [SerializeField] private InputField m_InputRequestId;
        [SerializeField] private InputField m_InputRequestData;
        [SerializeField] private Text m_TextResponse;
        [SerializeField] private Text m_TextOnNotify;
        [Header("Right")] [SerializeField] private Text m_TextOnRequest;
        [SerializeField] private InputField m_InputResponseData;
        [SerializeField] private InputField m_InputNotifyId;
        [SerializeField] private InputField m_InputNotifyData;

        private void Awake()
        {
            InitVirtualServer();
            InitVirtualClient();
        }

        private void OnDestroy()
        {
            var client = NetManager.Shared.GetClient<IVirtualClient>("client");
            client.RemoveEventListener();
            NetManager.Shared.ClearClient(client);

            NetManager.Shared.ClearServer("server");
        }

        private void InitVirtualServer()
        {
            var server = new VirtualServer("server", "none");
            NetManager.Shared.Register(server, true);
            server.RegisterExtension(VirtualReqIds.Id0, OnRequestHandler);
            server.RegisterExtension(VirtualReqIds.Id1, OnRequestHandler);
            server.RegisterExtension(VirtualReqIds.Id2, OnRequestHandler);
            server.RegisterExtension(VirtualReqIds.Id3, OnRequestHandler);
        }

        private void InitVirtualClient()
        {
            var client = new VirtualClient("client", "none");
            NetManager.Shared.Register(client, true);
            var serverProxy = NetManager.Shared.GetServer<IVirtualServer>("server") as IVirtualServerProxy;
            client.Connect(serverProxy);

            client.AddEventListener(VirtualClientEvents.EventResponse, OnClientResponse);
            client.AddEventListener(VirtualClientEvents.EventNotify, OnClientNotify);
        }

        private readonly StringBuilder m_Sb = new StringBuilder();

        private void OnRequestHandler(IVirtualServer server, string protoid, object data)
        {
            DebugUtil.Log("OnRequest:", $"[Pid={protoid}, Data={data}]");
            server.ResponseToClient(protoid, VirtualResultCodes.Succ, m_InputResponseData.text.Trim());
            m_Sb.Clear();
            m_Sb.Append($"RequestPid={protoid}\n");
            m_Sb.Append($"Data={data}");
            m_TextOnRequest.text = m_Sb.ToString();
        }

        private void OnClientNotify(EventData evd)
        {
            var resp = (VirtualServerNotify) evd.Data;
            DebugUtil.Log("OnClientNotify:", $"[Pid={resp.Pid}, Data={resp.Data}]");
            m_Sb.Clear();
            m_Sb.Append($"NotifyPid={resp.Pid}\n");
            m_Sb.Append($"NotifyData={resp.Data}");
            m_TextOnNotify.text = m_Sb.ToString();
        }

        private void OnClientResponse(EventData evd)
        {
            var resp = (VirtualServerResponse) evd.Data;
            DebugUtil.Log("OnClientResponse:", $"[Pid={resp.Pid}, RsCode={resp.RsCode}, Data={resp.Data}]");
            m_Sb.Clear();
            m_Sb.Append($"RequestPid={resp.Pid}\n");
            m_Sb.Append($"RsCode={resp.RsCode}\n");
            m_Sb.Append($"Data={resp.Data}");
            m_TextResponse.text = m_Sb.ToString();
        }

        private void AddServerListeners()
        {
            var server = NetManager.Shared.GetServer<IVirtualServer>("server");
            server.AddEventListener(VirtualServerEvents.EventResponse, OnServerResponse);
            server.AddEventListener(VirtualServerEvents.EventNotify, OnServerNotify);
        }

        private void RemoveServerListeners()
        {
            var server = NetManager.Shared.GetServer<IVirtualServer>("server");
            server.RemoveEventListener(VirtualServerEvents.EventNotify, OnServerNotify);
            server.RemoveEventListener(VirtualServerEvents.EventResponse, OnServerResponse);
        }

        private void OnServerResponse(EventData evd)
        {
            var resp = (VirtualServerResponse) evd.Data;
            DebugUtil.Log("OnServerResponse:", $"[Pid={resp.Pid}, RsCode={resp.RsCode}, Data={resp.Data}]");
        }

        private void OnServerNotify(EventData evd)
        {
            var resp = (VirtualServerNotify) evd.Data;
            DebugUtil.Log("OnServerNotify:", $"[Pid={resp.Pid}, Data={resp.Data}]");
        }

        public void OnClickRequest()
        {
            var protoId = m_InputRequestId.text.Trim();
            if (string.IsNullOrEmpty(protoId))
            {
                DebugUtil.LogWarning("Request ProtoId is lack!");
                return;
            }

            NetManager.Shared.GetClient<IVirtualClient>("client").Request(protoId, m_InputRequestData.text.Trim());
        }

        public void OnClickNotify()
        {
            var pid = m_InputNotifyId.text.Trim();
            if (string.IsNullOrEmpty(pid))
            {
                DebugUtil.LogWarning("Notify ProtoId is lack!");
                return;
            }

            NetManager.Shared.GetServer<IVirtualServer>("server").NotifyToClient(pid, m_InputNotifyData.text.Trim());
        }
    }
}