﻿using BNEBotCore;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace BNEBotLauncher
{
  public class BotManagerConnection
  {
    public BotManagerConnection(TcpClient client, Action exitAction)
    {
      m_ExitAction = exitAction;

      Client = client;
      Stream = Client.GetStream();
      Writer = new BinaryWriter(Stream);
      Reader = new BinaryReader(Stream);
    }

    public TcpClient Client
    {
      get;
      private set;
    }

    public NetworkStream Stream
    {
      get;
      private set;
    }

    public BinaryWriter Writer
    {
      get;
      private set;
    }

    public BinaryReader Reader
    {
      get;
      private set;
    }

    private Action m_ExitAction;

    // Send a message to this manager
    public void SendMessage(NetCommand msg)
    {
      Writer.Write((int)msg.Type);

      if (msg.CompressedData == null)
      {
        Writer.Write(0);
      }
      else
      {
        Writer.Write(msg.CompressedData.Length);
        Writer.Write(msg.CompressedData);
      }
    }

    // Receive incoming commands
    public void Receive()
    {
      while (Client.Available > 0)
      {
        NetCommandType cmdType = (NetCommandType)Reader.ReadInt32();
        int dataSize = Reader.ReadInt32();
        if (dataSize > 0)
        {
          byte[] data = Reader.ReadBytes(dataSize);

          switch (cmdType)
          {
            case NetCommandType.KillBot:
              OnKillBots(data);
              break;

            case NetCommandType.TerminateServer:
              m_ExitAction();
              break;

            case NetCommandType.SpawnBots:
              OnSpawnBotsCommand(data);
              break;
          }
        }
      }
    }

    private void OnKillBots(byte[] data)
    {
      KillBotCommand cmd = new KillBotCommand()
      {
        CompressedData = data
      };
      cmd.Restore();

      if (cmd.BotsToKill == null || cmd.BotsToKill.Count == 0)
      {
        // Just kill all
        BotProcessManager.KillAll();
      }
      else
      {
        foreach (string botName in cmd.BotsToKill)
        {
          BotProcessManager.KillBot(botName);
        }
      }
    }

    private void OnSpawnBotsCommand(byte[] data)
    {
      SpawnBotsCommand cmd = new SpawnBotsCommand()
      {
        CompressedData = data
      };
      cmd.Restore();

      if (cmd.Info != null)
      {
        BotProcessManager.QueueSpawnCommand(cmd.Info);
      }
    }
  }
}
