use noto_sans_mono_bitmap::{
    FontWeight,
    RasterHeight,
    RasterizedChar,
    get_raster,
    get_raster_width,
};

const RASTER_H: RasterHeight = RasterHeight::Size20;

pub fn glyph_w() -> u32 {
    get_raster_width(FontWeight::Regular, RASTER_H) as u32
}

pub fn glyph_h() -> u32 {
    RASTER_H.val() as u32
}

fn rasterize(ch: char, bold: bool) -> RasterizedChar {
    let w = if bold {
        FontWeight::Bold
    } else {
        FontWeight::Regular
    };
    get_raster(ch, w, RASTER_H)
        .unwrap_or_else(|| {
            get_raster('?', w, RASTER_H).unwrap()
        })
}

fn lerp(a: u8, b: u8, t: u8) -> u8 {
    let a = a as i32;
    let b = b as i32;
    let t = t as i32;
    (a + (b - a) * t / 255) as u8
}

pub fn blit_glyph(
    buf: &mut [u8],
    img_w: u32,
    cx: u32,
    cy: u32,
    ch: char,
    fg: [u8; 3],
    bg: [u8; 3],
    bold: bool,
    pad: u32,
) {
    let gw = glyph_w();
    let gh = glyph_h();
    let cell_w = gw + pad;
    let cell_h = gh + pad;
    let x0 = cx * cell_w;
    let y0 = cy * cell_h;

    // Fill entire cell with bg
    for dy in 0..cell_h {
        for dx in 0..cell_w {
            let off =
                ((y0 + dy) * img_w + (x0 + dx)) as usize
                    * 4;
            buf[off] = bg[0];
            buf[off + 1] = bg[1];
            buf[off + 2] = bg[2];
            buf[off + 3] = 255;
        }
    }

    // Draw anti-aliased glyph centered in cell
    let ox = pad / 2;
    let oy = pad / 2;
    let raster = rasterize(ch, bold);
    for (row, scanline) in
        raster.raster().iter().enumerate()
    {
        for (col, &intensity) in
            scanline.iter().enumerate()
        {
            if intensity == 0 {
                continue;
            }
            let px = x0 + ox + col as u32;
            let py = y0 + oy + row as u32;
            let off = (py * img_w + px) as usize * 4;
            buf[off] = lerp(bg[0], fg[0], intensity);
            buf[off + 1] =
                lerp(bg[1], fg[1], intensity);
            buf[off + 2] =
                lerp(bg[2], fg[2], intensity);
            buf[off + 3] = 255;
        }
    }
}
