using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using QCRPG.Framework;

namespace QCRPG.TSL.BT;

public class AclDataBufferHandler
{
	private int btBufferSize;

	private int leBufferSize;

	private SpecificPacketNotifier specificPacketNotifier;

	private BTAPI btAPI;

	private ManualResetEvent parentShutdownEvent;

	private Dictionary<int, ACLDataQueue> btConnectionAclDataQueues = new Dictionary<int, ACLDataQueue>();

	private Dictionary<int, ACLDataQueue> leConnectionAclDataQueues = new Dictionary<int, ACLDataQueue>();

	public AclDataBufferHandler(SpecificPacketNotifier specificPacketNotifier, BTAPI btAPI, ManualResetEvent parentShutdownEvent = null)
	{
		this.specificPacketNotifier = specificPacketNotifier;
		this.btAPI = btAPI;
		this.parentShutdownEvent = parentShutdownEvent;
	}

	public void AddBTConnection(int connectionHandle)
	{
		ACLDataQueue aCLDataQueue = new ACLDataQueue(connectionHandle, specificPacketNotifier, btAPI, parentShutdownEvent);
		if (btBufferSize != 0)
		{
			aCLDataQueue.SetBufferSize(btBufferSize);
			btConnectionAclDataQueues[connectionHandle] = aCLDataQueue;
		}
		else
		{
			aCLDataQueue.SetBufferSize(leBufferSize);
			leConnectionAclDataQueues[connectionHandle] = aCLDataQueue;
		}
		InitializeAclBuffers();
	}

	public void AddLEConnection(int connectionHandle)
	{
		ACLDataQueue aCLDataQueue = new ACLDataQueue(connectionHandle, specificPacketNotifier, btAPI, parentShutdownEvent);
		if (leBufferSize != 0)
		{
			aCLDataQueue.SetBufferSize(leBufferSize);
			leConnectionAclDataQueues[connectionHandle] = aCLDataQueue;
		}
		else
		{
			aCLDataQueue.SetBufferSize(btBufferSize);
			btConnectionAclDataQueues[connectionHandle] = aCLDataQueue;
		}
		InitializeAclBuffers();
	}

	public void RemoveConnection(int connectionHandle)
	{
		if (btConnectionAclDataQueues.ContainsKey(connectionHandle))
		{
			btConnectionAclDataQueues.Remove(connectionHandle);
		}
		if (leConnectionAclDataQueues.ContainsKey(connectionHandle))
		{
			leConnectionAclDataQueues.Remove(connectionHandle);
		}
		InitializeAclBuffers();
	}

	public ACLDataQueue GetAclDataQueue(int connectionHandle)
	{
		if (btConnectionAclDataQueues.ContainsKey(connectionHandle))
		{
			return btConnectionAclDataQueues[connectionHandle];
		}
		if (leConnectionAclDataQueues.ContainsKey(connectionHandle))
		{
			return leConnectionAclDataQueues[connectionHandle];
		}
		return null;
	}

	public void SetAclBuffers(int btBufferSize, int leBufferSize)
	{
		if (btBufferSize == 0 && leBufferSize == 0)
		{
			throw new Exception("Both BT and LE buffer sizes cannot be 0.");
		}
		this.btBufferSize = btBufferSize;
		this.leBufferSize = leBufferSize;
	}

	private void InitializeAclBuffers()
	{
		if (btBufferSize == 0)
		{
			ShareBuffer(leBufferSize, leConnectionAclDataQueues);
			return;
		}
		if (leBufferSize == 0)
		{
			ShareBuffer(btBufferSize, btConnectionAclDataQueues);
			return;
		}
		ShareBuffer(btBufferSize, btConnectionAclDataQueues);
		ShareBuffer(leBufferSize, leConnectionAclDataQueues);
	}

	private void ShareBuffer(int maxAvailable, Dictionary<int, ACLDataQueue> aclDataQueues)
	{
		if (aclDataQueues.Count != 0)
		{
			int num = maxAvailable / aclDataQueues.Count;
			int[] array = aclDataQueues.Keys.ToArray();
			int num2 = 0;
			for (int i = 0; i < array.Length - 1; i++)
			{
				aclDataQueues[array[i]].ResizeBufferSize(num);
				num2 += num;
			}
			aclDataQueues[array[array.Length - 1]].ResizeBufferSize(maxAvailable - num2);
		}
	}
}
