/* VectorGraphics JavaScript library: SVG + VML module.
 * adopted from: http://www.codeproject.com/jscript/jbridge.asp
 *
 * (C) 2006-2007 Dmitriy Khudorozhkov (mailto:kh_dmitry2001@mail.ru)
 *
 * This software is provided "as-is", without any express or implied warranty. In
 * no event will the author be held liable for any damages arising from the use
 * of this software.
 *
 * Permission is granted to anyone to use this software for any purpose, including
 * commercial applications, and to alter it and redistribute it freely, subject to
 * the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not claim
 *    that you wrote the original software. If you use this software in a product,
 *    an acknowledgment in the product documentation would be appreciated but is
 *    not required.
 *
 * 2. Altered source versions must be plainly marked as such, and must not be
 *    misrepresented as being the original software.
 *
 * 3. This notice may not be removed or altered from any source distribution.
 */

function VectorGraphics(container)
{
// Implementation reference & setup:

  this._impl = this._EstablishImplementor(container);

  return this;
}

VectorGraphics.prototype = {

  // private methods:

  _EstablishImplementor: function(container)
  {
    // Some older browsers support 'image/svg-xml', not 'image/svg+xml':
    if((navigator.mimeTypes &&
      ((navigator.mimeTypes["image/svg+xml"] && (navigator.mimeTypes["image/svg+xml"].enabledPlugin || (navigator.mimeTypes["image/svg+xml"].enabledPlugin == undefined) )) ||
       (navigator.mimeTypes["image/svg-xml"] && (navigator.mimeTypes["image/svg-xml"].enabledPlugin || (navigator.mimeTypes["image/svg-xml"].enabledPlugin == undefined) ))))  // Opera 8.5+
       ||
       (navigator.userAgent.toLowerCase().indexOf("firefox") != -1) && !window.opera)   // Mozilla Firefox supports SVG
      return new VectorGraphicsImplSVG(container);

    else if((navigator.userAgent.toLowerCase().indexOf("msie") != -1) && (!window.opera))
      return new VectorGraphicsImplVML(container);  // MS IE natively supports VML

    return null;
  },

  // Public methods:

  MoveTo: function(x, y)
  {
    if(this._impl && this._impl.MoveTo)
      return this._impl.MoveTo(x, y);

    return null;
  },

  Polygon: function(arrayofPoints)
  {
    if(this._impl && this._impl.Polygon)
      return this._impl.Polygon(arrayofPoints);

    return null;
  },

  SetFillColor: function(rgb)
  {
    if(this._impl && this._impl._fillColor != undefined)
      this._impl._fillColor = rgb;
  },

  SetStrokeColor: function(rgb)
  {
    if(this._impl && this._impl._strokeColor != undefined)
      this._impl._strokeColor = rgb;
  },

  SetStrokeWidth: function(width)
  {
    if(this._impl && this._impl._strokeWidth != undefined)
      this._impl._strokeWidth = width;
  },

  SetOpacity: function(opacity)
  {
    if(this._impl && this._impl._opacity != undefined)
      this._impl._opacity = opacity;
  },

  SetFont: function(fontNames, fontSize, fontColor, fontVariant)
  {
    if(this._impl)
    {
      if(this._impl._fontNames   != undefined) this._impl._fontNames   = fontNames;
      if(this._impl._fontSize    != undefined) this._impl._fontSize    = fontSize;
      if(this._impl._fontColor   != undefined) this._impl._fontColor   = fontColor;
      if(this._impl._fontVariant != undefined) this._impl._fontVariant = fontVariant;
    }
  }
}

function VectorGraphicsImplSVG(container)
{
  this._svgns = "http://www.w3.org/2000/svg";
  this._curX = 0;
  this._curY = 0;
  this._root = null;
  this._cntr = container;

  this._fillColor   = "#FFF";
  this._strokeColor = "#000";
  this._strokeWidth = 1;
  this._fontNames   = "Arial";
  this._fontSize    = "14px";
  this._fontColor   = "#000";
  this._fontVariant = "";
  this._opacity     = 1;

  return this;
}

VectorGraphicsImplSVG.prototype = {

  // The following 3 methods are required for the script to work in MS IE 6,
  // which has a mediocre XML namespace support.
  //
  _createElementNS: function(ns, name)
  {
    if(document.createElementNS)
      return document.createElementNS(ns, name);
    else
    {
      var elem = document.createElement(name);
      elem.setAttribute("xmlns", ns);

      return elem;
    }
  },

  _getAttributeNS: function(element, ns, name)
  {
    return (element.getAttributeNS ? element.getAttributeNS(ns, name) : element.getAttribute(name));
  },

  _setAttributeNS: function(element, ns, name, value)
  {
    if(element.setAttributeNS)
      element.setAttributeNS(ns, name, value);
    else
      element.setAttribute(name, value);
  },

  _SetupRoot: function()
  {
    if(this._root) return;

    // create SVG canvas:
    this._root = this._createElementNS(this._svgns, "svg");
    this._cntr.appendChild(this._root);

    this._setAttributeNS(this._root, null, "width", "0");
    this._setAttributeNS(this._root, null, "height", "0");
  },

  // This method was "inspired" by Opera browser, which doesn't
  // resize the SVG canvas automatically, like MS IE or Mozilla.
  //
  _ExpandCanvas: function(x, y)
  {
    var curW = parseInt(this._getAttributeNS(this._root, null, "width"));
    var curH = parseInt(this._getAttributeNS(this._root, null, "height"));

    this._setAttributeNS(this._root, null, "width",  x > curW ? String(x) : String(curW));
    this._setAttributeNS(this._root, null, "height", y > curH ? String(y) : String(curH));
  },

  MoveTo: function(x, y)
  {
    if(!this._root) this._SetupRoot();

    this._curX = x;
    this._curY = y;

    this._ExpandCanvas(x, y);
  },

  Polygon: function(arrayofPoints)
  {
    if(!this._root) this._SetupRoot();

    // find area coords/width/height:
    var xmax = arrayofPoints[0][0], ymax = arrayofPoints[0][1];
    var listofPoints = xmax + "," + ymax;

    for(var k = 1, m = arrayofPoints.length; k < m; k++)
    {
      var x = arrayofPoints[k][0];
      var y = arrayofPoints[k][1];

      if(x > xmax) xmax = x;
      if(y > ymax) ymax = y;

      listofPoints += " " + String(x) + "," + String(y);
    }

    var polygon = this._createElementNS(this._svgns, "polygon");

    this._setAttributeNS(polygon, null, "points",         listofPoints);
    this._setAttributeNS(polygon, null, "fill",           this._fillColor);
    this._setAttributeNS(polygon, null, "fill-opacity",   this._opacity);
    this._setAttributeNS(polygon, null, "stroke",         this._strokeColor);
    this._setAttributeNS(polygon, null, "stroke-width",   this._strokeWidth);
    this._setAttributeNS(polygon, null, "stroke-opacity", this._opacity);

    this._root.appendChild(polygon);

    this._ExpandCanvas(xmax, ymax);

    return polygon;
  }
}

function VectorGraphicsImplVML(container)
{
  this._curX = 0;
  this._curY = 0;
  this._root = null;
  this._cntr = container;

  this._fillColor   = "#FFF";
  this._strokeColor = "#000";
  this._strokeWidth = 1;
  this._fontNames   = "Arial";
  this._fontSize    = "14px";
  this._fontColor   = "#000";
  this._fontVariant = "";
  this._opacity     = 1;

  return this;
}

VectorGraphicsImplVML.prototype = {

  _SetupRoot: function()
  {
    if(this._root) return;

    // Add VML style definition:
    var stl = document.createStyleSheet();
    stl.addRule("v\\:*", "behavior: url(#default#VML);");

    // Add xml namespace definition:
    document.namespaces.add("v", "urn:schemas-microsoft-com:vml");

    // Create VML canvas:
    var root = document.createElement("v:group");

    root.style.width  = this._cntr.offsetWidth;
    root.style.height = this._cntr.offsetHeight;
    root.coordorigin  = "0,0";
    root.coordsize    = this._cntr.offsetWidth + "," + this._cntr.offsetHeight;

    this._root = this._cntr.appendChild(root)
  },

  MoveTo: function(x, y)
  {
    this._curX = x;
    this._curY = y;
  },

  Polygon: function(arrayofPoints)
  {
    if(!this._root) this._SetupRoot();

    // find area coords/width/height:
    var xmin = xmax = arrayofPoints[0][0],
        ymin = ymax = arrayofPoints[0][1];

    var path = "m " + xmax + "," + ymax + " l ";

    for(var k = 1, m = arrayofPoints.length; k < m; k++)
    {
      var x = arrayofPoints[k][0];
      var y = arrayofPoints[k][1];

      if(x > xmax) xmax = x;
      if(x < xmin) xmin = x;
      if(y > ymax) ymax = y;
      if(y < ymin) ymin = y;

      path += String(x) + "," + String(y) + ((k == m - 1) ? "" : ",");
    }

    path += " x e";

    var polygon = document.createElement("v:shape");
    this._root.appendChild(polygon);

    var ps = polygon.style;

    ps.position = "absolute";
    ps.top    = ymin;
    ps.left   = xmin;
    ps.width  = xmax - xmin;
    ps.height = ymax - ymin;

    polygon.coordorigin  = xmin + "," + ymin;
    polygon.coordsize    = (xmax - xmin) + "," + (ymax - ymin);
    polygon.fillcolor    = this._fillColor;
    polygon.strokecolor  = this._strokeColor;
    polygon.strokeweight = this._strokeWidth + "px";

    var pathobj = document.createElement("v:path");
    pathobj.v = path;

    polygon.appendChild(pathobj);

    var s = document.createElement("v:stroke");
    s.opacity = this._opacity;
    polygon.insertBefore(s, null);

    var f = document.createElement("v:fill");
    f.opacity = this._opacity;
    polygon.insertBefore(f, null); 

    return polygon;
  }
}
