using UnityEngine;
using Unity.Collections;
using Unity.Netcode;

//自定义的Unnamed消息处理。结构跟普通差不多,只是用来处理自定义的数据,而不是NetCode规定的NetworkVariable
public class UnnamedStringMessageHandler : CustomUnnamedMessageHandler<string>
{
    //定义唯一的消息ID,作为消息头,可以用其他方式构建消息id
    protected override byte MessageType()
    {
        return 1;
    }

    public override void OnNetworkSpawn()
    {
        base.OnNetworkSpawn();

        if(IsServer)
        {
            NetworkManager.OnClientConnectedCallback += OnClientConnectedCallback;
        }
        else
        {
            //客户端,给服务器发消息
            SendUnnamedMessage("I am a client connecting!");
        }
    }

    public override void OnNetworkDespawn()
    {
        base.OnNetworkDespawn();

        NetworkManager.OnClientConnectedCallback -= OnClientConnectedCallback;
    }

    //其他客户端连接上来,通知所有客户端
    private void OnClientConnectedCallback(ulong clientId)
    {
        SendUnnamedMessage($"welcome the newly joined client ({clientId})!");
    }

    //解析消息
    protected override void OnReceivedUnnamedMessage(ulong clientId, FastBufferReader reader)
    {
        var stringMessage = string.Empty;
        reader.ReadValueSafe(out stringMessage);
        if(IsServer)
        {
            Debug.Log($"Server received unnamed message of type ({MessageType()}) from client " +
                $"({clientId}) that contained the string: \"{stringMessage}\"");

            //可以通知所有客户端
            SendUnnamedMessage($"Newly connected client sent this greeting: \"{stringMessage}\"");
        }
        else
        {
            Debug.Log(stringMessage);
        }
    }

    //发送数据(payload)
    public override void SendUnnamedMessage(string dataToSend)
    {
        var writer = new FastBufferWriter(1100, Allocator.Temp);
        var customMessagingManager = NetworkManager.CustomMessagingManager;
        using(writer)
        {
            //写入消息头
            writer.WriteValueSafe(MessageType());
            //写入消息体
            writer.WriteValueSafe(dataToSend);
            if(IsServer)
            {
                //发送消息,SendUnnamedMessageToAll方法只能Server调用,Client调用会报异常
                customMessagingManager.SendUnnamedMessageToAll(writer);
            }
            else
            {
                //发送给服务器。SendUnnamedMessage方法可以Client和Server之间互相调用发送
                //NetworkManager.ServerClientId表示服务器的id。为了保持一致性,服务端也要有一个ClientID,便于客户端向服务端发送消息。默认为0,不能更改。
                //感觉取名ServerId会更好?
                customMessagingManager.SendUnnamedMessage(NetworkManager.ServerClientId, writer);
            }
        }
    }
}

//消息处理基类,必须继承NetworkBehaviour。T是要发送的消息类型
public class CustomUnnamedMessageHandler<T> : NetworkBehaviour
{
    protected virtual byte MessageType()
    {
        return 0;
    }

    public override void OnNetworkSpawn()
    {
        //三种模式都要订阅
        NetworkManager.CustomMessagingManager.OnUnnamedMessage += ReceiveMessage;
    }

    public override void OnNetworkDespawn()
    {
        NetworkManager.CustomMessagingManager.OnUnnamedMessage -= ReceiveMessage;
    }

    //自定义处理,可以进行消息解析,并处理
    protected virtual void OnReceivedUnnamedMessage(ulong clientId, FastBufferReader reader)
    {

    }

    //处理收到的消息数据
    private void ReceiveMessage(ulong clientId, FastBufferReader reader)
    {
        //判断消息类型
        var messageType = (byte)0;
        reader.ReadValueSafe(out messageType);
        //解析消息
        if(messageType == MessageType())
        {
            OnReceivedUnnamedMessage(clientId, reader);
        }
    }

    //发送消息
    public virtual void SendUnnamedMessage(T dataToSend)
    {
    }

}