The left to right selection like when you hover your cursor over the left and right sides of your selection it becomes a stretch cursor, I want it to never cancel out of selection unless the cursor is not the stretch cursor during the click because obviously clicking outside of the selection cancels the selection and that's fine but that is how I think this should be fixed. Also I want it to after you click the Save As Crop button and it does it's thing, I want it to zoom out the waveform fully. Please provide entire code back no commentary.

using System;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using NAudio.Wave;
using Timer = System.Windows.Forms.Timer;

namespace ByteBreath
{
    public partial class AudioEditorForm : Form
    {
        private DataSetMaker _datasetMaker;
        public Color mainColor;
        public Color accentColor;
        public Color textColor;

        private float[] audioSamples; // interleaved samples: totalFrames * channels
        private WaveFormat waveFormat;
        private string currentFilePath;
        public string SelectionPath;
        private bool isSelecting = false;
        private bool isMovingSelection = false;
        private int selectionStart = -1; // frame index
        private int selectionEnd = -1;   // frame index

        private int sampleRate;

        private WaveOutEvent waveOut;
        private BufferedWaveProvider bufferedWaveProvider;

        private Timer playbackTimer;
        private long playStartFrame = 0;
        private long playEndFrame = 0;
        private bool isPlaying = false;

        private int viewStartFrame = 0; // viewing frames start (for zooming and scrolling)
        private int viewFrames = 0;
        private const int minViewFrames = 1000;
        private const int maxViewFramesFactor = 1;

        private bool isMouseInWaveform = false;

        // New fields for right-click panning
        private bool isPanning = false;
        private int lastPanMouseX = 0;

        // New fields for selection moving
        private int moveSelectionStartFrameDiff = 0;
        private int lastMouseX = 0;

        // New fields for selection resizing
        private bool isResizingLeft = false;
        private bool isResizingRight = false;
        private const int selectionEdgeSensitivity = 5; // pixels

        public AudioEditorForm(DataSetMaker dataSetMaker)
        {
            InitializeComponent();
            waveformPanel.Paint += WaveformPanel_Paint;
            waveformPanel.MouseDown += WaveformPanel_MouseDown;
            waveformPanel.MouseMove += WaveformPanel_MouseMove;
            waveformPanel.MouseUp += WaveformPanel_MouseUp;
            waveformPanel.MouseWheel += WaveformPanel_MouseWheel;
            waveformPanel.MouseEnter += WaveformPanel_MouseEnter;
            waveformPanel.MouseLeave += WaveformPanel_MouseLeave;
            waveformPanel.KeyDown += WaveformPanel_KeyDown;

            playbackTimer = new Timer();
            playbackTimer.Interval = 30;
            playbackTimer.Tick += PlaybackTimer_Tick;

            this.KeyPreview = true;
            this.KeyDown += AudioEditorForm_KeyDown;

            btnSave.Enabled = false;
            TopMost = true;
            _datasetMaker = dataSetMaker;
        }

        private void WaveformPanel_MouseEnter(object sender, EventArgs e)
        {
            isMouseInWaveform = true;
            waveformPanel.Focus();
        }

        private void WaveformPanel_MouseLeave(object sender, EventArgs e)
        {
            if (!isSelecting && !isMovingSelection && !isResizingLeft && !isResizingRight)
            {
                waveformPanel.Cursor = Cursors.Default;
            }
            isMouseInWaveform = false;
        }

        private void WaveformPanel_MouseWheel(object sender, MouseEventArgs e)
        {
            if (isMouseInWaveform)
                ZoomWaveform(e);
        }

        private void ZoomWaveform(MouseEventArgs e)
        {
            if (audioSamples == null || audioSamples.Length == 0)
                return;

            int panelWidth = waveformPanel.ClientSize.Width;
            if (panelWidth <= 0)
                return;

            if (viewFrames == 0)
            {
                int totalFrames = audioSamples.Length / waveFormat.Channels;
                viewFrames = totalFrames;
                viewStartFrame = 0;
            }

            float zoomFactor = 1.0f - (e.Delta / 1200.0f);
            if (zoomFactor <= 0) zoomFactor = 0.1f;

            int newViewFrames = (int)(viewFrames * zoomFactor);

            int minFrames = minViewFrames;
            int maxFrames = (audioSamples.Length / waveFormat.Channels) * maxViewFramesFactor;
            if (maxFrames < minFrames) maxFrames = minFrames;

            if (newViewFrames < minFrames) newViewFrames = minFrames;
            if (newViewFrames > maxFrames) newViewFrames = maxFrames;

            if (newViewFrames == viewFrames)
                return;

            double mouseRatio = (double)e.X / panelWidth;
            mouseRatio = Math.Clamp(mouseRatio, 0.0, 1.0);

            long mouseFrame = viewStartFrame + (long)(mouseRatio * viewFrames);
            long newViewStartFrame = mouseFrame - (long)(mouseRatio * newViewFrames);

            if (newViewStartFrame < 0) newViewStartFrame = 0;
            if (newViewStartFrame + newViewFrames > audioSamples.Length / waveFormat.Channels)
                newViewStartFrame = (audioSamples.Length / waveFormat.Channels) - newViewFrames;
            if (newViewStartFrame < 0)
                newViewStartFrame = 0;

            viewStartFrame = (int)newViewStartFrame;
            viewFrames = newViewFrames;

            waveformPanel.Invalidate();
        }

        private void SplitAndSaveChunks(string filePath, TimeSpan totalDuration, WaveFormat originalFormat)
        {
            try
            {
                using var reader = new AudioFileReader(filePath);
                int channels = reader.WaveFormat.Channels;
                int sampleRateLocal = reader.WaveFormat.SampleRate;
                int samplesPerSecond = sampleRateLocal * channels;
                int chunkSeconds = 20 * 60; // 20 minutes in seconds
                int chunkSamples = samplesPerSecond * chunkSeconds;

                string directory = Path.GetDirectoryName(filePath);
                string originalFileName = Path.GetFileNameWithoutExtension(filePath);
                string extension = Path.GetExtension(filePath);

                int totalSamples = (int)(reader.Length / 4); // float samples
                int totalChunks = (totalSamples + chunkSamples - 1) / chunkSamples;

                for (int chunkIndex = 0; chunkIndex < totalChunks; chunkIndex++)
                {
                    int samplesToRead = Math.Min(chunkSamples, totalSamples - chunkIndex * chunkSamples);
                    float[] chunkBuffer = new float[samplesToRead];

                    reader.Position = chunkIndex * chunkSamples * 4;
                    int readSamples = 0;
                    int offset = 0;
                    while (offset < samplesToRead)
                    {
                        int needed = samplesToRead - offset;
                        int readNow = reader.Read(chunkBuffer, offset, needed);
                        if (readNow == 0)
                            break;
                        offset += readNow;
                    }

                    string chunkFileName = $"{originalFileName}_Part{chunkIndex + 1}{extension}";
                    string chunkFilePath = Path.Combine(directory, chunkFileName);

                    using (var writer = new WaveFileWriter(chunkFilePath, originalFormat))
                    {
                        if (originalFormat.Encoding == WaveFormatEncoding.IeeeFloat)
                        {
                            writer.WriteSamples(chunkBuffer, 0, offset);
                        }
                        else if (originalFormat.BitsPerSample == 16)
                        {
                            short[] int16Samples = new short[offset];
                            for (int i = 0; i < offset; i++)
                            {
                                float sample = chunkBuffer[i];
                                sample = Math.Max(-1f, Math.Min(1f, sample));
                                int16Samples[i] = (short)(sample * short.MaxValue);
                            }
                            byte[] bytes = new byte[int16Samples.Length * 2];
                            Buffer.BlockCopy(int16Samples, 0, bytes, 0, bytes.Length);
                            writer.Write(bytes, 0, bytes.Length);
                        }
                        else
                        {
                            MessageBox.Show("Unsupported bit depth: " + originalFormat.BitsPerSample);
                            return;
                        }
                    }
                }

                // Delete original large file
                try
                {
                    waveOut?.Stop();
                    waveOut?.Dispose();
                    waveOut = null;
                }
                catch { }
                try
                {
                    File.Delete(filePath);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Failed to delete original large file: " + ex.Message);
                }

                MessageBox.Show("Audio file split into 20 minute chunks and original file deleted.", "Split Complete", MessageBoxButtons.OK, MessageBoxIcon.Information);
                this.Close(); // Close current editor form since the original file is deleted.
            }
            catch (Exception ex)
            {
                MessageBox.Show("Failed to split and save chunks: " + ex.Message);
            }
        }

        private void LoadWaveFile(string path)
        {
            if (string.IsNullOrWhiteSpace(path))
                return;

            try
            {
                currentFilePath = path;

                waveOut?.Stop();
                waveOut?.Dispose();
                waveOut = null;
                bufferedWaveProvider = null;

                audioSamples = null;
                selectionStart = -1;
                selectionEnd = -1;

                // Check file length and ask about splitting if longer than 20 minutes
                using (var readerDurationCheck = new AudioFileReader(path))
                {
                    double totalSeconds = readerDurationCheck.TotalTime.TotalSeconds;
                    if (totalSeconds > 20 * 60)
                    {
                        DialogResult dr = MessageBox.Show(
                            "Audio file is larger than 20 minutes. Would you like to split it into 20 minute chunks now?",
                            "Large File Warning",
                            MessageBoxButtons.YesNo,
                            MessageBoxIcon.Warning);
                        if (dr == DialogResult.Yes)
                        {
                            SplitAndSaveChunks(path, readerDurationCheck.TotalTime, readerDurationCheck.WaveFormat);
                            return;
                        }
                    }
                }

                using (var reader = new AudioFileReader(path))
                {
                    waveFormat = reader.WaveFormat;
                    sampleRate = waveFormat.SampleRate;

                    long totalFloatSamplesLong = reader.Length / 4;

                    if (totalFloatSamplesLong > int.MaxValue)
                        throw new InvalidOperationException("Audio file too large.");

                    int sampleCount = (int)totalFloatSamplesLong;
                    audioSamples = new float[sampleCount];

                    int offset = 0;
                    int samplesRead;
                    var buffer = new float[1024];

                    reader.Position = 0;
                    while ((samplesRead = reader.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        int copyCount = Math.Min(samplesRead, sampleCount - offset);
                        Array.Copy(buffer, 0, audioSamples, offset, copyCount);
                        offset += copyCount;
                    }
                }

                int totalFrames = audioSamples.Length / waveFormat.Channels;

                viewStartFrame = 0;
                viewFrames = totalFrames;

                btnSave.Enabled = true;

                playStartFrame = 0;
                playEndFrame = totalFrames - 1;

                waveOut = new WaveOutEvent();
                waveOut.PlaybackStopped += WaveOut_PlaybackStopped;

                bufferedWaveProvider = new BufferedWaveProvider(waveFormat)
                {
                    BufferLength = audioSamples.Length * waveFormat.BlockAlign
                };
                bufferedWaveProvider.ClearBuffer();

                byte[] byteBuffer = new byte[audioSamples.Length * 4];
                Buffer.BlockCopy(audioSamples, 0, byteBuffer, 0, byteBuffer.Length);
                bufferedWaveProvider.AddSamples(byteBuffer, 0, byteBuffer.Length);

                waveOut.Init(bufferedWaveProvider);

                waveformPanel.Invalidate();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Failed to load WAV: " + ex.Message);
            }
        }

        private void WaveformPanel_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.Clear(mainColor);
            if (audioSamples == null || audioSamples.Length == 0)
            {
                using (var brush = new SolidBrush(accentColor))
                    e.Graphics.DrawString("No audio loaded", this.Font, brush, new PointF(10, 10));
                return;
            }

            int w = waveformPanel.ClientSize.Width;
            int h = waveformPanel.ClientSize.Height;

            int totalFrames = audioSamples.Length / waveFormat.Channels;

            using (var pen = new Pen(accentColor))
            {
                if (viewFrames == 0)
                    viewFrames = totalFrames;
                if (viewStartFrame + viewFrames > totalFrames)
                    viewStartFrame = totalFrames - viewFrames;

                if (viewStartFrame < 0) viewStartFrame = 0;
                if (viewFrames <= 0) viewFrames = totalFrames;

                int framesPerPixel = Math.Max(1, viewFrames / w);

                for (int x = 0; x < w; x++)
                {
                    int startFrame = viewStartFrame + x * framesPerPixel;
                    if (startFrame >= totalFrames)
                        break;
                    int endFrame = Math.Min(totalFrames, startFrame + framesPerPixel);

                    float min = 1f;
                    float max = -1f;
                    for (int f = startFrame; f < endFrame; f++)
                    {
                        float sumSample = 0f;
                        for (int c = 0; c < waveFormat.Channels; c++)
                        {
                            float val = audioSamples[f * waveFormat.Channels + c];
                            sumSample += val;
                        }
                        float valAvg = sumSample / waveFormat.Channels;

                        if (valAvg < min) min = valAvg;
                        if (valAvg > max) max = valAvg;
                    }

                    int yMax = (int)((1 - (max + 1) / 2) * h);
                    int yMin = (int)((1 - (min + 1) / 2) * h);

                    e.Graphics.DrawLine(pen, x, yMin, x, yMax);
                }
            }

            // Draw selection rectangle
            if (selectionStart >= 0 && selectionEnd >= 0 && selectionEnd != selectionStart)
            {
                int wFrames = viewFrames;
                int visibleStart = viewStartFrame;
                int x1 = (int)((double)(selectionStart - visibleStart) / wFrames * w);
                int x2 = (int)((double)(selectionEnd - visibleStart) / wFrames * w);

                int rectX = Math.Min(x1, x2);
                int rectW = Math.Abs(x2 - x1);

                if (rectW > 0)
                {
                    using (var selectionBrush = new SolidBrush(Color.FromArgb(100, mainColor)))
                        e.Graphics.FillRectangle(selectionBrush, rectX, 0, rectW, h);

                    using (var pen = new Pen(textColor, 2))
                        e.Graphics.DrawRectangle(pen, rectX, 0, rectW, h - 1);

                    // Draw realtime text anchored centered in the selection rectangle
                    double selectedFrames = Math.Abs(selectionEnd - selectionStart);
                    double selectedSeconds = selectedFrames / (double)sampleRate;
                    string selectionDurationText = $"{selectedSeconds:F2} s selected";

                    using (var font = new Font(this.Font.FontFamily, 10, FontStyle.Bold))
                    using (var brush = new SolidBrush(textColor))
                    {
                        SizeF textSize = e.Graphics.MeasureString(selectionDurationText, font);
                        float textX = rectX + rectW / 2f - textSize.Width / 2f;
                        float textY = h / 2f - textSize.Height / 2f;

                        // Draw text background for better visibility
                        using (var bgBrush = new SolidBrush(Color.FromArgb(160, mainColor)))
                        {
                            RectangleF bgRect = new RectangleF(textX - 4, textY - 2, textSize.Width + 8, textSize.Height + 4);
                            e.Graphics.FillRectangle(bgBrush, bgRect);
                        }

                        e.Graphics.DrawString(selectionDurationText, font, brush, textX, textY);
                    }
                }
            }

            // Draw playback position line
            if (isPlaying && audioSamples != null && waveOut != null)
            {
                int bytesPerSample = sizeof(float);
                int bytesPerFrame = bytesPerSample * waveFormat.Channels;
                long currentFrame = 0;

                try
                {
                    currentFrame = waveOut.GetPosition() / bytesPerFrame + playStartFrame;
                }
                catch
                {
                    currentFrame = 0;
                }

                if (currentFrame > audioSamples.Length / waveFormat.Channels)
                    currentFrame = audioSamples.Length / waveFormat.Channels;

                long segmentLength = playEndFrame - playStartFrame + 1;
                if (segmentLength <= 0) segmentLength = audioSamples.Length / waveFormat.Channels;

                if (currentFrame > playEndFrame)
                    currentFrame = playEndFrame;

                int x = 0;

                if (selectionStart >= 0 && selectionEnd >= 0 && selectionStart != selectionEnd)
                {
                    int wFrames = viewFrames;
                    int visibleStart = viewStartFrame;

                    int sx1 = (int)((double)(selectionStart - visibleStart) / wFrames * w);
                    int sx2 = (int)((double)(selectionEnd - visibleStart) / wFrames * w);

                    int rectX = Math.Min(sx1, sx2);
                    int rectW = Math.Abs(sx2 - sx1);

                    if (segmentLength > 0)
                        x = rectX + (int)((double)(currentFrame - playStartFrame) / segmentLength * rectW);
                    else
                        x = rectX;
                }
                else
                {
                    int wFrames = viewFrames;
                    int visibleStart = viewStartFrame;
                    x = (int)((double)(currentFrame - visibleStart) / wFrames * w);
                }

                if (x >= 0 && x < w)
                {
                    using (var pen = new Pen(textColor, 2))
                        e.Graphics.DrawLine(pen, x, 0, x, h);
                }
            }

            DrawTimeStamps(e.Graphics, w, h);
        }

        private void DrawTimeStamps(Graphics g, int width, int height)
        {
            if (waveFormat == null || audioSamples == null || audioSamples.Length == 0)
                return;

            int totalFrames = audioSamples.Length / waveFormat.Channels;
            if (viewFrames <= 0) return;

            int maxLabels = width / 60;
            if (maxLabels < 2) maxLabels = 2;

            int intervalFrames = viewFrames / maxLabels;
            if (intervalFrames <= 0) intervalFrames = 1;

            using (var brush = new SolidBrush(textColor))
            using (var font = new Font(this.Font.FontFamily, 8))
            using (var pen = new Pen(textColor))
            {
                int yOffset = height - 16;
                int tickHeight = 8;

                for (int i = 0; i <= maxLabels; i++)
                {
                    int framePos = viewStartFrame + i * intervalFrames;
                    if (framePos > totalFrames) framePos = totalFrames;

                    double seconds = (double)framePos / sampleRate;
                    int minutesPart = (int)(seconds / 60);
                    int secondsPart = (int)(seconds % 60);

                    string timeLabel = $"{minutesPart:D2}:{secondsPart:D2}";

                    double positionRatio = (double)(framePos - viewStartFrame) / viewFrames;
                    int x = (int)(positionRatio * width);

                    if (x < 0) x = 0;
                    if (x > width) x = width;

                    g.DrawLine(pen, x, height - tickHeight, x, height);

                    SizeF size = g.MeasureString(timeLabel, font);

                    int textX = x - (int)(size.Width / 2);
                    if (textX < 0) textX = 0;
                    if (textX + size.Width > width) textX = width - (int)size.Width;

                    g.DrawString(timeLabel, font, brush, new PointF(textX, yOffset));
                }
            }
        }

        private void WaveformPanel_MouseDown(object sender, MouseEventArgs e)
        {
            if (audioSamples == null) return;

            int w = waveformPanel.ClientSize.Width;
            int totalFrames = audioSamples.Length / waveFormat.Channels;

            if (e.Button == MouseButtons.Left)
            {
                int frameIndex = viewStartFrame + (int)((double)e.X / w * viewFrames);
                frameIndex = Math.Clamp(frameIndex, 0, totalFrames - 1);

                // Check if clicking near edges for resizing
                if (selectionStart >= 0 && selectionEnd >= 0 && selectionEnd != selectionStart)
                {
                    int selStart = Math.Min(selectionStart, selectionEnd);
                    int selEnd = Math.Max(selectionStart, selectionEnd);

                    int xStart = (int)((double)(selStart - viewStartFrame) / viewFrames * w);
                    int xEnd = (int)((double)(selEnd - viewStartFrame) / viewFrames * w);

                    // Check left edge
                    if (e.X >= xStart - selectionEdgeSensitivity && e.X <= xStart + selectionEdgeSensitivity)
                    {
                        isResizingLeft = true;
                        waveOut.Stop();
                        isPlaying = false;
                        playbackTimer.Stop();
                        return;
                    }
                    // Check right edge
                    if (e.X >= xEnd - selectionEdgeSensitivity && e.X <= xEnd + selectionEdgeSensitivity)
                    {
                        isResizingRight = true;
                        waveOut.Stop();
                        isPlaying = false;
                        playbackTimer.Stop();
                        return;
                    }

                    // Check if clicking inside existing selection to start moving
                    if (e.X >= xStart && e.X <= xEnd)
                    {
                        isMovingSelection = true;
                        lastMouseX = e.X;
                        moveSelectionStartFrameDiff = frameIndex - selStart;

                        // Stop playback when moving
                        if (isPlaying)
                        {
                            waveOut?.Stop();
                            isPlaying = false;
                            playbackTimer.Stop();
                        }

                        return;
                    }
                }

                // Otherwise, begin selection
                isSelecting = true;

                selectionStart = frameIndex;
                selectionEnd = frameIndex;
                waveformPanel.Invalidate();
            }
            else if (e.Button == MouseButtons.Right)
            {
                isPanning = true;
                lastPanMouseX = e.X;
                waveformPanel.Cursor = Cursors.Hand;
            }
        }

        private void WaveformPanel_MouseMove(object sender, MouseEventArgs e)
        {
            if (audioSamples == null) return;

            int w = waveformPanel.ClientSize.Width;
            int totalFrames = audioSamples.Length / waveFormat.Channels;

            if (isResizingLeft && e.Button == MouseButtons.Left)
            {
                int frameIndex = viewStartFrame + (int)((double)e.X / w * viewFrames);
                frameIndex = Math.Clamp(frameIndex, 0, totalFrames - 1);

                int selEnd = selectionEnd;
                if (frameIndex >= selEnd) frameIndex = selEnd - 1;
                if (frameIndex < 0) frameIndex = 0;

                selectionStart = frameIndex;

                waveformPanel.Invalidate();
                return;
            }
            else if (isResizingRight && e.Button == MouseButtons.Left)
            {
                int frameIndex = viewStartFrame + (int)((double)e.X / w * viewFrames);
                frameIndex = Math.Clamp(frameIndex, 0, totalFrames - 1);

                int selStart = selectionStart;
                if (frameIndex <= selStart) frameIndex = selStart + 1;
                if (frameIndex >= totalFrames) frameIndex = totalFrames - 1;

                selectionEnd = frameIndex;

                waveformPanel.Invalidate();
                return;
            }

            if (isMovingSelection && e.Button == MouseButtons.Left)
            {
                // Calculate delta frames based on mouse movement, independent of exact mouse-to-frame mapping
                int pixelDeltaX = e.X - lastMouseX;
                lastMouseX = e.X;

                if (viewFrames <= 0 || w <= 0)
                    return;

                double framesPerPixel = (double)viewFrames / w;
                int frameDelta = (int)(pixelDeltaX * framesPerPixel);

                int selStart = Math.Min(selectionStart, selectionEnd);
                int selEnd = Math.Max(selectionStart, selectionEnd);
                int selectionLength = selEnd - selStart;
                if (selectionLength <= 0) selectionLength = 1;

                int newStart = selStart + frameDelta;
                int newEnd = newStart + selectionLength;

                // Clamp selection within valid frames
                if (newStart < 0)
                {
                    newStart = 0;
                    newEnd = selectionLength;
                }
                if (newEnd > totalFrames)
                {
                    newEnd = totalFrames;
                    newStart = newEnd - selectionLength;
                }

                selectionStart = newStart;
                selectionEnd = newEnd;

                waveformPanel.Invalidate();
                return;
            }

            if (isSelecting && e.Button == MouseButtons.Left)
            {
                int frameIndex = viewStartFrame + (int)((double)e.X / w * viewFrames);
                frameIndex = Math.Clamp(frameIndex, 0, totalFrames - 1);

                selectionEnd = frameIndex;
                waveformPanel.Invalidate();
            }
            else if (isPanning && e.Button == MouseButtons.Right)
            {
                int deltaX = e.X - lastPanMouseX;
                lastPanMouseX = e.X;

                if (viewFrames > 0 && w > 0)
                {
                    double framesPerPixel = (double)viewFrames / w;
                    int deltaFrames = (int)(-deltaX * framesPerPixel);

                    int newViewStartFrame = viewStartFrame + deltaFrames;

                    if (newViewStartFrame < 0)
                        newViewStartFrame = 0;

                    int maxStartFrame = totalFrames - viewFrames;
                    if (maxStartFrame < 0) maxStartFrame = 0;

                    if (newViewStartFrame > maxStartFrame)
                        newViewStartFrame = maxStartFrame;

                    if (newViewStartFrame != viewStartFrame)
                    {
                        viewStartFrame = newViewStartFrame;
                        waveformPanel.Invalidate();
                    }
                }
            }
            else // Update cursor depending on proximity to selection edges
            {
                if (selectionStart >= 0 && selectionEnd >= 0 && selectionEnd != selectionStart)
                {
                    int selStart = Math.Min(selectionStart, selectionEnd);
                    int selEnd = Math.Max(selectionStart, selectionEnd);

                    int xStart = (int)((double)(selStart - viewStartFrame) / viewFrames * w);
                    int xEnd = (int)((double)(selEnd - viewStartFrame) / viewFrames * w);

                    if (e.X >= xStart - selectionEdgeSensitivity && e.X <= xStart + selectionEdgeSensitivity)
                    {
                        waveformPanel.Cursor = Cursors.SizeWE;
                        return;
                    }
                    else if (e.X >= xEnd - selectionEdgeSensitivity && e.X <= xEnd + selectionEdgeSensitivity)
                    {
                        waveformPanel.Cursor = Cursors.SizeWE;
                        return;
                    }
                    else if (e.X > xStart + selectionEdgeSensitivity && e.X < xEnd - selectionEdgeSensitivity)
                    {
                        waveformPanel.Cursor = Cursors.SizeAll;
                        return;
                    }
                }
                waveformPanel.Cursor = Cursors.Default;
            }
        }

        private void WaveformPanel_MouseUp(object sender, MouseEventArgs e)
        {
            if (audioSamples == null) return;

            if (e.Button == MouseButtons.Left)
            {
                if (isSelecting)
                {
                    isSelecting = false;

                    if (Math.Abs(selectionEnd - selectionStart) == 0)
                    {
                        selectionStart = -1;
                        selectionEnd = -1;
                    }
                    waveformPanel.Invalidate();
                }
                else if (isMovingSelection)
                {
                    isMovingSelection = false;
                    waveformPanel.Invalidate();
                }
                else if (isResizingLeft)
                {
                    isResizingLeft = false;
                    waveformPanel.Invalidate();
                }
                else if (isResizingRight)
                {
                    isResizingRight = false;
                    waveformPanel.Invalidate();
                }
            }
            else if (e.Button == MouseButtons.Right)
            {
                isPanning = false;
                waveformPanel.Cursor = Cursors.Default;
            }
        }

        private void DeleteSelection()
        {
            if (audioSamples == null) return;
            if (selectionStart < 0 || selectionEnd < 0) return;

            int start = Math.Min(selectionStart, selectionEnd);
            int end = Math.Max(selectionStart, selectionEnd);
            if (end == start) return;

            int channels = waveFormat.Channels;
            int deletedFrames = end - start;
            int deletedSamples = deletedFrames * channels;

            int oldViewStartFrame = viewStartFrame;
            int oldViewFrames = viewFrames;

            int newTotalFrames = audioSamples.Length / channels - deletedFrames;
            int newLength = newTotalFrames * channels;
            float[] newSamples = new float[newLength];

            Array.Copy(audioSamples, 0, newSamples, 0, start * channels);
            Array.Copy(audioSamples, end * channels, newSamples, start * channels, (audioSamples.Length - end * channels));

            audioSamples = newSamples;

            selectionStart = -1;
            selectionEnd = -1;

            if (isPlaying)
            {
                waveOut?.Stop();
                isPlaying = false;
                playbackTimer.Stop();
            }

            bufferedWaveProvider = new BufferedWaveProvider(waveFormat)
            {
                BufferLength = audioSamples.Length * waveFormat.BlockAlign
            };
            bufferedWaveProvider.ClearBuffer();

            byte[] byteBuffer = new byte[audioSamples.Length * sizeof(float)];
            Buffer.BlockCopy(audioSamples, 0, byteBuffer, 0, byteBuffer.Length);
            bufferedWaveProvider.AddSamples(byteBuffer, 0, byteBuffer.Length);

            waveOut?.Init(bufferedWaveProvider);

            playStartFrame = 0;
            playEndFrame = (audioSamples.Length / channels) - 1;

            if (oldViewStartFrame >= end)
            {
                viewStartFrame = Math.Max(0, oldViewStartFrame - deletedFrames);
                viewFrames = oldViewFrames;
            }
            else if (oldViewStartFrame < end && (oldViewStartFrame + oldViewFrames) > start)
            {
                int newViewFrames = oldViewFrames - deletedFrames;
                if (newViewFrames < minViewFrames) newViewFrames = Math.Min(minViewFrames, audioSamples.Length / channels);
                if (newViewFrames > audioSamples.Length / channels) newViewFrames = audioSamples.Length / channels;

                viewStartFrame = oldViewStartFrame;
                if (viewStartFrame > (audioSamples.Length / channels) - newViewFrames)
                    viewStartFrame = (audioSamples.Length / channels) - newViewFrames;
                if (viewStartFrame < 0) viewStartFrame = 0;

                viewFrames = newViewFrames;
            }
            else
            {
                viewStartFrame = oldViewStartFrame;
                viewFrames = oldViewFrames;
            }

            if (viewFrames > audioSamples.Length / channels)
            {
                viewFrames = audioSamples.Length / channels;
                viewStartFrame = 0;
            }

            waveformPanel.Invalidate();
        }

        private void WaveformPanel_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Delete)
            {
                if (selectionStart >= 0 && selectionEnd >= 0 && selectionEnd != selectionStart)
                {
                    DeleteSelection();
                    e.Handled = true;
                }
            }
        }

        private void BtnSave_Click(object sender, EventArgs e)
        {
            if (audioSamples == null || string.IsNullOrEmpty(currentFilePath)) return;

            try
            {
                waveOut?.Stop();

                using (var writer = new WaveFileWriter(currentFilePath, waveFormat))
                {
                    if (waveFormat.Encoding == WaveFormatEncoding.IeeeFloat)
                    {
                        writer.WriteSamples(audioSamples, 0, audioSamples.Length);
                    }
                    else if (waveFormat.BitsPerSample == 16)
                    {
                        short[] int16Samples = new short[audioSamples.Length];
                        for (int i = 0; i < audioSamples.Length; i++)
                        {
                            float sample = audioSamples[i];
                            sample = Math.Max(-1f, Math.Min(1f, sample));
                            int16Samples[i] = (short)(sample * short.MaxValue);
                        }
                        byte[] bytes = new byte[int16Samples.Length * 2];
                        Buffer.BlockCopy(int16Samples, 0, bytes, 0, bytes.Length);
                        writer.Write(bytes, 0, bytes.Length);
                    }
                    else
                    {
                        MessageBox.Show("Unsupported bit depth: " + waveFormat.BitsPerSample);
                        return;
                    }
                }
                MessageBox.Show("File saved to " + currentFilePath);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Failed to save WAV: " + ex.Message);
            }
            finally
            {
                if (audioSamples != null && audioSamples.Length > 0 && waveFormat != null)
                {
                    waveOut?.Dispose();

                    waveOut = new WaveOutEvent();
                    waveOut.PlaybackStopped += WaveOut_PlaybackStopped;

                    bufferedWaveProvider = new BufferedWaveProvider(waveFormat)
                    {
                        BufferLength = audioSamples.Length * waveFormat.BlockAlign
                    };
                    bufferedWaveProvider.ClearBuffer();

                    byte[] byteBuffer = new byte[audioSamples.Length * 4];
                    Buffer.BlockCopy(audioSamples, 0, byteBuffer, 0, byteBuffer.Length);
                    bufferedWaveProvider.AddSamples(byteBuffer, 0, byteBuffer.Length);

                    waveOut.Init(bufferedWaveProvider);
                }
            }
        }

        private void TogglePlayPause()
        {
            if (audioSamples == null || waveOut == null || waveFormat == null) return;

            int channels = waveFormat.Channels;

            if (!isPlaying)
            {
                if (selectionStart >= 0 && selectionEnd >= 0 && selectionEnd != selectionStart)
                {
                    playStartFrame = Math.Min(selectionStart, selectionEnd);
                    playEndFrame = Math.Max(selectionStart, selectionEnd);
                }
                else
                {
                    playStartFrame = 0;
                    playEndFrame = (audioSamples.Length / channels) - 1;
                }

                waveOut.Stop();

                long totalFrames = playEndFrame - playStartFrame + 1;
                long totalSamples = totalFrames * channels;

                if (playStartFrame < 0 || playEndFrame >= (audioSamples.Length / channels) || totalFrames <= 0)
                {
                    MessageBox.Show("Invalid selection for playback.");
                    return;
                }

                try
                {
                    int bytesPerSample = sizeof(float);
                    int intLengthBytes = (int)(totalSamples * bytesPerSample);
                    int byteOffset = (int)(playStartFrame * channels * bytesPerSample);

                    if (byteOffset < 0 || (byteOffset + intLengthBytes) > audioSamples.Length * bytesPerSample)
                    {
                        MessageBox.Show("Playback selection range is out of audio sample bounds.");
                        return;
                    }

                    bufferedWaveProvider?.ClearBuffer();

                    bufferedWaveProvider = new BufferedWaveProvider(waveFormat)
                    {
                        BufferLength = intLengthBytes
                    };

                    byte[] byteBuffer = new byte[intLengthBytes];
                    Buffer.BlockCopy(audioSamples, byteOffset, byteBuffer, 0, intLengthBytes);
                    bufferedWaveProvider.AddSamples(byteBuffer, 0, intLengthBytes);

                    waveOut.Init(bufferedWaveProvider);
                    waveOut.Play();

                    isPlaying = true;
                    playbackTimer.Start();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error occurred during playback start: " + ex.Message);
                    return;
                }
            }
            else
            {
                waveOut.Stop();
                isPlaying = false;
                playbackTimer.Stop();
            }

            waveformPanel.Invalidate();
        }

        private void PlaybackTimer_Tick(object sender, EventArgs e)
        {
            if (!isPlaying) return;

            int bytesPerSample = sizeof(float);
            int channels = waveFormat.Channels;
            int bytesPerFrame = bytesPerSample * channels;

            long currentFrame = 0;

            try
            {
                if (bufferedWaveProvider != null && waveOut != null)
                {
                    long position = waveOut.GetPosition();
                    currentFrame = position / bytesPerFrame + playStartFrame;
                }
            }
            catch
            {
                currentFrame = 0;
            }

            if (currentFrame > playEndFrame)
            {
                waveOut.Stop();
                return;
            }

            waveformPanel.Invalidate();
        }

        private void WaveOut_PlaybackStopped(object sender, StoppedEventArgs e)
        {
            isPlaying = false;
            playbackTimer.Stop();
            waveformPanel.Invalidate();
        }

        private void AudioEditorForm_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Space)
            {
                if (!e.Handled)
                {
                    TogglePlayPause();
                    e.Handled = true;
                }
            }
        }

        private void AudioEditorForm_Load(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(SelectionPath))
            {
                LoadWaveFile(SelectionPath);
            }
            else
            {
                btnSave.Enabled = false;
            }
            BackColor = mainColor;
            btnSave.ForeColor = textColor;
            btnSave.BackColor = mainColor;
            SaveAsCrop.BackColor = mainColor;
            SaveAsCrop.ForeColor = textColor;
        }

        private void AudioEditorForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            waveOut?.Stop();
            waveOut?.Dispose();
            _datasetMaker.Show();
        }

        private void SaveAsCrop_Click(object sender, EventArgs e)
        {
            if (audioSamples == null || string.IsNullOrEmpty(currentFilePath))
            {
                MessageBox.Show("No audio loaded or invalid file path.");
                return;
            }

            if (selectionStart < 0 || selectionEnd < 0 || selectionStart == selectionEnd)
            {
                MessageBox.Show("No selection made.");
                return;
            }

            try
            {
                int channels = waveFormat.Channels;

                int startFrame = Math.Min(selectionStart, selectionEnd);
                int endFrame = Math.Max(selectionStart, selectionEnd);

                int selectedFrames = endFrame - startFrame;
                int selectedSamples = selectedFrames * channels;

                float[] selectedSamplesArray = new float[selectedSamples];
                Array.Copy(audioSamples, startFrame * channels, selectedSamplesArray, 0, selectedSamples);

                WaveFormat selectedFormat = waveFormat;

                string directory = System.IO.Path.GetDirectoryName(currentFilePath);
                string originalFileName = System.IO.Path.GetFileNameWithoutExtension(currentFilePath);
                string extension = System.IO.Path.GetExtension(currentFilePath);

                double startSeconds = (double)startFrame / sampleRate;
                int hours = (int)(startSeconds / 3600);
                int minutes = (int)((startSeconds % 3600) / 60);
                int seconds = (int)(startSeconds % 60);

                string timeStamp = $"{hours:D2}-{minutes:D2}-{seconds:D2}";

                Random rnd = new Random();
                int randomNumber = rnd.Next(1000, 9999);

                string newFileName = $"{originalFileName}_Cropped_{timeStamp}_{randomNumber}{extension}";
                string newFilePath = System.IO.Path.Combine(directory, newFileName);

                using (var writer = new WaveFileWriter(newFilePath, selectedFormat))
                {
                    if (selectedFormat.Encoding == WaveFormatEncoding.IeeeFloat)
                    {
                        writer.WriteSamples(selectedSamplesArray, 0, selectedSamplesArray.Length);
                    }
                    else if (selectedFormat.BitsPerSample == 16)
                    {
                        short[] int16Samples = new short[selectedSamplesArray.Length];
                        for (int i = 0; i < selectedSamplesArray.Length; i++)
                        {
                            float sample = selectedSamplesArray[i];
                            sample = Math.Max(-1f, Math.Min(1f, sample));
                            int16Samples[i] = (short)(sample * short.MaxValue);
                        }
                        byte[] bytes = new byte[int16Samples.Length * 2];
                        Buffer.BlockCopy(int16Samples, 0, bytes, 0, bytes.Length);
                        writer.Write(bytes, 0, bytes.Length);
                    }
                    else
                    {
                        MessageBox.Show("Unsupported bit depth: " + selectedFormat.BitsPerSample);
                        return;
                    }
                }

                MessageBox.Show($"Selection saved as: {newFileName}");
            }
            catch (Exception ex)
            {
                MessageBox.Show("Failed to save cropped selection: " + ex.Message);
                return;
            }

            DeleteSelection();
            _datasetMaker.LoadSpeakers();
        }
    }
}