/* [Lego Type] */
type = "brick"; // ["brick":Brick, "plate":Plate, "slope45":"Slope 45","knob":Knob]
studs_x = 4;
studs_y = 2;
slice_x = false;

/* [Hidden] */
block_height =
	(type == "brick" || type == "slope45") ? 9.6 :
	(type == "plate" || type == "knob") ? 3.2 :
	0;
length_per_stud = 31.8 / 4;
wall_width = 1.6;
ceiling_width = 1;
centered_knob = type == "knob";
$fs = 1;

assert(block_height > 0, "Invalid block height. Perhaps type is not correct?");
assert(studs_x >= studs_y, "studs_x must be equal or larger than studs_y");

module stud() {
	if (type == "knob") {
		difference() {
			cylinder(d = 4.8, h = 1.8);
			cylinder(d = 3.2, h = 1.9);
		}
	} else {
		cylinder(d = 4.8, h = 1.8);
	}
}

module studs() {
	if (centered_knob) {
		for (x = [0:studs_x-2], y = [0:studs_y-2])
		translate([(x+1) * length_per_stud, (y+1) * length_per_stud, 0])
		stud();
	} else {
		for (x = [0:studs_x-1], y = [0:studs_y-1])
		translate([(x+0.5) * length_per_stud, (y+0.5) * length_per_stud, 0])
		stud();
	}
}

module base() {
	width = (studs_y + (type == "slope45" ? 1 : 0)) * length_per_stud;
	length = studs_x * length_per_stud;
	difference() {
		cube([ length, width, block_height ]);
		translate([wall_width, wall_width, -ceiling_width]) {
			difference() {
				cube([
					length - wall_width * 2,
					width - wall_width * 2,
					block_height
				]);
				if (type == "slope45") {					
					translate([-wall_width, width-wall_width/2-wall_width*1.4, 3.2])
					rotate([45, 0, 0])
					cube([length + 2, length_per_stud, block_height]);
				}
			}
		}
	}
}

module pillar() {
	cylinder(h = block_height, d = 6.55);
}

module small_pillar() {
	cylinder(h = block_height, d = 3.2);
}

module pillars() {
	if (type == "slope45") {
		for (x = [0:studs_x-2], y = [0:studs_y-1])
		translate([(x+1) * length_per_stud, (y+1) * length_per_stud, 0])
		pillar();
	} else if (studs_x >= 2 && studs_y >= 2) {
		for (x = [0:studs_x-2], y = [0:studs_y-2])
		translate([(x+1) * length_per_stud, (y+1) * length_per_stud, 0])
		pillar();
	} else if (studs_x >= 2) {
		for (x = [0:studs_x-2])
		translate([(x+1) * length_per_stud, length_per_stud/2, 0])
		small_pillar();
	}
}

module block() {
	width = (studs_y + (type == "slope45" ? 1 : 0)) * length_per_stud;
	length = studs_x * length_per_stud;
	difference() {
		union() {
			base();
			pillars();
			translate([0, 0, block_height])
			studs();
		}
		if (type == "slope45") {
			translate([-1, width-wall_width, 3.2])
			rotate([45, 0, 0])
			translate([0, 1, -10])
			cube([length + 2, 10, 20]);
		}
	}
}

difference() {
	color([0.9, 0.8, 0])
	block();
	if (slice_x) {
		translate([10, -10, -10])
		cube([100, 100, 100]);
	}
}