
class DrawClass {

  public static final int FORMAT_NONE = 0;
  public static final int FORMAT_SVG = 1;
  public static final int FORMAT_PNG = 2;

  ArrayList<String> sb = new ArrayList<String>();
  ArrayList<String> sb_last = new ArrayList<String>();
  String fontFamily = "Ariel, sans-serif";
  int format = FORMAT_SVG;
  color fillCol = #000000;
  float fontSize = 14;
  boolean noStrokeMode = false;
  color strokeCol = #000000;
  float strokeWidth = 1.0;
  String textAnchor = "start"; // "middle";
  float viewBoxXMin = 0.0;
  float viewBoxXMax = width;
  float viewBoxYMin = 0.0;
  float viewBoxYMax = height;
  float viewBoxPad = 50.0;

  void Ellipse(float cx, float cy, float rx, float ry) {
   if ((cx -rx) < viewBoxXMin) {
     viewBoxXMin = cx-rx - viewBoxPad;
   } else if ((cx+rx) > viewBoxXMax) {
     viewBoxXMax = cx + rx + viewBoxPad;
   }
   if ((cy -ry) < viewBoxYMin) {
     viewBoxYMin = cy-ry - viewBoxPad;
   } else if ((cy+ry) > viewBoxYMax) {
     viewBoxYMax = cy + ry + viewBoxPad;
   }

   switch(format) {
    case FORMAT_SVG:
     if (!noStrokeMode) {
      sb.add("<ellipse cx=\"" + cx + "\" cy=\"" + cy + "\" rx=\"" + rx/2 + "\" ry=\"" + ry/2 + "\" stroke=\"" + Hex(strokeCol) + "\" fill=\"" + Hex(fillCol) + "\" stroke-width=\"" + strokeWidth + "\"/>\n");
     } else { // simulate noStroke mode
      sb.add("<ellipse cx=\"" + cx + "\" cy=\"" + cy + "\" rx=\"" + rx/2 + "\" ry=\"" + ry/2 + "\" fill=\"" + Hex(fillCol) + "\"/>\n");
     }
     break;
   }
   ellipse(cx,cy,rx,ry);
  }

  void Polygon(ArrayList<Float> xv, ArrayList<Float> yv) {
   int n = xv.size();
   if (yv.size() < n) {
     n = yv.size(); // strange, should have same length - issue warning? TODO
   }
   String s = "";
   switch(format) {
    case FORMAT_SVG:
     s = "<polygon points=\"";
     for (int i = 0; i < n; ++i) {
       float x = xv.get(i);
       float y = yv.get(i);
       s = s + x + "," + y + " ";
     }
     s = s + "\"";
     if (!noStrokeMode) {
       s = s + " stroke=\"" + Hex(strokeCol) + "\" stroke-width=\"" + strokeWidth + "\"";
     }
     s = s + " fill=\"" + Hex(fillCol) + "\"/>\n";
     sb.add(s); // + x1 + "," + y1 + " " + x2 + "," + y2 + " " + x3 + "," + y3 + "\" stroke=\"" + Hex(strokeCol) + "\" fill=\"" + Hex(fillCol) + "\" />\n";
     break;
   }
   beginShape();
   for (int i = 0; i < n; ++i) {
     vertex(xv.get(i), yv.get(i));
   }
   if (n > 1) {
    vertex(xv.get(0), yv.get(0));
   }
   endShape();
  }

  void Triangle(float x1, float y1, float x2, float y2, float x3, float y3) {
   switch(format) {
    case FORMAT_SVG:
     if (!noStrokeMode) {
      sb.add("<polygon points=\"" + x1 + "," + y1 + " " + x2 + "," + y2 + " " + x3 + "," + y3 + "\" stroke=\"" + Hex(strokeCol) + "\" fill=\"" + Hex(fillCol) + "\" stroke-width=\"" + strokeWidth + "\"/>\n");
     } else { // simulate noStroke mode
      sb.add("<polygon points=\"" + x1 + "," + y1 + " " + x2 + "," + y2 + " " + x3 + "," + y3 + "\" stroke=\"" + Hex(strokeCol) + "\" fill=\"" + Hex(fillCol) + "\"/>\n");
     }
     break;
   }
   triangle(x1,y1,x2,y2,x3,y3);
  }

  /** Copy fill color. "color" is actually a synonym for the primitive type int, so this is a "deep" copy */
  void Fill(color col) {
      fillCol = col;
      fill(col);
  }

  String Hex(color c) {
    String s = hex(c);
    s = "#" + s.substring(2); // skip first two characters that are opacity
    return s;
  }
  
  void Line(float x1, float y1, float x2, float y2) {
   if (format == FORMAT_SVG) {
    sb.add("<line x1=\"" + x1 + "\" y1=\""+ y1 + "\" x2=\"" + x2 + "\" y2=\"" + y2 + "\" stroke=\"black\" stroke-width=\"" + strokeWidth + "\" />\n");
   }
   line(x1,y1,x2,y2);
  }

  void NoStroke() { 
    noStrokeMode = true;
    noStroke();
  }

  void setFormat(int formatId) {
    format = formatId;   
  }

  void Stroke(color c) {
    noStrokeMode = false;
    strokeCol = c;
    stroke(c);
  }

  void StrokeWeight(float x) {
      strokeWidth = x;
      strokeWeight(x);
  }

  void Text(String txt, float x, float y) {
   if (format == FORMAT_SVG) {
    sb.add("<text x=\"" + x + "\" y=\"" + y + "\" text-anchor=\"" + textAnchor + "\" fill=\"" + Hex(fillCol) + "\" font-size=\"" + fontSize + "px\" font-family=\"" + fontFamily + "\" >" + txt + "</text>\n");
   }
   text(txt, x, y);
  }

  void TextSize(float size) {
    fontSize = size;
    textSize(size);
  }

  void clear() {
     sb_last = new ArrayList<String>(sb); // shallow copy
     sb.clear();
     viewBoxXMin = 0;
     viewBoxXMax = width;
     viewBoxYMin = 0;
     viewBoxYMax = height;
  }

  String toString() { return sb.toString(); }  

  /** Output as SVG formatted Strings. Uses Processing variables width and height that correspond to screen dimensions */
  synchronized String[] toSVG() { // int width, int height) { 
    ArrayList<String> sbc = new ArrayList<String>(); // sb.size()); // (sb.clone());
    for (int i = 0; i < sb_last.size(); ++i) {
      if (i < sb_last.size()) {
       sbc.add(sb_last.get(i));
      }
    }
    int n = sbc.size(); 
    String[] result = new String[n +2];
   // viewBox="0 0 " + screenResX + " " + screenResY + "\" xmlns=\"http://www.w3.org/2000/svg\"
    String s = "<svg width=\"" + width + "\" height=\"" + height + "\" viewBox=\"" + viewBoxXMin + " " + viewBoxYMin + " " + viewBoxXMax + " " + viewBoxYMax + "\" xmlns=\"http://www.w3.org/2000/svg\">\n";
    result[0] = s;
//    println("DEBUG SVG Sizes: " + n + " " + sbc.size() + " " + result.length);
    for (int i = 0; i < n; ++i) {
//      println("working on svg line" + i);
      if (i >= sbc.size()) {
       println("Warning!!! DrawClass.pde L168");
      }
      if ((i+1) >= result.length) {
       println("Warning!!! DrawClass.pde L171");
      }
      result[i+1] = sbc.get(i);
    }
//    println("setting last line:" + (result.length-1));
    result[result.length-1] = "</svg>";
    return result;
  }  

/*  String toHTML(int width, int height) {
    String s = "<html>\n"
              +"<head>\n"
	      +"</head>\n"
	      +"<body>\n"
	      + toSVG(width, height)
	      +"</body\n"
	      +"</html>"; 
    return s;	      
  }
*/

}