// -------------------------------------------------
// Settings
// -------------------------------------------------

$fn = 50;

// -------------------------------------------------
// Configuration
// -------------------------------------------------

outer_size = 54.0;
outer_corner = 5.0;
wall_width = 1.7;
wall_height = 10.0;
tab_width = 0.7;
tab_height = 1.0;
hole_height = 10.0;
top_height = 4.0;
antenna_cfg = 2;
stack_height = 30.7;
compliance = 0.2;

fixture_size = 10;
large_fixture_size = 30;

pwr_hole_size = 14.5;
pwr_posx = 12.5;
pwr_height = 19;

stepper_posy = 0;
stepper_height = 16;
stepper_z_hole_size = 20;
stepper_y_hole_size = 37;

endstop_posx = 0;
endstop_height = 19;
endstop_z_hole_size = 14;
endstop_x_hole_size = 32;
// -------------------------------------------------

inner_size = outer_size - 2 * wall_width;
inner_corner_diameter = outer_corner - wall_width;

// -------------------------------------------------
// Modules
// -------------------------------------------------

module wall(outer, width, corner) {

    inner = outer - 2 * width;
    inner_corner = corner - width;

    difference() {

        minkowski() {
            square(outer - 2 * corner, true);
            circle(corner);
        }


        minkowski() {
            square(inner - 2 * inner_corner, true);
            circle(inner_corner);
        }

    }

}

module walls() {
    wall(outer_size, wall_width, outer_corner);
}

module tabs() {
    outer = outer_size + (tab_width - wall_width) * 2;
    corner = outer_corner + (tab_width - wall_width);
    difference() {
        wall(outer, tab_width, corner);
        square([32,outer_size], true);
        square([outer_size,39], true);
    }
}

module hole() {
    translate([18,22]) {
        difference() {
            union() {
                circle(3.7/2);
                translate([-3.7/2,0]) square([3.7,5]);
            }
            circle(2.0/2);
        }
    }
}

module holes() {
    hole();
    mirror([1,0,0]) hole();
    mirror([0,1,0]) {
        hole();
        mirror([1,0,0]) hole();
    }
}

module antenna() {
    rotate([90,0,0]) linear_extrude(wall_width*2) circle(7/2);
}

module screw() {
    linear_extrude(top_height) circle(3/2);
    linear_extrude(top_height/2) circle(6/2);
}

module top() {

    minkowski() {
        square(outer_size - 2 * outer_corner, true);
        circle(outer_corner);
    }

}

module bottom_layer() {
    union() {
        translate([0,0,top_height]) {
            difference() {
                linear_extrude(wall_height) walls();
                if (antenna_cfg == 1) translate([0,outer_size/2,4]) antenna();
                if (antenna_cfg == 2) translate([7.5,outer_size/2,4]) antenna();
                if (antenna_cfg == 3) translate([7.5,outer_size/2,4]) antenna();
                if (antenna_cfg == 3) translate([-7.5,outer_size/2,4]) antenna();
            }
            translate([0,0,wall_height-hole_height]) {
                linear_extrude(hole_height) holes();
            }
            translate([0,0,wall_height]) {
                linear_extrude(tab_height) tabs();
            }
        }
        difference() {
            linear_extrude(top_height) top();
            translate([22,-22]) screw();
            translate([-22,-22]) screw();
            translate([-22,22]) screw();
            translate([22,22]) screw();
        }
    }
}

module middle_layer() {
    height = 12.5;
    difference() {
        union() {
            difference() {
                linear_extrude(height) walls();
                translate([0,outer_size/2,height-6]) antenna();
            }
            translate([0,0,height-hole_height]) {
                linear_extrude(hole_height) holes();
            }
            translate([0,0,height]) {
                linear_extrude(tab_height) tabs();
            }
        }
        linear_extrude(tab_height) tabs();
    }
}

module cover_top() {
	difference() {		
    		minkowski() {
        		square(outer_size + 2*wall_width + compliance - 2 * outer_corner, true);
        		circle(outer_corner);
		}
    		minkowski() { 
        		square(outer_size - 2 * outer_corner - 1.5 * 2 * wall_width, true);
        		circle(outer_corner);
		}	
    }
}

module plate() {
    	minkowski() {
        	square(outer_size - 2 * outer_corner, true);
        	circle(outer_corner);
		}
}

module half_minkowski(width, depth, radius) {
	union() {
		square([width, 3*depth/4]);
		translate([radius, depth/2-radius, 0]) minkowski() { 
			square([width - 2*radius, depth/2]);
			circle(radius);
		}
	}
}

module fixture() {
difference() {
	linear_extrude(wall_width) union() {
		translate([0, fixture_size/2-4,0]) minkowski() {
			square([fixture_size, fixture_size/2], true);
			circle(1.0); 
		}
 translate([0, -fixture_size/2+4,0]) square([fixture_size+2, fixture_size/2], true); 
		}
	translate([0,1, -wall_width]) cylinder(2 * wall_width +1, 1.5, 1.5, false);
	}
}

module largefixture() {
	difference() {
		linear_extrude(wall_width) translate([-large_fixture_size/2, 0 ,0]) half_minkowski(large_fixture_size, fixture_size, 1);
	translate([-10,fixture_size/2, -wall_width/2]) cylinder(2*wall_width, d=4.1, true);
	translate([10,fixture_size/2, -wall_width/2]) cylinder(2*wall_width, d=4.1, true);
	}
//	color("cyan") translate([10,fixture_size/2, -wall_width/2]) cylinder(2*wall_width, d=4.1, true);
}

module cover() {	
	union() {
		linear_extrude(top_height/2) cover_top();
		linear_extrude(stack_height) wall(outer_size + 2*wall_width + compliance, wall_width, outer_corner); 
		
	}
}

difference() {
	union() { 
		cover();
		translate([0, outer_size/2+wall_width-compliance,stack_height-wall_width]) largefixture();
		translate([0, -(outer_size/2+wall_width-compliance),stack_height-wall_width]) rotate([0,0,180]) largefixture();
	}
	
	color("red") translate([pwr_posx, outer_size/2,pwr_height]) rotate([0,90,90]) linear_extrude(2 * wall_width) minkowski() { 
		square(pwr_hole_size, true);
		circle(1);
	}
	
	color("blue") translate([-outer_size/2-2*wall_width, stepper_posy, stepper_height]) rotate([0,90,0]) linear_extrude(2 * wall_width) minkowski() { 
		square([ stepper_z_hole_size, stepper_y_hole_size ] ,  true);
		circle(1);
	}
	
	color("green") translate([ endstop_posx, -outer_size/2-2*wall_width, endstop_height]) rotate([0,90,90]) linear_extrude(2 * wall_width) minkowski() { 
		square([ endstop_z_hole_size, endstop_x_hole_size ] ,  true);
		circle(1);
	}
}

// color("pink") translate([0,0,30]) linear_extrude(2.2) plate();
// translate([0, 40,0]) half_minkowski(50,50,2);