﻿using System;
using BeardedManStudios.Network;
using Dissonance.Networking;
using BNetworking = BeardedManStudios.Network.Networking;

namespace Dissonance.Integrations.ForgeNetworking
{
    public class ForgeClient
        : BaseClient<ForgeServer, ForgeClient, ForgePeer>
    {
        private readonly ForgeCommsNetwork _network;

        private readonly BMSByte _sendBuffer = new BMSByte();

        private NetWorker _connected;

        public ForgeClient(ForgeCommsNetwork network)
            : base(network)
        {
            _network = network;
        }

        public override void Connect()
        {
            //Add receive event for packets coming from the server
            _connected = BNetworking.PrimarySocket;
            _connected.AddCustomDataReadEvent(unchecked((uint)_network.SystemMessagesChannelToClient), ReceiveFromNetwork);
            _connected.AddCustomDataReadEvent(unchecked((uint)_network.VoiceDataChannelToClient), ReceiveFromNetwork);

            Connected();
        }

        public override void Disconnect()
        {
            if (_connected != null)
            {
                _connected.RemoveCustomDataReadEvent(unchecked((uint)_network.SystemMessagesChannelToClient));
                _connected.RemoveCustomDataReadEvent(unchecked((uint)_network.VoiceDataChannelToClient));
                _connected = null;
            }

            base.Disconnect();
        }

        private void ReceiveFromNetwork(NetworkingPlayer source, NetworkingStream data)
        {
            var packet = new ArraySegment<byte>(data.Bytes.byteArr, data.Bytes.StartPointer, data.Bytes.Size);
            NetworkReceivedPacket(packet);
        }

        protected override void ReadMessages()
        {
            //This is empty, so where do we read the forge messages!?
            //Forge delivers it's packets in event handlers, look above in `Connect()` to find the event handlers being setup
        }

        private void Send(ArraySegment<byte> packet, uint channel, bool reliable)
        {
            if (_network.PreprocessPacketToServer(packet, channel, reliable))
                return;

            _sendBuffer.Clear();
            _sendBuffer.BlockCopy(packet.Array, packet.Offset, packet.Count);

            BNetworking.WriteCustom(
                channel,
                BNetworking.PrimarySocket,
                _sendBuffer,
                reliable,
                NetworkReceivers.Server
            );
        }

        protected override void SendReliable(ArraySegment<byte> packet)
        {
            Send(packet, unchecked((uint)_network.SystemMessagesChannelToServer), true);
        }

        protected override void SendUnreliable(ArraySegment<byte> packet)
        {
            Send(packet, unchecked((uint)_network.VoiceDataChannelToServer), false);
        }
    }
}
