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

#include "svg.h"

// outside dimensions of hive - eventually these may be command-line parameters...

float wood = 4.65;

#define W 140 /* left-right */
//#define H 380 /* top-bottom */
#define H 190 /* top-bottom */
#define D 55  /* front-back */

int PREVIEW = 0;

// --------------------------------------------------------
int mm(int m) {
  return m*100;
}

int in(int m) {
  return m*2540;
}

int ft(int m) {
  return in(m*12);
}

int mm_f(float m) {
  return (int)(m*100.0);
}

int in_f(float m) {
  return (int)(m*2540.0);
}

int ft_f(float m) {
  return in_f(m*12.0);
}

#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_f 0.003
#define VISIBLE_LINE_f 0.1

#define LIVE_FILL WHITE
#define PREVIEW_FILL PINK

static svg* psvg;

#ifdef PREVIEW
float linewidth_f = VISIBLE_LINE_f;
char *fill = PREVIEW_FILL;
#else
float linewidth_f = HAIRLINE_f;
char *fill = LIVE_FILL;
#endif

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

void face(int w, int h, int x, int y) {
  svg_rectangle(psvg, /* size */ mm(w), mm(h), /* at */ mm(x), mm(y),
                fill, /* outline */ RED, /* border-width */mm_f(linewidth_f),
                /* radius x,y */ 0,0);
}

#ifdef NEVER
  svg_text(psvg, /* at */ mm(x+10), mm(y+25+1),
           "sans-serif",
           mm(3),
           /* fill colour */ COMMENT_TEXT, /* stroke colour */ COMMENT_TEXT, "5cm x 5cm square", "");
#endif

void toothcomb(float x, float y, int steps, float spacing, int cut_depth) {
  int i;
  for (i = 0; i <= steps; i++) 
    svg_line(psvg, RED, /* width */ mm_f(linewidth_f),
    /* from */ mm_f(x+i*spacing), mm_f(y),
      /* to */ mm_f(x+i*spacing), mm_f(y+cut_depth));
}

void front_face(int x, int y) {
  float gap;
  int steps = (W-wood*2)/2;
  face(W, H, x+5, y+5);
  hole_mm_f(W-wood*2, 25, x+5+wood, y+5);
  hole_mm_f(W-wood*2-20, 100, x+5+wood+10, y+5+25+15);
  gap = W-wood*2 - steps*2.0;
  toothcomb(x+5+wood+gap/2, y+5+25, steps, 2, 3); // WARNING: NOT CENTERED
}

void back_face(int x, int y) {
  float gap;
  int steps = (W-wood*2)/2;
  face(W, H, x+5+W+5, y+5);
  hole_mm_f(W-wood*2, 25, x+5+W+5+wood, y+5);
  gap = W-wood*2 - steps*2.0;
  toothcomb(x+5+W+5+wood+gap/2, y+5+25, steps, 2, 3); // WARNING: NOT CENTERED
}

void left_face(int x, int y) {
  face(D, H, x+5+W+5+W+5, y+5);
  // sides
  hole_mm_f(wood, H, x+5+W+5+W+5, y+5);
  hole_mm_f(wood, H, x+5+W+5+W+5+D-wood, y+5);
  // top
  hole_mm_f(D, wood, x+5+W+5+W+5, y+5);
  hole_mm_f(D, wood, x+5+W+5+W+5, y+5+H-wood);
}

void right_face(int x, int y) {
  face(D, H, x+5+W+5+W+5+D+5, y+5);
  // sides
  hole_mm_f(wood, H, x+5+W+5+W+5+D+5, y+5);
  hole_mm_f(wood, H, x+5+W+5+W+5+D+5+D-wood, y+5);
  // top
  hole_mm_f(D, wood, x+5+W+5+W+5+D+5, y+5);
  hole_mm_f(D, wood, x+5+W+5+W+5+D+5, y+5+H-wood);
}

void top_face(int x, int y) {
  face(D, W, x+5+W+5+W+5+D+5+D+5, y+5);
  // sides
  hole_mm_f(wood, W, x+5+W+5+W+5+D+5+D+5, y+5);
  hole_mm_f(wood, W, x+5+W+5+W+5+D+5+D+5+D-wood, y+5);
  // top
  hole_mm_f(D, wood, x+5+W+5+W+5+D+5+D+5, y+5);
  hole_mm_f(D, wood, x+5+W+5+W+5+D+5+D+5, y+5+W-wood);
}

void shelf(int x, int y) {
  face(D, W, x+5+W+5+W+5+D+5+D+5, y+5+W+5);
  // sides
  hole_mm_f(wood, W, x+5+W+5+W+5+D+5+D+5, y+5+W+5);
  hole_mm_f(wood, W, x+5+W+5+W+5+D+5+D+5+D-wood, y+5+W+5);
  // top
  hole_mm_f(D, wood, x+5+W+5+W+5+D+5+D+5, y+5+W+5);
  hole_mm_f(D, wood, x+5+W+5+W+5+D+5+D+5, y+5+W-wood+W+5);
}

void ruler(int x, int y) {
  svg_line(psvg, RED, /* width */ mm_f(linewidth_f), /* from */ mm(x), mm(y), /* to */ mm(x+50), mm(y));
  svg_line(psvg, RED, /* width */ mm_f(linewidth_f), /* from */ mm(x), mm(y), /* to */ mm(x), mm(y-5));
  svg_line(psvg, RED, /* width */ mm_f(linewidth_f), /* from */ mm(x+50), mm(y), /* to */ mm(x+50), mm(y-5));
  svg_text(psvg, /* at */ mm(x+10), mm(y-1),
           "sans-serif",
           mm(3),
           /* fill colour */ BLACK, /* stroke colour */ BLACK, "5cm line", "");

}

void hive(int x, int y) {
  front_face(x,y);
  back_face(x,y);
  left_face(x,y);
  right_face(x,y);
  top_face(x,y);
  shelf(x,y);
}

int main(void) {
  PREVIEW = 0;
  linewidth_f = VISIBLE_LINE_f;
  fill = PREVIEW_FILL;

  psvg = svg_create(in(36), in(24)); // size of laser cutter bed

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

  hive(20,20);

  svg_text(psvg, /* at */ mm(2), mm(4),
           "sans-serif",
           mm(3),
           /* fill colour */ COMMENT_TEXT, /* stroke colour */ COMMENT_TEXT, "THIS IS A PREVIEW-OPTIMISED VERSION.  CUT THE OTHER FILE.", "");

  svg_finalize(psvg);
  svg_save(psvg, "hive-preview.svg");
  svg_free(psvg);

  PREVIEW = 1;
  linewidth_f = HAIRLINE_f;
  fill = LIVE_FILL;

  psvg = svg_create(in(36), in(24)); // size of laser cutter bed

  if (psvg == NULL) {
    puts("psvg is NULL");
    exit(EXIT_FAILURE);
  }

  hive(20,20);

  svg_finalize(psvg);
  svg_save(psvg, "hive.svg");
  svg_free(psvg);

  exit(EXIT_SUCCESS);
  return EXIT_FAILURE;
}