Documentation
mod bresenham;

use std::error::Error;
use ndarray::Array3;
use beambook::{Book,Command};

fn rgb12_to_color(x:u16)->[u8;3] {
    [(((x >> 4) & 0xf0) | ((x >> 8) & 0x0f)) as u8,
     (( x       & 0xf0) | ((x >> 4) & 0x0f)) as u8,
     (((x << 4) & 0xf0) | ( x       & 0x0f)) as u8]
}

fn draw_disk(u:&mut Array3<u8>,
	     i0:i32,
	     j0:i32,
	     r:i32,
	     color:[u8;3]) {
    let (m,n,_) = u.dim();
    for di in -r..=r {
	let i = i0 + di;
	if 0 <= i && i < m as i32 {
	    for dj in -r..=r {
		let j = j0 + dj;
		if 0 <= j && j < n as i32 && di*di + dj*dj < r*r {
		    u[[i as usize,j as usize,0]] = color[0];
		    u[[i as usize,j as usize,1]] = color[1];
		    u[[i as usize,j as usize,2]] = color[2];
		}
	    }
	}
    }
}

fn main()->Result<(),Box<dyn Error>> {
    let in_fn = std::env::args().nth(1).expect("Specify input path");
    let out_base = std::env::args().nth(2).expect("Specify output base");
    let bk = Book::load_from_file(in_fn).unwrap();

    let ss = 16;
    let ny = 1024;
    let nx = 1920;

    let invert = 0xfff;

    let mut bm : Array3<u8> = Array3::from_elem((ny*ss,nx*ss,3),(invert & 0xff) as u8);

    let size = 11;
    let margin = 16.0;

    for (ipage,page) in bk.pages.iter().enumerate() {
	for (iplot,plot) in page.plots.iter().enumerate() {
	    let mut rect = plot.bounding();
	    println!("Page bounds: {:?}",rect);
	    let scale = (nx as f64 / rect.dx()).min(ny as f64 / rect.dy());
	    println!("Scale factor: {}",scale);
	    rect.a.x -= margin/scale;
	    rect.a.y -= margin/scale;
	    rect.b.x += margin/scale;
	    rect.b.y += margin/scale;
	    let scale = (nx as f64 / rect.dx()).min(ny as f64 / rect.dy());
	    let scale = ss as f64 * scale;
	    for cmd in plot.commands.iter() {
		match *cmd {
		    Command::Points{ color,ref points } => {
			for &p in points.iter() {
			    let p = p - rect.a;
			    let ix = (p.x * scale).floor() as i32;
			    let iy = (p.y * scale).floor() as i32;
			    draw_disk(&mut bm,ix,iy,size,rgb12_to_color(color ^ invert));
			}
		    },
		    Command::Lines{ color,ref lines } => {
			for line in lines.iter() {
			    for ps in line.windows(2) {
				let p1 = ps[0] - rect.a;
				let p2 = ps[1] - rect.a;
				let ix1 = (p1.x * scale).floor() as i32;
				let iy1 = (p1.y * scale).floor() as i32;
				let ix2 = (p2.x * scale).floor() as i32;
				let iy2 = (p2.y * scale).floor() as i32;
				let color = rgb12_to_color(color ^ invert);
				for (ix,iy) in bresenham::Bresenham::new(ix1,iy1,ix2,iy2) {
				    draw_disk(&mut bm,iy,ix,size,color);
				}
			    }
			}
		    }
		}
	    }

	    let mut w : Array3<u8> = Array3::zeros((ny,nx,3));
	    for iy in 0..ny {
		for ix in 0..nx {
		    let mut cnt = [0_usize;3];
		    for u in 0..ss {
			for v in 0..ss {
			    cnt[0] += bm[[ss*iy+u,ss*ix+v,0]] as usize;
			    cnt[1] += bm[[ss*iy+u,ss*ix+v,1]] as usize;
			    cnt[2] += bm[[ss*iy+u,ss*ix+v,2]] as usize;
			}
		    }
		    let c = [(cnt[0] / (ss * ss)) as u8,
			     (cnt[1] / (ss * ss)) as u8,
			     (cnt[2] / (ss * ss)) as u8];
		    for ic in 0..3 {
			w[[iy,ix,ic]] = c[ic];
		    }
		}
	    }

	    let out_fn = format!("{}-{:03}-{:03}.png",out_base,ipage,iplot);
	    ndarray_image::save_image(out_fn,w.view(),ndarray_image::Colors::Rgb)?;
	}
    }
    Ok(())
}