use contract_bridge::Builder;
use contract_bridge::deck::{Deck, fill_deals, full_deal};
use core::hint::black_box;
use criterion::{Criterion, criterion_group, criterion_main};
use rand::SeedableRng;
use rand::rngs::SmallRng;

fn bench_draw_13(c: &mut Criterion) {
    c.bench_function("Deck::draw_13_from_full", |b| {
        let mut rng = SmallRng::seed_from_u64(0);
        b.iter(|| {
            let mut deck = Deck::ALL;
            black_box(deck.draw(&mut rng, 13))
        });
    });
}

fn bench_full_deal(c: &mut Criterion) {
    c.bench_function("full_deal", |b| {
        let mut rng = SmallRng::seed_from_u64(0);
        b.iter(|| black_box(full_deal(&mut rng)));
    });
}

fn bench_fill_deals_known_north(c: &mut Criterion) {
    let mut rng = SmallRng::seed_from_u64(42);
    let mut deck = Deck::ALL;

    let subset = Builder::new()
        .north(deck.draw(&mut rng, 13))
        .build_partial()
        .expect("known partial deal is valid");

    c.bench_function("fill_deals_with_known_north_x100", |b| {
        let mut rng = SmallRng::seed_from_u64(0);
        b.iter(|| {
            for d in fill_deals(&mut rng, subset).take(100) {
                black_box(d);
            }
        });
    });
}

fn bench_full_deal_x100(c: &mut Criterion) {
    c.bench_function("full_deal_x100", |b| {
        let mut rng = SmallRng::seed_from_u64(0);
        b.iter(|| {
            for _ in 0..100 {
                black_box(full_deal(&mut rng));
            }
        });
    });
}

criterion_group!(
    benches,
    bench_draw_13,
    bench_full_deal,
    bench_full_deal_x100,
    bench_fill_deals_known_north,
);
criterion_main!(benches);
