using System;
using NAudio.Wave;

namespace Whisper
{
    internal class NAudioClass : IDisposable
    {
        private WaveInEvent waveIn;
        private WaveFileWriter waveWriter;
        private readonly int deviceNumber;
        private readonly string outputFilePath;
        private bool isDisposed = false;

        public NAudioClass(int deviceNumber, string outputFilePath)
        {
            this.deviceNumber = deviceNumber;
            this.outputFilePath = outputFilePath;
        }

        public void StartRecording()
        {
            try
            {
                waveIn = new WaveInEvent
                {
                    DeviceNumber = deviceNumber,
                    WaveFormat = new WaveFormat(44100, 16, 1),
                    BufferMilliseconds = 20
                };

                waveWriter = new WaveFileWriter(outputFilePath, waveIn.WaveFormat);
                waveIn.DataAvailable += WaveIn_DataAvailable;
                waveIn.StartRecording();
                Console.WriteLine("Recording started. Press Enter to stop and save the file.");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error occurred: {ex.Message}");
            }
        }

        private void WaveIn_DataAvailable(object? sender, WaveInEventArgs e)
        {
            if (waveWriter == null) return;

            waveWriter.Write(e.Buffer, 0, e.BytesRecorded);
            waveWriter.Flush();
            // Convert the audio buffer to an array of 16-bit integers
            Int16[] values = new Int16[e.Buffer.Length / 2];
            Buffer.BlockCopy(e.Buffer, 0, values, 0, e.Buffer.Length);

            // Determine the highest audio level as a fraction of the maximum possible value
            float fraction = (float)values.Max() / 32768;

            // Create a level meter bar and display it in the console
            string bar = new('#', (int)(fraction * 70));
            string meter = "[" + bar.PadRight(60, '-') + "]";
            Console.CursorLeft = 0;
            Console.CursorVisible = false;
            Console.Write($"{meter} {fraction * 100:00.0}%");
            // Existing level meter implementation...
        }

        public void StopRecording()
        {
            if (waveIn == null) return;
            Console.WriteLine("");
            try
            {
                waveIn.StopRecording();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error occurred: {ex.Message}");
            }
            finally
            {
                Dispose();
                Console.WriteLine("");
                Console.WriteLine($"Audio recorded and saved as '{outputFilePath}'");
            }
        }

        public void Dispose()
        {
            if (!isDisposed)
            {
                waveIn?.Dispose();
                waveWriter?.Close();
                waveWriter?.Dispose();
                isDisposed = true;
            }
        }
    }
}