// AxisTest.js
//  -----------------------------------------------------
// <p>Title: Axis-Test.</p>
// <p>Description: test of an autoscaling axis in Javascript creating svg-elements to XHTML</p>
// <p>Copyright: Copyright (c) 2008 - 2010</p>
// <p>Company: SiG Software Integration GmbH</p>
// <p>Author Dr. Horst Walther</p>
// <p>Version 0.5</p>
//  ----------------------------------------------------------------------------

//  ----------------------------------------------------------------------------
function AxisTest() {
  var wordy = false;
  var RED = '#ff0000';
  var idText = 'axis';
  var CIRCLE = 9;
  var isDown = false;
  var lastX, lastY;
  var tx = 0;
  var ty = 0;
  var dx = 0;
  var downId = '';
  var p2d = null;
  var pixelMin = 0;
  var pixelMax = 0;
  var axisPixelMin = 0;
  var axisPixelMax = 0;
  var textNodes = [];
  var circNodes = [];
  var axisNodes = [];
  var nodeIndex = [];
  var nodeIDs = [];

  this.xMin = [];
  this.xMax = [];
  this.textFormatIndex = [];
  this.axisText = [];
  this.axisType = 0;
  this.dateTimeAxisType = 1;
  this.titleText = '';
  this.headerText = '';
  this.id = 'AxisTest';
  this.axes = [];
  this.p2d = null;

//  -------------------------------------------------------------------------->
  this.init = function (id, width, height, fill, opacity) {
    this.p2d = new plot2d(id, width, height, fill, opacity);
//    alert (this.id+'.init ('+id+', '+width+', '+height+', '+fill+', '+opacity+'), p2d='+this.p2d+', this.axisType='+this.axisType); 
    this.graphPanel = this.getGraphics ('1');
    this.setData ();
    this.createDialog('dialog', this.headerText);
    if (!this.p2d) return null;
    this.createAxes(this.axisType, this.titleText, this.xMin, this.xMax, this.axisText, this.textFormatIndex);
    this.initForm (0);
    document.dragger = new Drag();
    document.dragger.init('header1', 'panelDialog');
    return this;
};

//  -------------------------------------------------------------------------->
  this.setData = function () {
//    alert (this.id+'.set ('+p2d+', '+axisType+', '+headerText+', '+xMin+', '+xMax+', '+axisText+', '+textFormatIndex+')');
    this.axisText = new Array('min & max similar magnitude', 'min << max', 'small difference', 'very small difference', 'min negative, max positive', 'both negative', 'small difference nagative', 'very small but negative'); // -->
    this.textFormatIndex = new Array(1, 1, 2, 3, 1, 2, 2, 3);
    this.xMin = new Array(78.8, 8.8, 90.05, 90.005, -78.8, -90.25, -90.25, -90.025);
    this.xMax = new Array(90.25, 90.25, 90.25, 90.025, 90.25, -8.8, -90.05, -90.020);
    this.titleText = "selfscaling axis test";
    this.headerText = "create your own axis";
//    alert (this.id+'.set ('+this.p2d+', '+this.axisType+', '+this.titleText+', '+this.xMin+', '+this.xMax+', '+this.axisText+', '+this.textFormatIndex+')');
    return this;
 };

//  -------------------------------------------------------------------------->
  this.getGraphics = function (id) {
//    alert (this.p2d.id);
    return this.p2d.getGraphics().getCanvas(); 
  };

//  ----------------------------------------------------------------------------
  this.createAxes = function  (axisType, text, min, max, axisText, textFormatIndex) {
//    alert (this.id+'.createAxes ('+this.p2d.id+', '+axisType+', '+text+', '+min+', '+max+', '+axisText+', '+textFormatIndex+')');
    this.t = new HWText (this.p2d, text, 12.0, 7.0, 18, 'black');
    for (var i = 0; i < min.length; i++) {
      this.axes[idText+i] = this.createAxis (axisType);
//      alert (this.id+'.axis '+(idText+i)+' created: '+this.axes[idText+i].id);
      this.axes[idText+i].init(new Point2d(1.0, 19 - 1.5 * i), min[i], max[i], 17.0, 0.0, true, i+': ' + axisText[i] , 'navy');
    }
    this.node = this.p2d.makeContainer(this.id);
	return this;
  };

//  ----------------------------------------------------------------------------
   this.createAxis = function(axisType) {
//    alert (this.id+'.createAxis ('+axisType+'): '+(this.dateTimeAxisType ? new DateTimeAxis(this.p2d) : new Axis(this.p2d)).id+', p2d='+this.p2d);
    return axisType == this.dateTimeAxisType ? new DateTimeAxis(this.p2d) : new Axis(this.p2d);
  };

//  ---------------------------------------------------------------------------
  this.updateFunction = function(node) {
    deleteFunction (node); 
    return this.updateAxis (node, nodeOf('inputIdx').value, 
                                  nodeOf('inputMin').value, 
                                  nodeOf('inputMax').value);
  };

//  -------------------------------------------------------------------------->
  this.createDialog = function (containerID, headerText) {

    var dialog = nodeOf (containerID);
    var dialogPanel = new Panel ('Dialog', 'dialog'); dialog.appendChild(dialogPanel);

    var header = new Header ('1', headerText); dialogPanel.appendChild(header); header.ondblclickAction = function () {header.toggleHeight(header)}; 
    var minMaxPanel = new Panel ('MinMax'); dialogPanel.appendChild(minMaxPanel); 
    var buttonPanel = new Panel ('Button'); dialogPanel.appendChild(buttonPanel); 
    var toDoPanel = new Panel ('toDo'); dialogPanel.appendChild(toDoPanel);  
    var node = document.axisNode;

    var numField = new Field ('Idx', 'number: ', 0); 
    numField.isValid = function () {return(nodeOf('inputIdx').value > -1) && (nodeOf('inputIdx').value < 8)}; 
    numField.autoCorrect = function () {nodeOf('inputIdx').value = confine (nodeOf('inputIdx').value, 0, 7); return nodeOf('inputIdx')}; 
    numField.postAction = function () {node.initForm (nodeOf('inputIdx').value)}; 
    minMaxPanel.appendChild (numField);

    var minField = new Field ('Min', 'min.: ', this.xMin[0]);
    minMaxPanel.appendChild (minField);
    minField.getInput().setType ('float');
    minField.postAction = function () {orderNodes (nodeOf('inputMin'), nodeOf('inputMax')); 
                                       node.updateFunction (document.axisNode.axes)};

    var maxField = new Field ('Max', 'max.: ', this.xMax[0]); // .setType ('float'); 
    maxField.postAction = function () {orderNodes (nodeOf('inputMin'), nodeOf('inputMax'));
                                       node.updateFunction (document.axisNode.axes)};
    maxField.getInput().setType ('float');
    minMaxPanel.appendChild (maxField);

    buttonPanel.appendHeader ('actions:');
    buttonPanel.appendChild (new Button ("flush", "flush", function () {deleteFunction(document.axisNode.axes)}));
    buttonPanel.appendChild (document.createElement ('br'));

    buttonPanel.appendChild (new Button ("update", "update", function () {node.updateFunction (document.axisNode.axes)}));
    buttonPanel.appendChild (document.createElement ('br'));

    toDoPanel.appendHeader ('To do list ...');
    toDoPanel.appendListItem ('resize an axis via drag & drop');
    toDoPanel.appendListItem ('test y-axis as well');
    toDoPanel.appendListItem ('improve date- / time-axis auto labelling');
    toDoPanel.appendListItem ('introduce 3d axis');
  };

//  ---------------------------------------------------------------------------
  orderNodes = function (node)  {
    var length = arguments.length
    if (length) {
      var elements = [];
      for (var i = 0; i < length; i++)
        elements[i] = parseFloat (nodeOf(arguments[i]).value, 10);
      elements = elements.sort();
      for (var i = 0; i < length; i++)
        arguments [i].value = elements[i];
      return arguments;
    }
  return null;
  };

//  ---------------------------------------------------------------------------
  deleteFunction = function (node) {
    if (!node) return;
//    alert (nodeOf('inputIdx').value);
    var idx = idText+nodeOf('inputIdx').value;
//    alert (idx);
//    alert (node.axis0.id);
//    alert (node[idx].id);
    return node[idx].remove();
  };

 //  --------------------------------------------------------------------------->
this.initForm = function (i) {
  var idx = idText+i;
//  alert (this.id+'.initForm: '+this.axes+', idx='+idx);
//  alert ('length='+this.axes.length);
//  alert ('axes='+this.axes[idx].id);
//  alert ('axes='+this.axes.axis0.id);
  nodeOf('inputIdx').value = i;
  nodeOf('inputMin').value = this.axes[idx].min.toString();
  nodeOf('inputMax').value = this.axes[idx].max.toString();
}

//  ----------------------------------------------------------------------------
  this.drawAxes = function  () {
//    alert (this.id+'.drawAxes ()');
    this.p2d.enterContainer (this.node);
    this.t.draw ('middle');
    var j = 0;
    var axis = 0;
    for (var i = 0; i < this.xMin.length; i++) {
      axis = this.axes[idText+i];
      axis.draw ();
      axis.setPositionFunctions (document.axisNode.down, document.axisNode.move, document.axisNode.up);
      this.xMin[i].onmousedown = document.axisNode.down;
      this.xMax[i].onmousedown = document.axisNode.down;
      this.drawPositions (axis, new Array (this.xMin[i], this.xMax[i]), 'blue', true, this.textFormatIndex[i]);
    }
    this.p2d.leaveContainer ();
	return this;
  };

//  ----------------------------------------------------------------------------
function getPositions(i) {
  if (i === undefined) {
    return positions;
  }
  return positions[i];
};

//  ----------------------------------------------------------------------------
function getcircNodes(i) {
  if (i === undefined) {
    return circNodes;
  }
  return circNodes[i];
};

//  ----------------------------------------------------------------------------
function gettextNodes(i) {
  if (i === undefined) {
    return textNodes;
  }
  return textNodes[i];
};

//  ----------------------------------------------------------------------------
function setPositions(positions, color, draggablePosX, textFormatIndex) {
  if (positions) {
    this.positions = positions;
  }
  if (color) {
    this.posColor = color;
  }
  if (draggablePosX) {
    this.draggablePosX = draggablePosX;
  }
  if (textFormatIndex) this.textFormatIndex = textFormatIndex;
    if (wordy) alert (this.id+'.setPositions: textFormatIndex='+this.textFormatIndex);
};

//  ----------------------------------------------------------------------------
this.down = function (evt) {
  if (isDown) return;
  isDown = true;	
  evt = fixEvent(evt);
  var node = evt.target;
  if (!node.id) node = node.parentNode;
//  alert ('node: '+node.nodeName+'.'+node.id+'('+(node)+') has '+node.childNodes.length+' child nodes, is child of: '+node.parentNode.id);
  document.onmousemove = document.axisNode.move;
  document.onmouseup = document.axisNode.up;
//      node.addEventListener("mousedown", this.down, false);
//      document.addEventListener("mousemove", this.move, false);
//      document.addEventListener("mouseup", this.up, false);
//  alert (node+', '+getX(node)+', '+node.getAttribute("cx"));
  dx = evt.clientX - getX(node); //  node.x();   node.getAttribute("cx");
  lastX = evt.clientX;
  lastY = evt.clientY;
  downId = node.id;
  var axis = axisNodes[downId];
  var j = axis.id.substr(4);
  var i = nodeIndex[downId];
  var axisNode = document.axisNode;
  axisNode.p2d.changeSymbol(circNodes[downId], null, null, CIRCLE, null, null, RED);
  axisNode.p2d.changeText(textNodes[downId], null, null, null, null, null, null, RED);
  nodeOf('inputIdx').value = j;
  var minTag = nodeOf('inputMin');
  var maxTag = nodeOf('inputMax');
  if (i) {
    maxTag.value = parseFloat(axis.getMax()).toFixed(axis.getScaler().getPlaces() + 1);
    maxTag.style.color= "red";
  } else {
    minTag.value = parseFloat(axis.getMin()).toFixed(axis.getScaler().getPlaces() + 1);
    minTag.style.color= "red";
  }
  pixelMax = axis.toPixels (axis.getMax());
  pixelMin = axis.toPixels (axis.getMin());
  axisPixelMin = axis.getValMinPixel();
  axisPixelMax = axis.getValMaxPixel();
  show('trace', 'down at ' + axis.id +  '.' + circNodes[downId].id + ': (' + j + ',' + i + '), ' + dx + '-->'+(i ? axis.getMax() : axis.getMin())+')');
}

//  ----------------------------------------------------------------------------
this.move = function (evt) {
  if (!isDown) return;
  evt = fixEvent(evt);
  var i = nodeIndex[downId];
  var axis = axisNodes[downId];
  var j = axis.id.substr(4);
  var x = evt.clientX - dx;
  x = i ? confine (x, pixelMin, axisPixelMax) : confine (x, axisPixelMin, pixelMax);
  var xPos = axis.rebuildValue(x);
  var axisNode = document.axisNode;
  axisNode.p2d.pixelShift (circNodes[downId], x);
  axisNode.p2d.changeText (textNodes[downId], null, null, xPos);
  axisNode.p2d.pixelShift (textNodes[downId], x);
  nodeOf(i ? 'inputMax' : 'inputMin').value = xPos;
  if (i) axis.setMax(xPos); else axis.setMin(xPos);
  show('trace', 'move ' + axis.id +  '.' + circNodes[downId].id + ' : (' + j + ',' + i + '), ' + x + '-->'+xPos+')');
}

//  ----------------------------------------------------------------------------
this.up = function (evt) {
  if (!isDown) return;
  isDown = false;
  evt = fixEvent(evt);
  var i = nodeIndex[downId];
  if (wordy) alert('up: ' + downId + ' --> i=' + i + ', axis=' + axisNodes[downId].id);
  var axisNode = document.axisNode;
  axisNode.p2d.changeText(textNodes[downId], null, null, null, null, null, null, 'black');
  axisNode.p2d.changeSymbol(circNodes[downId], null, null, CIRCLE, null, null, 'blue');
  nodeOf(i ? 'inputMax' : 'inputMin').style.color= "black";
  axisNode.updateAxis(document.axisNode.axes,
               nodeOf('inputIdx').value, 
               nodeOf('inputMin').value, 
               nodeOf('inputMax').value);
  document.onmousemove = null;
  document.onmouseup = null;
  show('trace', axisNodes[downId].id + ' up at ' + downId);
};

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

//  ----------------------------------------------------------------------------
 this.parsePosition = function(pos) {
  return parseFloat(pos);
};

//  ----------------------------------------------------------------------------
 this.updateAxis = function(node, i, x1, x2) {
//  alert ('updateAxis1('+node+', '+i+', '+x1+', '+x2+')');
  x1 = this.parsePosition(x1);
  x2 = this.parsePosition(x2);
  i = idText+parseInt(i);
//  alert ('updateAxis2('+node[i].id+', '+i+', '+x1+', '+x2+')');
  var axis = node[i];
  if (axis.rescale(x1, x2)) {
//    alert('updateAxis3: '+ i + ': ' + '(' + x1 + ' > ' + axis.getValMin() + ') && (' + x2 + ' < ' + axis.getValMax() + ')');
    show('trace', i + ': ' + '(' + x1 + ' > ' + axis.getValMin() + ') && (' + x2 + ' < ' + axis.getValMax() + ')');
//    alert ('updateAxis about to redraw '+ axis.min+' and '+axis.max);
    axis.redraw();
//    alert ('updateAxis about to changePositions '+ axis.id+', '+new Array(x1, x2));
    changePositions(axis, new Array(x1, x2));
//    alert ('updateAxis about to drawPositions '+ axis.id+', '+new Array(x1, x2)+', blue, true');
    this.drawPositions(axis, new Array(x1, x2), 'blue', true);
  } else 
    show('trace', '### err: could not recale: updateAxis('+i+', '+x1+', '+x2+') ');
  return axis;
};

//  ----------------------------------------------------------------------------
this.setPositionFunctions = function () {
//  alert (this.id+'.setPositionFunctions:'+document.axisNode.id);
  for (var i = 0; i < this.axes.length; i++) {
//    alert (this.id+'.setPositionFunctions:'+document.axisNode.down+', '+document.axisNode.move+', '+document.axisNode.up);
    this.axes[i].setPositionFunctions (document.axisNode.down, document.axisNode.move, document.axisNode.up);
  }
  return this;
};

//  ----------------------------------------------------------------------------
 this.drawPositions = function(axis, positions, color, draggablePosX) {
  if (wordy) alert('drawPositions (' + axis.id + ', ' + positions + ', ' + color + ', ' + draggablePosX + ')');
  var node= null;
  var j = axis.id.substr(4);
  if (positions == null) return this;
  var positionFormat = axis.findPositionFormat (positions);
  axis.enterContainer();
  for (var i = 0; i < positions.length; i++) {
    node = axis.drawPosition(positions[i], color, draggablePosX);
    node.onmousedown = this.down;
    var nodeId = node.id;
    textNodes[nodeId] = axis.drawPositionText(positions[i], positionFormat);
    circNodes[nodeId] = node;
    axisNodes[nodeId] = axis;
    nodeIndex[nodeId] = i;
    nodeIDs[2*j+i] = nodeId;
  }
  axis.leaveContainer();
};


//  ----------------------------------------------------------------------------
function changePositions(axis, positions, textFormatIndex) {
  if (wordy) alert('changePositions (' + axis.id + ', ' + positions+')');
  var j = axis.id.substr(4);
  var nodeId = null;
  if (positions == null) return this;
  axis.setMin(positions[0]); 
  axis.setMax(positions[1]); 
  for (var i = 0; i < positions.length; i++) {
    nodeId = nodeIDs [2*j+i];
    if (wordy) alert ('changePositions: '+(2*j+i)+'-->'+nodeId+', '+circNodes[nodeId]+', '+positions[i]);
    axis.changePosition (circNodes[nodeId], positions[i]);
    axis.changePositionText (textNodes[nodeId], positions[i], textFormatIndex);
  }
};


//  ----------------------------------------------------------------------------
function listPositions(j, positions) {
  if (wordy) alert('listPositions (' + j + ', ' + positions + ')');
  var s = "";
  s += 'AxisTest.listPositions :';
  for (var i = 0; i < positions.length; i++) {
    var nodeId = 'circ'+(j*i+1);
  if (wordy) alert ('nodeId: '+nodeId);
    s += i + ', circNodes[' + nodeId + '].id=' + circNodes[nodeId].id + ' / '
           +   'textNodes[' + nodeId + '].id=' + textNodes[nodeId].id + ', ';
  }
  alert(s);
};
  //  ----------------------------------------------------------------------------
}
//  --------------------------------------------------------------------------->
