#include <stdio.h>
#include <math.h>
#include <time.h>
#include <stdlib.h>

//
// This generates a jig that can be attached to the Dremel drill press, to
// help route a hole in a Vectrex cartridge suitable for a ZIF socket by
// manually sliding the cartridge lid around within the captive enclosure.
//
#include "gpc.h"
#include "svg.h"

// Corel-svg uses floating point units in millimeters.  This code uses 1/100ths of a mm,
// (i.e. 10 microns per unit), stored in integers.  May later re-engineer as micron base units.

#define mm(m) (int)roundf((m)*100.0)
#define in(m) (int)roundf((m)*2540.0)
#define ft(m) in((m)*12.0)

#define PLATFORM_HEIGHT mm(144.2)
#define PLATFORM_WIDTH  mm(152.6)

#define WOOD_THICKNESS  mm(4.65) // only used when creating joints

#define LASER_KERF      mm(0.57) // really tight fit, but comes loose after a few removals and reinsertions
#define HALF_LASER_KERF (LASER_KERF/2)

#define ROUTER_KERF  mm(2.8) /* check with micrometer */
#define HALF_ROUTER_KERF (ROUTER_KERF/2)

#define SAFETY mm(0) // make the initial test holes 4mm in on all sides, then reduce 'safety' to 0 if all centered OK. Test with hand-made cart.
//#define SAFETY mm(4) // make the initial test holes 4mm in on all sides, then reduce 'safety' to 0 if all centered OK. Test with hand-made cart.

#define CART_WIDTH  mm(71.5)
#define CART_HEIGHT mm(74.3)
#define ZIF_WIDTH   (mm(22.9)-SAFETY*2-ROUTER_KERF)
#define ZIF_HEIGHT  (mm(50.4)-SAFETY*2-ROUTER_KERF)
#define HOLE_WIDTH  (CART_WIDTH+ZIF_WIDTH)   // to do: subtract router width from both.
#define HOLE_HEIGHT (CART_HEIGHT+ZIF_HEIGHT)

// center of hole vs center of cartridge,
// determined by inspection, so takes into account
// that the drill bit is not in the true center of the base:
#define POSITION_X_OFFSET mm(4.5)  // x is 0 at left increasing to the right (was 3.9)
#define POSITION_Y_OFFSET mm(-7.5) // y is 0 at top increasing downwards

// --------------------------------------------------------

#define RED "#FF0000"
#define GREEN "#00FF00"
#define BLUE "#0000FF"
#define PINK "#FFAAAA"
#define WHITE "#FFFFFF"
#define BLACK "#000000"
#define BACKGROUND "#DDDDFF"

#define ENGRAVE_TEXT BLACK
#define COMMENT_TEXT BLUE

#define HAIRLINE mm(0.01)     // for cutting
#define VISIBLE_LINE mm(0.2)  // for preview

//#define MARGIN mm(0)
#define MARGIN mm(5.0)

#define LIVE_FILL WHITE
#define PREVIEW_FILL PINK

static svg* psvg;

int PREVIEW;
// value of these depends on PREVIEW
int linewidth;
char *fill;
int stage_width = mm(0.0), stage_height = mm(0.0);

void hole(int w, int h, int x, int y) {
  if (x+w > stage_width) stage_width = x+w+MARGIN; // not 'MARGIN*2' because MARGIN already added explicitly by user.
  if (y+h > stage_height) stage_height = y+h+MARGIN;

  if (PREVIEW) {
    svg_rectangle(psvg, /* size */ w, h, /* at */ x, y,
                  BACKGROUND, /* outline */ BACKGROUND, /* border-width */linewidth,
                  /* radius x,y */ 0,0);
  } else {
    svg_rectangle(psvg, /* size */ w, h, /* at */ x, y,
                  WHITE, /* outline */ RED, /* border-width */linewidth,
                  /* radius x,y */ 0,0);
  }
}

void face(int w, int h, int x, int y) {
  if (x+w > stage_width) stage_width = x+w+MARGIN;
  if (y+h > stage_height) stage_height = y+h+MARGIN;

  svg_rectangle(psvg, /* size */ w, h, /* at */ x, y,
                fill, /* outline */ RED, /* border-width */linewidth,
                /* radius x,y */ mm(0),mm(0));
}

void cross_ruler(int x, int y) {
  svg_line(psvg, RED, /* width */ linewidth, /* from */ x-mm(25), y, /* to */ x+mm(25), y);
  svg_line(psvg, RED, /* width */ linewidth, /* from */ x-mm(25), y-mm(2.5), /* to */ x-mm(25), y+mm(2.5));
  svg_line(psvg, RED, /* width */ linewidth, /* from */ x+mm(25), y-mm(2.5), /* to */ x+mm(25), y+mm(2.5));
  svg_text(psvg, /* at */ x+mm(10), y-mm(3),
	   "sans-serif",
	   mm(3),
	   /* fill colour */ (PREVIEW ? COMMENT_TEXT : ENGRAVE_TEXT), /* stroke colour */ (PREVIEW ? COMMENT_TEXT : ENGRAVE_TEXT), "5cm line", "");

  svg_line(psvg, RED, /* width */ linewidth, /* from */ x, y-in(1), /* to */ x, y+in(1));
  svg_line(psvg, RED, /* width */ linewidth, /* from */ x-mm(2.5), y-in(1), /* to */ x+mm(2.5), y-in(1));
  svg_line(psvg, RED, /* width */ linewidth, /* from */ x-mm(2.5), y+in(1), /* to */ x+mm(2.5), y+in(1));
  svg_text(psvg, /* at */ x-mm(5), y+mm(5)+in(1),
	   "sans-serif",
	   mm(3),
	   /* fill colour */ (PREVIEW ? COMMENT_TEXT : ENGRAVE_TEXT), /* stroke colour */ (PREVIEW ? COMMENT_TEXT : ENGRAVE_TEXT), "2in line", "");

}

void do_face(void) {
  face(PLATFORM_WIDTH, PLATFORM_HEIGHT, MARGIN,MARGIN); // outer 4in x 4in box
}

void do_hole(void) {
  hole(HOLE_WIDTH, HOLE_HEIGHT, MARGIN + (PLATFORM_WIDTH-HOLE_WIDTH)/2+POSITION_Y_OFFSET,
       MARGIN + (PLATFORM_HEIGHT-HOLE_HEIGHT)/2+POSITION_X_OFFSET                         
       ); // inner hole for cartridge
  //hole(HOLE_HEIGHT, HOLE_WIDTH, MARGIN + (PLATFORM_HEIGHT-HOLE_HEIGHT)/2+POSITION_X_OFFSET,
  //                              MARGIN + (PLATFORM_WIDTH-HOLE_WIDTH)/2+POSITION_Y_OFFSET); // inner hole for cartridge
}

int main(void) {
  // stage_width = in(36.0)-MARGIN*2; stage_height = in(24.0)-MARGIN*2;

  for (PREVIEW = 1; PREVIEW >= -1; PREVIEW--) { // do preview first to get size
    linewidth = PREVIEW ? VISIBLE_LINE : HAIRLINE;
    fill = PREVIEW ? PREVIEW_FILL : LIVE_FILL;

    psvg = svg_create(stage_width, stage_height); // size of laser cutter bed - either fixed, or 5mm margin around drawing below
    stage_width = mm(0.0); stage_height = mm(0.0);

    if (psvg == NULL) {
      puts("psvg is NULL");
      exit(EXIT_FAILURE);
    } else {
      if (PREVIEW) svg_fill(psvg, BACKGROUND);
    }

    if (PREVIEW) {
      do_face();
      do_hole();
    }
    

    if (PREVIEW) svg_text(psvg,
             /* at */ MARGIN+mm(2.0), mm(3.5),
             "sans-serif", mm(3.0),
             /* fill colour */ COMMENT_TEXT, /* stroke colour */ COMMENT_TEXT,
			  "THIS IS A PREVIEW-OPTIMISED VERSION.  CUT THE OTHER FILE.", "");

    if (PREVIEW) svg_text(psvg,
			  /* at */ MARGIN+mm(2.0), mm(3.5)+PLATFORM_HEIGHT+mm(5),
             "sans-serif", mm(3.0),
             /* fill colour */ COMMENT_TEXT, /* stroke colour */ COMMENT_TEXT,
			  "USING 4mm SAFETY MARGIN!  SET TO 0 FOR LIVE CUT!", "");

    svg_text(psvg,
             /* at */  mm(70), mm(-13) /* left/right as seen on screen More neg pushes text to right. */,
             "sans-serif", mm(6.0),
             /* fill colour */ (PREVIEW ? COMMENT_TEXT : ENGRAVE_TEXT), /* stroke colour */ (PREVIEW ? COMMENT_TEXT : ENGRAVE_TEXT),
             "FRONT", " transform=\"rotate(90)\"");

    cross_ruler(MARGIN+PLATFORM_WIDTH/2-mm(4), MARGIN+PLATFORM_HEIGHT/2-mm(1.5));
                                              // more neg moves cross up as viewed on screen
    //          more neg moves cross left as viewed on screem
    if (!PREVIEW) {
      do_hole();
      do_face();
    }
    
    svg_finalize(psvg);
    svg_save(psvg, PREVIEW ? "zifjig-preview.svg" : "zifjig.svg");
    svg_free(psvg);
  }

  exit(EXIT_SUCCESS);
  return EXIT_FAILURE;
}