use std::collections::HashMap;

use criterion::{Criterion, criterion_group, criterion_main};
use trueskill_tt::{
    BETA, GAMMA, IndexMap, MU, P_DRAW, SIGMA, agent::Agent, batch::Batch, drift::ConstantDrift,
    gaussian::Gaussian, player::Player,
};

fn criterion_benchmark(criterion: &mut Criterion) {
    let mut index = IndexMap::new();

    let a = index.get_or_create("a");
    let b = index.get_or_create("b");
    let c = index.get_or_create("c");

    let agents = {
        let mut map = HashMap::new();

        map.insert(
            a,
            Agent {
                player: Player::new(Gaussian::from_ms(MU, SIGMA), BETA, ConstantDrift(GAMMA)),
                ..Default::default()
            },
        );
        map.insert(
            b,
            Agent {
                player: Player::new(Gaussian::from_ms(MU, SIGMA), BETA, ConstantDrift(GAMMA)),
                ..Default::default()
            },
        );
        map.insert(
            c,
            Agent {
                player: Player::new(Gaussian::from_ms(MU, SIGMA), BETA, ConstantDrift(GAMMA)),
                ..Default::default()
            },
        );

        map
    };

    let mut composition = Vec::new();
    let mut results = Vec::new();
    let mut weights = Vec::new();

    for _ in 0..100 {
        composition.push(vec![vec![a], vec![b]]);
        results.push(vec![1.0, 0.0]);
        weights.push(vec![vec![1.0], vec![1.0]]);
    }

    let mut batch = Batch::new(1, P_DRAW);
    batch.add_events(composition, results, weights, &agents);

    criterion.bench_function("Batch::iteration", |b| {
        b.iter(|| batch.iteration(0, &agents))
    });
}

criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);
