//  ----------------------------------------------------------------------------
function svgJs(id, width, height, fill, opacity) {
  var nameSpace = 'http://www.w3.org/1999/xlink/namespace/';
  var wordy = false;

  this.id = "svgJs";
  this.absFactor = new Array();
  this.absFactor.x = 1;
  this.absFactor.y = 1;
  this.anchor = 'start';
  this.avLeft = null;
  this.avTop = null;
  this.backGroundNode = null;
  this.BLANK = ' ';
  this.canvas = null;
  this.color = 'navy';
  this.defs = null;
  this.designSize = new Array();
  this.designSize.height = 700;
  this.designSize.width  = 1200;
  this.dx = 0.0;
  this.dy = 0.0;
  this.fontName = 'trebuchet ms';
  this.fontSize = '12pt';
  this.textDecoration = 'none';
  this.fontWeight = 'normal';
  this.height = null;
  this.iCirc = 0;
  this.iComb = 0;
  this.iContainer = 0;
  this.iDiv = 0;
  this.iImage = 0;
  this.iLine = 0;
  this.iPath = 0;
  this.iRect = 0;
  this.iShape = 0;
  this.iText = 0;
  this.iTextPath = 0;
  this.opacity = 0.9;
  this.position = null;
  this.stroke = 1;
  this.svgNS = "http://www.w3.org/2000/svg";
  this.totalId = 'totalContainer';
  this.width = null;
  this.xlinkNS = "http://www.w3.org/1999/xlink";



  //  ---------------------------------------------------------------------------->
  show = function (id, text) {
    return document.getElementById(id).firstChild.nodeValue = text == undefined ? '' : id + ': ' + text;
  };

  //  ----------------------------------------------------------------------------
  this.init = function (wnd, id, width, height, fill, opacity) {
    this.avLeft = parseInt(screen.availLeft);
    this.avTop = parseInt(screen.availTop);
    this.height = parseInt(window.document.body.clientHeight);
    this.width = parseInt(window.document.body.clientWidth);
    this.maxSize = getMaxSize ();  
    this.setUnavail (230, 72);
    width  = width ==undefined ? this.maxSize.width  - this.getUnavail().width  : width;
    height = height==undefined ? this.maxSize.height - this.getUnavail().height : height;
    this.height = height;
    this.width = width;
    opacity = opacity == undefined ? this.opacity : opacity;
    this.canvas = this.initNative (wnd, nodeOf(id), width, height);
    document.getElementById(id).appendChild(this.canvas);
    this.position = this.canvas;
    this.totalContainer = this.makeContainer (this.getTotalId());
    this.enterContainer (this.totalContainer);
    if (fill) this.backGroundNode = this.add (this.drawRect(0, 0, this.designSize.width, this.designSize.height, fill, this.color, this.strike, opacity));
    if (this.backGroundNode) this.backGroundNode.style.zIndex = '-100';
    this.scale(this.getTotalId(), width / this.designSize.width, height / this.designSize.height);
    return this;
  };

  //  --------------------------------------------------------------------------->
  this.initNative = function (wnd, cnv, width, height) {
    wnd = isUndefined(wnd) ? window : wnd;
    this.canvas = wnd.document.createElementNS(this.svgNS, "svg");
    this.canvas.id = "canvas";
    this.canvas.setAttributeNS(null, 'version', "1.1");
    this.canvas.setAttributeNS(null, 'baseProfile', "full");
    this.canvas.setAttributeNS(null, 'width', width);
    this.canvas.setAttributeNS(null, 'height', height);
    return this.canvas;
  };

  //  ----------------------------------------------------------------------------
  this.paint = function (){
    return 'empty function - no action';
  };

  //  ----------------------------------------------------------------------------
  this.getEvent = function () {
    return evt;
  }

  //  ----------------------------------------------------------------------------
  this.getColor = function () {
    return this.color;
  }

  //  ----------------------------------------------------------------------------
  this.setColor = function (color) {
    this.color = color;
  }

  //  --------------------------------------------------------------------------->
  this.getSize = function () {
    return this.designSize;
  };

  //  --------------------------------------------------------------------------->
  this.getTrueSize = function () {
    var size = new Array ();
    size.width = this.width;
    size.height = this.height;
    return size;
  };

  //  --------------------------------------------------------------------------->
  this.getUnavail = function () {
//    alert ('getUnavail: '+this.unavail.width+', '+this.unavail.height);
    return this.unavail;
  };

  //  --------------------------------------------------------------------------->
  this.setUnavail = function (width, height) {
    this.unavail = new Array ();
    this.unavail.width = width;
    this.unavail.height = height;
//    alert ('setUnavail: '+this.unavail.width+', '+this.unavail.height);
    return this;
  };

  //  --------------------------------------------------------------------------->
  this.getTotalId = function () {
    return this.totalId;
  };

  //  ----------------------------------------------------------------------------
  this.getCanvas = function () {
    return this.canvas;
  }

  //  ----------------------------------------------------------------------------
  this.resizeCanvas = function (factorX, factorY) {
    factorX = factorX ? factorX : 1.0;
    factorY = factorY ? factorY : factorX;
    this.width *= factorX;
    this.height*= factorY;
    if (!this.canvas) {
      alert ('###  err: can\'t do '+this.id+'.resizeCanvas ('+factor+')! There is no canvas!');
      return this;
    }
    return this.setSize (this.canvas, this.width, this.height);
  }

  //  ----------------------------------------------------------------------------
  this.setSize = function (node, width, height) {
    node.setAttributeNS(null, 'width' , width);
    node.setAttributeNS(null, 'height', height);
    return node;
  };

  //  ----------------------------------------------------------------------------
  this.getCanvas = function () {
    return this.canvas;
  }

  //  ----------------------------------------------------------------------------
  this.getBackGroundNode = function () {
    return this.backGroundNode;
  }

  //  ----------------------------------------------------------------------------
  this.setBackGroundColor = function (color) {
    this.backGroundNode.setAttributeNS(null, 'style', 'fill:' + color);
    return this.backGroundNode;
  }

  //  ----------------------------------------------------------------------------
  this.setBackGroundSize = function (factor) {
    this.backGroundNode.setAttributeNS(null, 'dx', this.width * factor);
    this.backGroundNode.setAttributeNS(null, 'dy', this.height * factor);
    this.backGroundNode.setAttributeNS(null, 'font-size', this.fontSize * factor);
    return this.backGroundNode;
  }

  //  ----------------------------------------------------------------------------
  this.removeNode = function (node) {
    if (!node) return false;
    node.parentNode.removeChild(node);
    return true;
  }

  //  ----------------------------------------------------------------------------
  this.changeStyle = function (node, style_string) {
    node.setAttribute("style", style_string);
    return node;
  }

  //  ----------------------------------------------------------------------------
  this.randomColour = function () {
    return "rgb(" + Math.round(Math.random() * 255) + "," + Math.round(Math.random() * 255) + "," + Math.round(Math.random() * 255) + ")"
  }

  //  ----------------------------------------------------------------------------
  this.makeContainer = function (id) {
    var node = document.createElementNS(this.svgNS, "g");
    node.id = id ? id : "container" + (++this.iContainer);
    this.position.appendChild(node);
    this.position = node;
    return this.position;
  }

  //  ----------------------------------------------------------------------------
  this.scale = function (id, factorX, factorY) {
//    alert (this.id+'.scale ('+id+','+factorX+','+factorY+')');
    factorY = factorY ? factorY : factorX;
    var node = document.getElementById(id);
//    alert (this.id+'.scale ('+node.id+','+factorX+','+factorY+')');
    mode = node ? node : this.position;
    if (!node) alert('###  ' + this.id + '.scale: ' + id + ' does not exist!');
    this.absFactor.x = this.absFactor.x * factorX;
    this.absFactor.y = this.absFactor.y * factorY;
    node.setAttribute("transform", 'scale(' +this.absFactor.x+ ' ' +this.absFactor.y+ ')');
//    alert ('transform scale(' +this.absFactor.x+ ' ' +this.absFactor.y+ ')');
    return node;
  }

  //  ----------------------------------------------------------------------------
  this.enterContainer = function (node) {
    this.position = node;
    return this.position;
  }

  //  ----------------------------------------------------------------------------
  this.leaveContainer = function () {
    this.position = this.position.parentNode;
    return this.position;
  }

  //  ----------------------------------------------------------------------------
  this.setPath = function (id, d, stroke, fill, strokeWidth, transform) {
    /*
     The <path> tag is used to define a path.
     The following commands are available for path data:
     
     * M = moveto
     * L = lineto
     * H = horizontal lineto
     * V = vertical lineto
     * C = curveto
     * S = smooth curveto
     * Q = quadratic Belzier curve
     * T = smooth quadratic Belzier curveto
     * A = elliptical Arc
     * Z = closepath
     
     Note: All of the commands above can also be expressed with lower letters. 
     Capital letters means absolutely positioned, lower cases means relatively positioned.*/

    var node = document.createElementNS(this.svgNS, "path");
    node.id = id ? id : "path" + (++this.iPath);
    node.setAttributeNS(null, 'd', d);
    node.setAttributeNS(null, 'stroke', stroke);
    node.setAttributeNS(null, 'fill', fill);
    if (strokeWidth) node.setAttributeNS(null, 'stroke-width', strokeWidth);
    if (transform) node.setAttributeNS(null, 'transform', transform);
    if (!defs) {
      defs = document.createElementNS(this.svgNS, "defs")
      this.position.appendChild(defs);
    }
    defs.appendChild(node);
    /**/
    return node;
  }

  //  ----------------------------------------------------------------------------
  this.setTextPath = function (id, xlinkHref, startOffset) {
    var node = document.createElementNS(this.svgNS, "textPath");
    node.id = id ? id : "textPath" + (++this.iTextPath);
    node.setAttributeNS(this.xlinkNS, 'xlink:href', xlinkHref); // 
    node.setAttributeNS(this.xlinkNS, 'startOffset', startOffset);
    this.position.appendChild(node);
    return node;
  }

  //  ----------------------------------------------------------------------------
  this.drawText = function (x, y, text, dx, dy, fontSize, color, textDecoration, fontName, anchor, textPath) {
    dx = dx == undefined ? this.dx : dx;
    dy = dy == undefined ? this.dy : dy;
    fontSize = fontSize == undefined ? this.fontSize : fontSize;
    color = color == undefined ? this.color : color;
    anchor = anchor == undefined ? this.anchor : anchor;
    var node = document.createElementNS(this.svgNS, "text");
    node.id = "text" + (++this.iText);
    var data = document.createTextNode(text);
    var span = document.createElementNS(this.svgNS, "tspan");
    if (textPath) {
      span = textPath;
      x = 0;
      y = 0;
    }
    span.appendChild(data);
    node.appendChild(span);
    node.setAttributeNS(null, 'x', x);
    node.setAttributeNS(null, 'y', y);
    node.setAttributeNS(null, 'dx', dx);
    node.setAttributeNS(null, 'dy', dy);
    node.setAttributeNS(null, 'font-size', fontSize);
    node.setAttributeNS(null, 'fill', color);
    node.setAttributeNS(null, 'font-style', textDecoration);
    node.setAttributeNS(null, 'font-family', fontName);
    node.setAttributeNS(null, 'text-anchor', anchor);
    //    node.addEventListener('mousemove', doFunc, false);
    this.position.appendChild(node);
    return node;
  }

  //  ----------------------------------------------------------------------------
  this.changeText = function (node, x, y, text, dx, dy, fontSize, color, anchor) {
    if (wordy) alert(this.id + '.changeText: ' + node.id + ', ' + x + ', ' + y + ', ' + text + ', ' + dx + ', ' + dy + ', ' + fontSize + ', ' + color + ', ' + anchor + ')');
    if (x) node.setAttributeNS(null, 'x', x);
    if (y) node.setAttributeNS(null, 'y', y);
    if (wordy) alert('node.firstChild.firstChild.data: ' + node.firstChild.firstChild.data + ', text="' + text + '"');
    if (text) node.firstChild.firstChild.data = text;
    if (dx) node.setAttributeNS(null, 'dx', dx);
    if (dy) node.setAttributeNS(null, 'dy', dy);
    if (fontSize) node.setAttributeNS(null, 'font-size', fontSize);
    if (color) node.setAttributeNS(null, 'fill', color);
    if (anchor != undefined) node.setAttributeNS(null, 'text-anchor', anchor);
    return node;
  }

  //  ----------------------------------------------------------------------------
  this.drawLine = function (x1, y1, x2, y2, stroke, color, opacity) {
    stroke = stroke == undefined ? this.stroke : stroke;
    color = color == undefined ? this.color : color;
    opacity = opacity == undefined ? this.opacity : opacity;
    var node = document.createElementNS(this.svgNS, "line");
    node.id = "line" + (++this.iLine);
    node.setAttributeNS(null, 'x1', x1);
    node.setAttributeNS(null, 'x2', x2);
    node.setAttributeNS(null, 'y1', y1);
    node.setAttributeNS(null, 'y2', y2);
    node.setAttributeNS(null, 'stroke', color);
    node.setAttributeNS(null, 'stroke-width', stroke);
    node.setAttributeNS(null, 'stroke-opacity', opacity);
    this.position.appendChild(node);
    return node;
  }

  //  ----------------------------------------------------------------------------
  this.changeLine = function (node, x1, y1, x2, y2, stroke, color, opacity) {
    //    if (!node) return node;
    if (x1) node.setAttributeNS(null, 'x1', x1);
    if (y1) node.setAttributeNS(null, 'y1', y1);
    if (x2) node.setAttributeNS(null, 'x2', x2);
    if (y2) node.setAttributeNS(null, 'y2', y2);
    if (color) node.setAttributeNS(null, 'stroke', color);
    if (stroke) node.setAttributeNS(null, 'stroke-width', stroke);
    if (opacity) node.setAttributeNS(null, 'stroke-opacity', opacity);
    return node;
  }

  //  ----------------------------------------------------------------------------
  this.drawBox = function (x0, y0, width, height, color, strokeColor, stroke, opacity) {
    return this.drawRect(x0, y0, width, height, color, strokeColor, stroke, opacity);
  };

  //  ----------------------------------------------------------------------------
  this.drawRect = function (x, y, width, height, color, strokeColor, stroke, opacity) {
    color = color == undefined ? this.color : color;
    opacity = opacity == undefined ? this.opacity : opacity;
    var node = document.createElementNS(this.svgNS, "rect");
    node.id = "rect" + (++this.iRect);
    node.setAttributeNS(null, 'x', x);
    node.setAttributeNS(null, 'y', y);
    node.setAttributeNS(null, 'width', width);
    node.setAttributeNS(null, 'height', height);
    node.setAttributeNS(null, 'style', 'fill:' + color);
    node.setAttributeNS(null, 'stroke', strokeColor);
    node.setAttributeNS(null, 'stroke-width', stroke);
    node.setAttributeNS(null, "fill-opacity", opacity);
    this.position.appendChild(node);
    return node;
  };

  //  ----------------------------------------------------------------------------
  this.fillCircle = function (cx, cy, r, color, opacity, id) {
    return this.drawCircle (cx, cy, r, color, opacity, id);
  };

  //  ----------------------------------------------------------------------------
  this.drawCircle = function (cx, cy, r, color, opacity, id) {
    var node = document.createElementNS(this.svgNS, "circle");
    node.id = id ? id : "circ" + (++this.iCirc);
    node.setAttributeNS(null, 'cx', cx);
    node.setAttributeNS(null, 'cy', cy);
    node.setAttributeNS(null, 'r', r);
    node.setAttributeNS(null, 'style', 'fill:' + color);
    node.setAttributeNS(null, "fill-opacity", opacity);
    this.position.appendChild(node);
    return node;
  };

  //  ----------------------------------------------------------------------------
  this.changeCircle = function (node, cx, cy, r, color, opacity) {
//    this.id + '.changeCircle(' + node.id + ', ' + cx + ', ' + cy + ', ' + r + ', ' + color + ', ' + opacity + ')');
    if (!node) return node;
    if (cx) node.setAttributeNS(null, 'cx', cx);
    if (cy) node.setAttributeNS(null, 'cy', cy);
    if (r) node.setAttributeNS(null, 'r', r);
    //    if (color)   alert ('now set the colour: '+'style '+'fill:'+color);
    if (color) node.setAttributeNS(null, 'style', 'fill:' + color);
    if (opacity) node.setAttributeNS(null, "fill-opacity", opacity);
    return node;
  }

  //  ----------------------------------------------------------------------------
  this.pixelShift = function (node, cx, cy) {
    if (node) {
      if (cx) node.setAttributeNS(null, 'cx', cx);
      if (cy) node.setAttributeNS(null, 'cy', cy);
      if (cx) node.setAttributeNS(null, 'x', cx);
      if (cy) node.setAttributeNS(null, 'y', cy);
    }
    return node;
  };

  //  -------------------------------------------------------------------------->
  this.add = function (node) {
  //  return this.position.appendChild(node);
    return node;
  };
  
  //  -------------------------------------------------------------------------->
  getX = function(node) {
    return node.getAttribute("x") ? node.getAttribute("x") : node.getAttribute("cx");
  };

//  ----------------------------------------------------------------------------
}
