use std::{iter, fs, path};

use image::ImageFormat;
use criterion::{Criterion, criterion_group, criterion_main};

#[derive(Clone, Copy)]
struct BenchDef {
    dir: &'static [&'static str],
    files: &'static [&'static str],
    format: ImageFormat,
}

fn load_all(c: &mut Criterion) {
    const BENCH_DEFS: &'static [BenchDef] = &[
        BenchDef {
            dir: &["bmp", "images"],
            files: &[
                "Core_1_Bit.bmp",
                "Core_4_Bit.bmp",
                "Core_8_Bit.bmp",
                "rgb16.bmp",
                "rgb24.bmp",
                "rgb32.bmp",
                "pal4rle.bmp",
                "pal8rle.bmp",
                "rgb16-565.bmp",
                "rgb32bf.bmp",
            ],
            format: ImageFormat::Bmp,
        },
        BenchDef {
            dir: &["gif", "simple"],
            files: &[
                "alpha_gif_a.gif",
                "sample_1.gif",
            ],
            format: ImageFormat::Gif,
        },
        BenchDef {
            dir: &["hdr", "images"],
            files: &[
                "image1.hdr",
                "rgbr4x4.hdr",
            ],
            format: ImageFormat::Hdr,
        },
        BenchDef {
            dir: &["ico", "images"],
            files: &[
                "bmp-24bpp-mask.ico",
                "bmp-32bpp-alpha.ico",
                "png-32bpp-alpha.ico",
                "smile.ico",
            ],
            format: ImageFormat::Ico,
        },
        BenchDef {
            dir: &["jpg", "progressive"],
            files: &[
                "3.jpg",
                "cat.jpg",
                "test.jpg",
            ],
            format: ImageFormat::Jpeg,
        },
        // TODO: pnm
        // TODO: png
        BenchDef {
            dir: &["tga", "testsuite"],
            files: &[
                "cbw8.tga",
                "ctc24.tga",
                "ubw8.tga",
                "utc24.tga",
            ],
            format: ImageFormat::Tga,
        },
        BenchDef {
            dir: &["tiff", "testsuite"],
            files: &[
                "hpredict.tiff",
                "hpredict_packbits.tiff",
                "mandrill.tiff",
                "rgb-3c-16b.tiff",
            ],
            format: ImageFormat::Tiff,
        },
        BenchDef {
            dir: &["webp", "images"],
            files: &[
                "simple-gray.webp",
                "simple-rgb.webp",
                "vp8x-gray.webp",
                "vp8x-rgb.webp",
            ],
            format: ImageFormat::WebP,
        },
    ];

    for bench in BENCH_DEFS {
        bench_load(c, bench);
    }
}

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

fn bench_load(c: &mut Criterion, def: &BenchDef) {
    let group_name = format!("load-{:?}", def.format);
    let mut group = c.benchmark_group(&group_name);
    let paths = IMAGE_DIR.iter().chain(def.dir);

    for file_name in def.files {
        let path: path::PathBuf = paths.clone().chain(iter::once(file_name)).collect();
        let buf = fs::read(path).unwrap();
        group.bench_function(file_name.to_owned(), |b| b.iter(|| {
            image::load_from_memory_with_format(&buf, def.format).unwrap();
        }));
    }
}

const IMAGE_DIR: [&'static str; 3] = [".", "tests", "images"];

