extern crate gunpowder_treason as gt;
#[macro_use] extern crate itertools;
extern crate rand;

use std::collections::HashSet;
use rand::Rng;

fn main() {
    let cent = 0.393701;
    let (w, h) = (23.0 * cent, 30.0 * cent);
    let mut drawing = gt::svg(w, h);
    drawing.add(gt::rect((0.0, 0.0), (w, h)));

    let mut rng = rand::thread_rng();
    let per_inch = 5.0;

    let mut points: HashSet<(usize, usize)> = iproduct!(
        per_inch as usize .. per_inch as usize * 8,
        per_inch as usize .. per_inch as usize * 11
    ).collect();
    let mut src: Vec<(usize, usize)> = points.clone().into_iter().collect();
    rng.shuffle(&mut src);


    while let Some((ox, oy)) = src.pop() {
        let mut x = ox;
        let mut y = oy;
        if !points.remove(&(x, y)) { continue; }
        let mut total_points = 1usize;
        let mut line = gt::line(x as f64 / per_inch, y as f64 / per_inch);
        'find_next: loop {
            let mut neighbors = vec![
                (x - 1, y),
                (x + 1, y),
                (x, y - 1),
                (x, y + 1),
                (x, y - 1),
                (x, y + 1),
                (x, y - 1),
                (x, y + 1),
            ];
            rng.shuffle(&mut neighbors);
            'check_neighbors: for &(xn, yn) in neighbors.iter() {
                if points.remove(&(xn, yn)) {
                    total_points += 1;
                    line = line.to(xn as f64 / per_inch, yn as f64 / per_inch);
                    x = xn;
                    y = yn;
                    continue 'find_next;
                }
            }
            break 'find_next;
        }
        if total_points > 3 {
            drawing.add(gt::circle((ox as f64 / per_inch, oy as f64 / per_inch), 0.02));
            drawing.add(gt::circle((x as f64 / per_inch, y as f64 / per_inch), 0.02));
            drawing.add(line);
        }
    }

    if let Err(e) = drawing.output("space") {
        eprintln!("{:?}", e);
    }
}
