// Defines the box for the Fabula Open Source storyteller.
// This is the box, without any cutout nor electronics components mount.

// Global dimensions, change here
width = 180;
height = 90;
depth = 45;
screw_diameter = 3;

// Internal global variables
rounded_edge_diameter = height;
box_cut_height = 10;
flange_height = 3;
standoff_diameter=screw_diameter*3;

// Screw standoff
module standoff() {
    cylinder(h = depth, d = standoff_diameter, center = true);
}

// Screw hole, to be subtracted from standoff and box
module screw_hole() {
    // Hole where the screw will thread into
    cylinder(h = depth - 2, d = screw_diameter, center = true);
    // Hole where the screw will pass with slack, without threading (in the lid)
    translate([0, 0, depth/2 - box_cut_height/2]) {
        cylinder(h = box_cut_height + 12, d = screw_diameter*1.5, center = true);
    }
    // Screw head bevel
    bevel_depth = 1;
    translate([0, 0, depth/2 - bevel_depth/2 + 6]) {
        cylinder(h = bevel_depth, d2 = screw_diameter * 2.5, d1 = screw_diameter*1.5, center = true);
    }
}


// Main body
module main_body() {
    module half_body() {
        cube([width - rounded_edge_diameter/2, height/2, depth]);
        cylinder(h = depth, d = rounded_edge_diameter, $fn=256);   
    }

    union() {
        translate([-(width - rounded_edge_diameter)/2, 0, -depth/2]) {
            half_body();
        }
        translate([(width - rounded_edge_diameter)/2, 0, -depth/2]) {
            mirror([1, 0, 0]) {
                mirror([0, 1, 0]) {
                    half_body();
                }
            }
        }
    }
}

// Closed Box
module closed_box() {
    difference() {
        union() {
            // Hollow box
            difference() {
                // Round all edges to avoid danger for the children
                minkowski() {
                    $fn = 64;
                    main_body();
                    sphere(6);
                }
                main_body();
            }
            
            // Screws standoffs near curved edges
            translate([width/2 - rounded_edge_diameter/2, -height/2, 0]) {
                standoff();
            }
            translate([-width/2 + rounded_edge_diameter/2, height/2, 0]) {
                standoff();
            }
            // Screws standoff near sharp edges
            translate([-width/2 + standoff_diameter/2, -height/2, 0]) {
                standoff();
            }
            translate([width/2 - standoff_diameter/2, height/2, 0]) {
                standoff();
            }
        }
        // Screw holes near curved edges
        translate([width/2 - rounded_edge_diameter/2, -height/2, 0]) {
            screw_hole();
        }
        translate([-width/2 + rounded_edge_diameter/2, height/2, 0]) {
            screw_hole();
        }
        // Screws holes near sharp edges
        translate([-width/2 + standoff_diameter/2, -height/2, 0]) {
            screw_hole();
        }
        translate([width/2 - standoff_diameter/2, height/2, 0]) {
            screw_hole();
        }
    }
        
}

// Lower box
module box() {
    difference() {
        closed_box();
        translate([0, 0, depth - box_cut_height]) {
            cube([width*2, height*2, depth], true);
        }
    }
}

// Upper cap lip
module lip() {
    difference() {
        union() {
            // Lip support
            translate([0, 0, box_cut_height + 7]) {
                intersection() {
                    difference() {
                        scale([1.01, 1.01, 1.01]) main_body();
                        scale([0.92, 0.92, 0.92]) main_body();
                    }
                    
                    cube([width*2, height*2, box_cut_height], true);
                }
            }

            // Chamfered lip
            for (i = [0:10]) {
                translate([0, 0, box_cut_height + 2 - i * 0.5]) {
                    intersection() {
                        difference() {
                            scale_ratio = 0.98 - i * 0.002;
                            scale([scale_ratio, scale_ratio, scale_ratio]) {
                                main_body();
                            }
                            scale([0.92, 0.92, 0.92]) main_body();
                        }
                        
                        cube([width*2, height*2, 0.5], true);
                    }
                }
            }
        }
        

        // Leave space for screws standoffs near curved edges
        translate([width/2 - rounded_edge_diameter/2, -height/2, 0]) {
            scale([1.5, 1.5, 1]) standoff();
        }
        translate([-width/2 + rounded_edge_diameter/2, height/2, 0]) {
            scale([1.5, 1.5, 1]) standoff();
        }
        // Leave space for screws standoff near sharp edges
        translate([-width/2 + standoff_diameter/2, -height/2, 0]) {
            scale([1.5, 1.5, 1]) standoff();
        }
        translate([width/2 - standoff_diameter/2, height/2, 0]) {
            scale([1.5, 1.5, 1]) standoff();
        }
    }
}

// Upper cap
module cap() {
    difference() {
        closed_box();
        translate([0, 0, - box_cut_height]) {
            cube([width*2, height*2, depth], true);
        }
    }
    translate([0, 0, 0.6]) lip();
}

translate([0, -60, 0]) box();
translate([0, 60, 0]) rotate([180, 0, 0]) cap();
