use audio_samples::{AudioEditing, AudioSamples, sine_wave};
use criterion::{Criterion, black_box, criterion_group, criterion_main};
use std::sync::Arc;
use std::time::Duration;

fn bench_editing_basic_ops(c: &mut Criterion) {
    let audio = Arc::new(sine_wave::<f32, f32>(
        440.0,
        Duration::from_secs(5),
        44100,
        0.7,
    ));

    c.bench_function("editing::reverse", |b| {
        let audio = audio.clone();
        b.iter(move || {
            let a = audio.as_ref().clone();
            black_box(a.reverse())
        })
    });

    c.bench_function("editing::reverse_in_place", |b| {
        let audio = audio.clone();
        b.iter(move || {
            let mut a = audio.as_ref().clone();
            let _ = a.reverse_in_place();
            black_box(&a);
        })
    });

    c.bench_function("editing::trim", |b| {
        let audio = audio.clone();
        b.iter(move || {
            let a = audio.as_ref().clone();
            black_box(a.trim(0.1f32, 0.3f32).unwrap())
        })
    });

    c.bench_function("editing::pad", |b| {
        let audio = audio.clone();
        b.iter(move || {
            let a = audio.as_ref().clone();
            black_box(a.pad(0.05f32, 0.05f32, 0.0f32).unwrap())
        })
    });

    c.bench_function("editing::pad_to_duration", |b| {
        let audio = audio.clone();
        b.iter(move || {
            let a = audio.as_ref().clone();
            black_box(
                a.pad_to_duration(
                    1.2f32,
                    0.0f32,
                    audio_samples::operations::types::PadSide::Right,
                )
                .unwrap(),
            )
        })
    });

    c.bench_function("editing::pad_samples_right", |b| {
        let audio = audio.clone();
        b.iter(move || {
            let a = audio.as_ref().clone();
            black_box(a.pad_samples_right(22050, 0.0f32).unwrap())
        })
    });
}

fn bench_editing_split_concat_mix_repeat(c: &mut Criterion) {
    let a = Arc::new(sine_wave::<f32, f32>(
        220.0,
        Duration::from_secs(5),
        44100,
        0.6,
    ));
    let b = Arc::new(sine_wave::<f32, f32>(
        330.0,
        Duration::from_secs(5),
        44100,
        0.6,
    ));
    let vec_ab = Arc::new(vec![a.as_ref().clone(), b.as_ref().clone()]);

    c.bench_function("editing::split", |ben| {
        let a = a.clone();
        ben.iter(move || {
            let s = a.as_ref().clone();
            black_box(s.split::<f32>(0.05f32).unwrap())
        })
    });

    c.bench_function("editing::concatenate", |ben| {
        let vec_ab = vec_ab.clone();
        ben.iter(move || {
            let v = vec_ab.as_ref().clone();
            black_box(AudioSamples::concatenate_owned(v).unwrap())
        })
    });

    c.bench_function("editing::concatenate_owned", |ben| {
        let a = a.clone();
        let b = b.clone();
        ben.iter(|| {
            let owned = vec![a.as_ref().clone(), b.as_ref().clone()];
            black_box(AudioSamples::concatenate_owned(owned).unwrap())
        })
    });

    c.bench_function("editing::mix", |ben| {
        let vec_ab = vec_ab.clone();
        ben.iter(move || {
            let v = vec_ab.as_ref().clone();
            black_box(AudioSamples::mix(&v, None::<&[f32]>).unwrap())
        })
    });

    c.bench_function("editing::repeat", |ben| {
        let a = a.clone();
        ben.iter(|| {
            let s = a.as_ref().clone();
            black_box(s.repeat(2).unwrap())
        })
    });
}

fn bench_editing_fades_and_silence(c: &mut Criterion) {
    let audio = Arc::new(sine_wave::<f32, f32>(
        440.0,
        Duration::from_secs(5),
        44100,
        0.7,
    ));
    c.bench_function("editing::fade_in_out", |b| {
        let audio = audio.clone();
        b.iter(|| {
            let mut a = audio.as_ref().clone();
            let _ = a.fade_in(0.05f32, audio_samples::operations::types::FadeCurve::Linear);
            let _ = a.fade_out(0.05f32, audio_samples::operations::types::FadeCurve::Linear);
            black_box(&a);
        })
    });

    c.bench_function("editing::trim_silence", |b| {
        let audio = audio.clone();
        b.iter(|| {
            let a = audio.as_ref().clone();
            black_box(a.trim_silence(-40.0f32).unwrap())
        })
    });

    c.bench_function("editing::trim_all_silence", |b| {
        let audio = audio.clone();
        b.iter(|| {
            let a = audio.as_ref().clone();
            black_box(a.trim_all_silence(-40.0f32, 0.01f32).unwrap())
        })
    });
}

criterion_group!(
    benches,
    bench_editing_basic_ops,
    bench_editing_split_concat_mix_repeat,
    bench_editing_fades_and_silence
);
criterion_main!(benches);
