// file: axis.js
// Title: Axis
// Description: construct diagram axis
// Copyright: Copyright (c) 2010
// Company: SiG software Integration GmbH
//  ----------------------------------------------------------------------------

function Axis(_p) {
  //  constants  ---------------------------------------------------------------
  var wordy = false;
  this.axisType = 'number';
  this.pinFac = 0.01;
  this.jMax = 10;
  this.jMean = 5;
  this.defaultTickLen = 10;
  this.factor = 1.0;
  //  attributes -----------------------------------------------------------------
  this.draggablePosX = false; // you may dragg the PosX-symbols
  this.tickType = 1;
  this.fontSize = 12;

  this.shift = 0.0;
  this.pxGridLen = 0;
  this.pyGridLen = 0;
  this.x0 = 0.0;
  this.y0 = 0.0;
  this.tmpVal = 0.0;

  this.posColor = 'navy';
  this.gridColor = 'lightgray';

  this.node = null;
  this.textFormatIndex = 2;
  this.p = null;
  this.gridFlag = false;
  this.o = null;
  this.min = 0.0;
  this.max = 1.0;
  this.viewLen = 10.0;
  this.gridLen = 0.0;
  this.isXaxis = true;
  this.text = '';
  this.color = 'black';
  this.scaler = null;
  this.valOld = 0;
  if (_p === undefined) {
    if (wordy) alert('###  err: '+this.id+'.Axis: p=' + _p);
//    return null;
  }
  this.p = _p;

  //  ----------------------------------------------------------------------------
  this.init = function (_o, _min, _max, _viewLen, _gridLen, _isXaxis, _text, _color) {
    if (wordy) {alert(this.id+'.init (' + _o + ', ' + _min + ', ' + _max + ', ' + _viewLen + ', ' + _gridLen + ', ' + _isXaxis + ', ' + _text + ', ' + _color + ')');}
    this.id = this.p.getUniqueID('axis');
    this.set(_o, _min, _max, _viewLen, _gridLen, _isXaxis, _text, _color);
    if (wordy) {alert(this.id + " is initd: " + this.scaler.toString());}
//    alert (this.isXaxis ? 'x-axis' : 'y-axis');
    return this;
  };

  //  ----------------------------------------------------------------------------
  this.set = function (_o, _min, _max, _viewLen, _gridLen, _isXaxis, _text, _color) {
    if (wordy) {alert(this.id + '.set (' + _o + ', ' + _min + ', ' + _max + ', ' + _viewLen + ', ' + _gridLen + ', ' + _isXaxis + ', ' + _text + ', ' + _color + ')');}
    this.o       = _o === undefined ? new Point2d(0.0, 0.0) : _o;
    this.min     = _min === undefined ? 0.0 : _min;
    this.max     = _max === undefined ? 0.0 : _max;
    this.viewLen = _viewLen === undefined ? 0.0 : _viewLen;
    this.gridLen = _gridLen === undefined ? 0.0 : _gridLen;
    this.isXaxis = _isXaxis === undefined ? true : _isXaxis;
    this.text    = _text === undefined ? "" : _text;
    this.color   = _color === undefined ? 'black' : _color;
    this.gridFlag= (this.gridLen > 0.0);
//    alert (this.id+'.setScaler('+this.min+', '+this.max+', '+this.viewLen+', scaler='+this.setScaler(this.min, this.max, this.viewLen));
    this.scaler  = this.setScaler(this.min, this.max, this.viewLen);
    this.findPositionFormat(new Array(this.min, this.max));
    if (wordy) {alert(this.id + ".set: " + this.scaler.toString());}
    return this;
  };

  //  ----------------------------------------------------------------------------
  this.setScaler = function (min, max, viewLen) {
    return new Scaler(min, max, viewLen);
  };

  //  ----------------------------------------------------------------------------
  this.isSameType = function (axisType) {
    return this.axisType == axisType;
  };

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

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

  //  ----------------------------------------------------------------------------
  this.toString = function (t) {
    return ((t ? t : "Axis: ") + "o: (" + this.o.toString() + "), min: " + this.min + ", max: " + this.max + ', viewLen: ' + this.viewLen + ', isXaxis: ' + this.isXaxis + ', text: ' + this.text + ', color: ' + this.color);
  };

  //  ----------------------------------------------------------------------------
  this.setFactor = function (factor) {
    this.factor = factor;
    return this;
  };

  //  ----------------------------------------------------------------------------
  this.getScaler = function () {
    return this.scaler;
  };

  //  ----------------------------------------------------------------------------
  this.rescale = function (min, max, viewLen) {
    //    alert (this.id+'.rescale1 ('+min+', '+max+', '+viewLen+')');
    this.min = min == undefined ? this.min : min;
    this.max = max == undefined ? this.max : max;
    this.viewLen = viewLen == undefined ? this.viewLen : viewLen;
    //    alert (this.id+'.rescale2 ('+this.min+', '+this.max+', '+this.viewLen+')');
    this.scaler = this.scaler.autoScale(this.min, this.max, this.viewLen);
    //    alert (this.id+'.rescale3 ('+this.min+', '+this.max+', '+this.viewLen+')');
    return this;
  };

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

  //  ----------------------------------------------------------------------------
  this.getOrigin = function () {
    return this.o;
  };

  //  ----------------------------------------------------------------------------
  this.getFactor = function () {
    return this.scaler.getFactor();
  };

  //  ----------------------------------------------------------------------------
  this.getShift = function () {
    return this.shift;
  };

  //  ----------------------------------------------------------------------------
  this.setShift = function (s) {
    this.shift = s; //   alert ('Axis.setshift ('+shift+')');
    return this;
  };

  //  ----------------------------------------------------------------------------
  this.getZero = function () {
    return new Point2d(this.x0, this.y0);
  };

  //  ----------------------------------------------------------------------------
  this.setViewLen = function (p) {
    this.viewLen = p;
    return this;
  };

  //  ----------------------------------------------------------------------------
  this.setxAxisFlag = function (f) {
    this.isXaxis = f;
    return this;
  };

  //  ----------------------------------------------------------------------------
  this.getMin = function () {
    return this.min;
  };

  //  ----------------------------------------------------------------------------
  this.getMax = function () {
    return this.max;
  };

  //  ----------------------------------------------------------------------------
  this.setMin = function (min) {
    this.min = min;
    return this;
  };

  //  ----------------------------------------------------------------------------
  this.setMax = function (max) {
    this.max = max;
    return this;
  };

  //  ----------------------------------------------------------------------------
  this.getValMin = function () {
    return this.scaler.getValMin();
  };

  //  ----------------------------------------------------------------------------
  this.getValMax = function () {
    return this.scaler.getValMax();
  };

  //  ----------------------------------------------------------------------------
  this.getValMinPixel = function () {
    return this.isXaxis ? this.p.transformX(this.o.x) : this.p.transformY(this.o.y);
  };

  //  ----------------------------------------------------------------------------
  this.getValMaxPixel = function () {
    return this.isXaxis ? this.p.transformX(this.o.x + this.viewLen) : this.p.transformY(this.o.y + this.viewLen);
  };

  //  ----------------------------------------------------------------------------
  this.getValInc = function () {
    return this.scaler.getValInc();
  };

  //  ----------------------------------------------------------------------------
  this.scaleValue = function (v) {
    return (this.isXaxis ? this.o.x : this.o.y) + this.scaler.scaleValue(v);
  };

  //  ----------------------------------------------------------------------------
  this.toPixels = function (v) {
    return this.isXaxis ? this.p.transformX(this.scaleValue(v)) : this.p.transformY(this.scaleValue(v));
  };

  //  ----------------------------------------------------------------------------
  this.unScale = function (v) {
    return this.scaler.unScale(v - (this.isXaxis ? this.o.x : this.o.y)); // - this.shift;
  };

  //  ---------------------------------------------------------------------------->
  this.toValue = function (pixelPos) {
    return this.unScale(this.p.toWorldX(pixelPos));
  };

  //  ---------------------------------------------------------------------------->
  this.rebuildValue = function (pixelPos) {
    return this.toValue(pixelPos).toFixed(this.getScaler().getPlaces() + 1);
  };

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

  //  ----------------------------------------------------------------------------
  this.drawPositionText = function (position, format) {
    //    alert (this.id+'.drawPositionText ('+position.toString()+', '+format+')');
    if (position == null) return this;
    //    var x = this.isXaxis ? this.scaleValue(position) : this.o.x + 0.2;
    //    var y = this.isXaxis ? this.o.y + 0.2 : this.scaleValue(position);
    var pos = this.calcPos(position, this.isXaxis, 0.2, 0.2);
    return this.add(new HWText(this.p, this.makePositionText(position, format), pos.x, pos.y, 12, this.posColor, null, null, 'middle').draw());
  };

  //  ----------------------------------------------------------------------------
  this.makePositionText = function (position, format) {
    return this.formatPosition(position, format);
  };

  //  ----------------------------------------------------------------------------
  this.formatPosition = function (position, format) {
    return position + '';
  };

  //  ----------------------------------------------------------------------------
  this.findPositionFormat = function (positions) {
    return 0;
  };

  //  ----------------------------------------------------------------------------
  this.setPositionFunctions = function (down, move, up) {
//    alert (this.id+'.setPositionFunctions: '+down+', '+move+', '+up);
    this.down = down;
    this.move = move;
    this.up   = up;
//    alert (this.id+'.setPositionFunctions: '+this.down+', '+this.move+', '+this.up);
    return this;
  };

  //  ----------------------------------------------------------------------------
  this.drawPosition = function (position, color) {
    if (wordy) alert(this.id + '.drawPosition (' + position + ', ' + color + ', ' + draggablePosX + ')');
    if (position == null) return this;
    return node = this.add(this.p.drawSymbol(this.scaleValue(position), this.o.y, 9, 5, 1, color));
  };

  //  ----------------------------------------------------------------------------
  this.changePositionText = function (node, position) {
    if (wordy) alert(this.id + '.changePositionText (' + position + ')');
    if (!node) return this;
    if (position == null) return this;
    return this.p.changeText(node, this.scaleValue(position), this.o.y + 0.2, position);
  };

  //  ----------------------------------------------------------------------------
  this.changePosition = function (node, position) {
    if (wordy) alert(this.id + '.changePosition (' + position + ')');
    if (!node) return this;
    if (position == null) return this;
    return this.p.changeSymbol(node, this.scaleValue(position), this.o.y, 8);
  };

  //  ----------------------------------------------------------------------------
  this.drawParallel = function (val, color) {
    var x0 = this.isXaxis ? this.o.x : val;
    var y0 = this.isXaxis ? val : this.o.y;
    return this.add(this.p.drawLine(x0, y0,(this.isXaxis ? x0 + this.viewLen : x0), 
                                           (this.isXaxis ? y0 : y0 + this.viewLen), 0, 1, color, 1.0));
//    alert (x0+', '+y0+', '+(this.isXaxis ? x0 + this.viewLen : x0)+', '+ 
//                           (this.isXaxis ? y0 : y0 + this.viewLen)+', '+ 0+', '+ 1+', '+ color+', '+ 1.0);
  };

  //  ----------------------------------------------------------------------------
  this.draw = function () {

    this.pxGridLen = (this.isXaxis ? 0.0 : this.viewLen);
    this.pyGridLen = (this.isXaxis ? this.viewLen : 0.0);

    this.x0 = this.o.x + (this.isXaxis ? 0.0 : this.shift);
    this.y0 = this.o.y + (this.isXaxis ? this.shift : 0.0);

    this.node = this.p.makeContainer(this.id);
    //    this.node = this.p.scale(this.id, this.factor);
    var pinDist = (this.gridFlag ? this.gridLen : this.defaultTickLen) * this.pinFac;
    var color = this.gridFlag ? this.gridColor : this.color;

    if (wordy) {
      alert('p.status: ' + this.p.status + ', ' + this.x0 + ', ' + this.y0 + ', ' + 1 + ', ' + (this.gridFlag ? this.gridLen : this.defaultTickLen) * this.pinFac + ', ' + this.isXaxis);}

    var t = new HWText(this.p, this.text, (this.isXaxis ? this.x0 + this.viewLen + 0.5 : this.x0 + 0.5), (this.isXaxis ? this.y0 : this.y0 + this.viewLen), this.fontSize, this.color);
    this.add(t.draw(t.LEFT, t.CENTER));
    this.add(this.p.drawLine(this.x0, this.y0, (this.isXaxis ? this.x0 + this.viewLen : this.x0), (this.isXaxis ? this.y0 : this.y0 + this.viewLen), 0, 1, this.color, 1.0));
    for (var i = 0; i <= this.scaler.getNumInc(); i++) { // -->
      this.val = this.calcValue(i);
      if (this.gridFlag) this.drawGrid(this.val, color);
      this.drawTickText(this.val, this.color);
      if (this.tickType > 0) {
        this.drawTick(this.val, pinDist, color);
        this.calcMeanAndMax(this.val);
        if (i != this.scaler.getNumInc()) this.drawMicroTicks(this.val, pinDist, color);
      }
    }
    if (wordy) 
      {alert("Axis.draw : " + (this.isXaxis ? "X" : "Y") + "-Achse mit Nullpunkt: (" + this.x0 + ", " + this.y0 + "), Länge " + this.viewLen + " und " + this.scaler.getNumInc() + " Inkrementen gezeichnet");}
    this.p.leaveContainer();
    this.p.paint();
    return this;
  };

  //  --------------------------------------------------------------------------->
  this.calcMeanAndMax = function (val) {
    this.jMax = 10;
    this.jMean = 5;
  };

  //  --------------------------------------------------------------------------->
  this.drawTick = function (val, pinDist, color) {
    var xPinDist = (this.isXaxis ? 0.0 : pinDist);
    var yPinDist = (this.isXaxis ? pinDist : 0.0);
    var pos = this.calcPos(val, this.isXaxis, 0.0, 0.0);
    this.drawTickLine(pos.x, pos.y, xPinDist, yPinDist, color);
  };

  //  --------------------------------------------------------------------------->
  this.drawTickLine = function (x, y, xPinDist, yPinDist, color) {
    this.add(this.p.drawLine((x - (this.isHalfOuter(this.tickType) ? 0 : xPinDist)), (y - (this.isHalfOuter(this.tickType) ? 0 : yPinDist)), (x + (this.isHalfInner(this.tickType) ? 0 : xPinDist)), (y + (this.isHalfInner(this.tickType) ? 0 : yPinDist)), 0, 1, color, 1.0));
  };

  //  --------------------------------------------------------------------------->
  this.isHalfInner = function (tickType) {
    return tickType == 2;
  };

  //  --------------------------------------------------------------------------->
  this.isHalfOuter = function (tickType) {
    return tickType == 3;
  };

  //  --------------------------------------------------------------------------->
  this.drawMicroTicks = function (val, pinDist, color) {
    var mic, pos;
    var xPinDist = (this.isXaxis ? 0.0 : pinDist);
    var yPinDist = (this.isXaxis ? pinDist : 0.0);
    for (var j = 1; j <= this.jMax; j++) { // -->
      mic = this.calcMicroValue(val, j, this.jMax);
      pos = this.calcPos(mic, this.isXaxis, 0.0, 0.0);
      this.drawTickLine(pos.x, pos.y, xPinDist * (j == this.jMean ? 0.6 : 0.3), yPinDist * (j == this.jMean ? 0.6 : 0.3), color);
    }
  };

  //  --------------------------------------------------------------------------->
  this.drawTickText = function (val, color) {
    var pos = this.calcPos(val, this.isXaxis, -0.1 - this.defaultTickLen * this.pinFac, -0.5);
    var t = new HWText(this.p, this.makeTickText(val, 0), pos.x, pos.y, 10, color);
    return this.add(t.draw(this.isXaxis ? t.CENTER : t.RIGHT, this.isXaxis ? t.UP : t.CENTER));
  };

  //  --------------------------------------------------------------------------->
  this.calcPos = function (val, isXaxis, dx, dy) {
    var x = isXaxis ? this.scaleValue(val) : this.o.x + dx + this.shift;
    var y = isXaxis ? this.o.y + dy + this.shift : this.scaleValue(val);
    return new this.p.Position2d(x, y);
  };

  //  --------------------------------------------------------------------------->
  this.makeTickText = function (v, inc) {
    var format = this.getScaler().getPlaces() + inc;
    v = parseFloat(v, 10);
    if (isNaN(v)) alert(this.id + '.makeTickText(' + v + ', ' + format + ')');
    return (format == undefined) ? v + '' : v.toFixed(format);
  };

  //  --------------------------------------------------------------------------->
  this.drawGrid = function (val, color) {
    if (val == 0.0) return;
    var xGridLen = (this.isXaxis ? 0.0 : this.gridLen);
    var yGridlen = (this.isXaxis ? this.gridLen : 0.0);
    var pos = this.calcPos(val, this.isXaxis, -this.shift, -this.shift); //.unShift (this.isXaxis, this.shift);
    this.add(this.p.drawLine(pos.x, pos.y, pos.x + xGridLen, pos.y + yGridlen, 0, 1, color, 1.0));
  };

  //  --------------------------------------------------------------------------->
  this.calcValue = function (i) {
    return this.scaler.calcValue(i);
  };

  //  --------------------------------------------------------------------------->
  this.calcMicroValue = function (val, j, jMax) {
    return val + j * this.scaler.getValInc() / jMax;
  };

  //  --------------------------------------------------------------------------->
  this.remove = function () {
    if (this.node) {
      this.p.removeNode(this.node);}
    return this;
  };

  //  --------------------------------------------------------------------------->
  this.redraw = function () {
    this.remove();
    return this.draw();
  };

  //  --------------------------------------------------------------------------->
  this.getContainer = function () {
    return this.node;
  };

  //  --------------------------------------------------------------------------->
  this.getPlot2d = function () {
    return this.p;
  };

  //  --------------------------------------------------------------------------->
  this.add = function (node) {
    return this.p.add(node);
  };

  //  --------------------------------------------------------------------------->
  this.makeCoordText = function (x, y, color, anchor) {
//    alert (this.id+'.makeCoordText ('+x+', '+y+', '+color+', '+anchor+')');
    var coord = this.makeCoord(x,y);
    var text = this.isXaxis ? this.makeTickText(x, 1) : this.makeTickText(y, 1);
    return new HWText(this.p, text, coord.x, coord.y, 14, color, null, null, anchor);
  };

  //  --------------------------------------------------------------------------->
  this.changeCoordText = function (txtObj, node, x, y, color, anchor) {
//    alert (this.id+'.changeCoordText ('+x+', '+y+', '+color+', '+anchor+')');
    var coord = this.makeCoord(x,y);
    var text = this.isXaxis ? this.makeTickText(x, 1) : this.makeTickText(y, 1);
    return txtObj.changeValue(node, text, coord.x, coord.y, 14, color, null, null, anchor);
  };

  //  --------------------------------------------------------------------------->
  this.makeCoord = function (x, y) {
    var coord = [];
    if (this.isXaxis) {
      coord['x'] = this.scaleValue(x);
      coord['y'] = this.getZero().y + (y < 0 ? 0.5 : -0.5);
    } else {
      coord['x'] = this.getZero().x + (x < 0 ? 0.5 : -0.5);
      coord['y'] = this.scaleValue(y);
    }
    return coord;
  };

  //  --------------------------------------------------------------------------->
  if (wordy) alert('Axis created');
}
