#include "treedraw.h"
#include "unrooted.h"
#include "svg.h"

extern void do_plot(FD_nj_plot *fd_nj_plot, int doing_print);
extern void frame_and_draw_unrooted(FD_unrooted *fd_unrooted);
extern "C" int trim_key(char *name); /* remove trailing spaces */

const char *Fl_SVG_File_Surface::class_id = "Fl_SVG_File_Device";

Fl_SVG_File_Surface::Fl_SVG_File_Surface(int w, int h, FILE *f) : Fl_Surface_Device(new Fl_SVG_Graphics_Driver(f)) {
  fprintf(f,
	  "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\n"
	  "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \n"
	  "\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"
	  "<svg width=\"%dpx\" height=\"%dpx\" viewBox=\"0 0 %d %d\"\n"
	  "xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">\n", w, h, w, h);
}

Fl_SVG_File_Surface::~Fl_SVG_File_Surface() {
  delete driver();
}

void Fl_SVG_File_Surface::end() {
  Fl_SVG_Graphics_Driver *driver = (Fl_SVG_Graphics_Driver*)this->driver();
  fputs("</svg>\n", driver->file());
  fflush(driver->file());
}

Fl_SVG_Graphics_Driver::Fl_SVG_Graphics_Driver(FILE *f) {
  out_ = f;
  width_ = 1;
  linecap_ = "butt";
  family_ = strdup("");
  bold_ = "";
  style_ = "";
  red_ = green_ = blue_ = 0;
}

Fl_SVG_Graphics_Driver::~Fl_SVG_Graphics_Driver()
{
  free(family_);
}

void Fl_SVG_Graphics_Driver::rect(int x, int y, int w, int h) {
  fprintf(out_, "<rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" "
	  "fill=\"none\" stroke=\"rgb(%u,%u,%u)\" stroke-width=\"%d\"/>\n", x, y, w, h, red_, green_, blue_, width_);
}

void Fl_SVG_Graphics_Driver::rectf(int x, int y, int w, int h) {
  fprintf(out_, "<rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" "
	  "fill=\"rgb(%u,%u,%u)\" />\n", x, y, w, h, red_, green_, blue_);
}

void Fl_SVG_Graphics_Driver::line(int x1, int y1, int x2, int y2) {
  fprintf(out_, 
	  "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" "
	  "style=\"stroke:rgb(%u,%u,%u);stroke-width:%d;stroke-linecap:%s\" />\n", 
	  x1,y1,x2,y2, red_, green_, blue_, width_, linecap_);
}

void Fl_SVG_Graphics_Driver::font(int ft, int s) {
  Fl_Graphics_Driver::font(ft, s);
  Fl_Display_Device::display_device()->driver()->font(ft, s);
  Fl_Font f = Fl_Graphics_Driver::font();
  int attr; char *p, *name;
  name = strdup(Fl::get_font_name(f, &attr));
  if ((p=strstr(name, " Bold")) || (p=strstr(name, " bold"))) memset(p+1, ' ', 4);
  if ((p=strstr(name, " Italic")) || (p=strstr(name, " italic"))) memset(p+1, ' ', 6);
  bold_ =  ( attr&FL_BOLD ? " font-weight=\"bold\"" : "" );
  style_ =  ( attr&FL_ITALIC ? " font-style=\"italic\"" : "" );
  if ((p=strstr(name, " Oblique")) || (p=strstr(name, " oblique"))) {
     memset(p+1, ' ', 7);
    style_ = " font-style=\"oblique\"";
  }
  trim_key(name);
  free(family_);
  family_ = name;
}

void Fl_SVG_Graphics_Driver::line_style(int style, int width, char *dashes) {
  if (width == 0) width = 1;
  width_ = width;
  if (style & FL_CAP_SQUARE) linecap_ = "square";
  if (style & FL_CAP_ROUND) linecap_ = "round";
  else linecap_ = "butt";
}

void Fl_SVG_Graphics_Driver::draw(const char *str, int n, int x, int y) {
  double w = width(str, n);
  fprintf(out_, "<text x=\"%d\" y=\"%d\" font-family=\"%s\"%s%s font-size=\"%d\" "
	  "fill=\"rgb(%u,%u,%u)\" textLength=\"%.2f\">%s</text>\n",x, y, family_, bold_, style_, size(), red_, green_, blue_, w, str);
}

 void Fl_SVG_Graphics_Driver::draw(const char* str, int n, float fx, float fy) {
   return draw(str, n, (int)fx, (int)fy);
 }

 void Fl_SVG_Graphics_Driver::draw(int angle, const char* str, int n, int x, int y) {
   fprintf(out_, "<g transform=\"translate(%d,%d) rotate(%d)\">", x, y, -angle);
   draw(str, n, 0, 0);
   fputs("</g>\n", out_);
 }
 
void Fl_SVG_Graphics_Driver::rtl_draw(const char*, int, int, int) {}

void Fl_SVG_Graphics_Driver::color(Fl_Color c) {
  Fl_Graphics_Driver::color(c);
  Fl::get_color(c, red_, green_, blue_);
}

void Fl_SVG_Graphics_Driver::color(uchar r, uchar g, uchar b) {
  red_ = r;
  green_ = g;
  blue_ = b;
}

void Fl_SVG_Graphics_Driver::draw_image(const uchar*, int, int, int, int, int, int) {}
void Fl_SVG_Graphics_Driver::draw_image_mono(const uchar*, int, int, int, int, int, int) {}
void Fl_SVG_Graphics_Driver::draw_image(void (*)(void*, int, int, int, uchar*), void*, int, int, int, int, int) {}
void Fl_SVG_Graphics_Driver::draw_image_mono(void (*)(void*, int, int, int, uchar*), void*, int, int, int, int, int) {}
void Fl_SVG_Graphics_Driver::draw(Fl_RGB_Image*, int, int, int, int, int, int) {}
void Fl_SVG_Graphics_Driver::draw(Fl_Pixmap*, int, int, int, int, int, int) {}
void Fl_SVG_Graphics_Driver::draw(Fl_Bitmap*, int, int, int, int, int, int) {}
double Fl_SVG_Graphics_Driver::width(const char* str, int l) {
 return Fl_Display_Device::display_device()->driver()->width(str, l);
}
int Fl_SVG_Graphics_Driver::height() {
  return Fl_Display_Device::display_device()->driver()->height();
}
int Fl_SVG_Graphics_Driver::descent() {
  return Fl_Display_Device::display_device()->driver()->descent();
}


void svg_tree_save(FD_nj_plot *fd_nj_plot)
{
  Fl_Native_File_Chooser *chooser = new Fl_Native_File_Chooser(Fl_Native_File_Chooser::BROWSE_SAVE_FILE);
  chooser->title("Enter SVG filename");       
  chooser->filter("SVG Files\t*.{svg}");
  char tmp[100];
  strcpy(tmp, extract_filename(fd_nj_plot->tree_name));
  char *p = strrchr(tmp, '.'); if(p != NULL) *p = 0;
  strcat(tmp, ".svg");
  chooser->preset_file(tmp);
  chooser->options(Fl_Native_File_Chooser::SAVEAS_CONFIRM | chooser->options());
  char *plotfilename = run_and_close_native_file_chooser(chooser);
  if(plotfilename == NULL) return;
  FILE *out;
  if (!(out = fopen(plotfilename, "w"))) return;
  Fl_SVG_File_Surface svg(fd_nj_plot->panel->w(), fd_nj_plot->panel->h(), out);
  svg.set_current();
  fl_font(fd_nj_plot->font_family, fd_nj_plot->font_size);
  fl_color(FL_GRAY);
  fl_rect(0, 0, fd_nj_plot->panel->w(), fd_nj_plot->panel->h());
  fl_color(FL_BLACK);
  fl_line_style(FL_CAP_SQUARE, 1);
  if(fd_nj_plot->fd_unrooted == NULL) {
    do_plot(fd_nj_plot, TRUE);
    }
  else {
    FD_unrooted *fd_unrooted = (FD_unrooted *)fd_nj_plot->fd_unrooted;
    fd_unrooted->previous_w = 0; 
    fd_unrooted->previous_h = 0;
    fd_unrooted->comp_phys_bounds = TRUE;
    int old_x = fd_unrooted->x_offset;
    int old_y = fd_unrooted->y_offset;
    fd_unrooted->x = fd_unrooted->x_offset = 0;
    fd_unrooted->y = fd_unrooted->y_offset = 0;
    fd_unrooted->w = fd_nj_plot->panel->w();
    fd_unrooted->h = fd_nj_plot->panel->h();
    frame_and_draw_unrooted(fd_unrooted);
    fd_unrooted->x_offset = old_x;
    fd_unrooted->y_offset = old_y;
    fd_unrooted->comp_phys_bounds = FALSE;
  }
  Fl_Display_Device::display_device()->set_current();
  svg.end();
  fclose(out);
}

