/*
 * $Id: chart_slider_Advanced.js,v 1.2 2010/09/06 13:13:00 obo Exp $
 */
dojo.declare("swx.inv.ChartSliderHelper", null, {

/*************************************************************************************************
 * Constructor                                                                                   *
 *************************************************************************************************/
  constructor: function(chartLayout, surface_coords_x, surface_offset_x) {  // all arrays and complex objects should be declared here

    this._chartLayout = chartLayout;       // save the chart

    this._leftLimit = chartLayout.marginLeft + chartLayout.paddingLeft;
    if (dojo.isIE) this._leftLimit += 2; // cheat

    this._surface_coords_x = surface_coords_x;
    this._surface_offset_x = surface_offset_x;

    // 2 vars used for connection onmousemove and onmouseup
    this.sliderMoveCon = null;
    this.sliderUpCon = null;

    // Save starting positions and sizes when clicked
    this.startEventX = null;
    this.startSliderLeft = null;
    this.startSliderWidth = null;

    // vars used to save a timout for left/right slidebar buttons (wait and then move constantly)
    this._leftRightButtonRedrawTimout = null;
    this._leftRightButtonRedrawInterval = null;

    this.moving = false;
    this.waitingMove = {};

    this.previewable = true;

    this._drawingTrackBar = false;
    this._init();

    // A cache object that will contain Max / Min / Open values for days
    this._intradayMaxMinOpenCache = {};
  },

/*************************************************************************************************
 * Static members ( You have to use this.statics.XXXX )                                          *
 *************************************************************************************************/
  statics: {
    MOVE_SLIDER_MIDDLE : 1,
    MOVE_SLIDER_LEFT   : 2,
    MOVE_SLIDER_RIGHT  : 3,

    PIXELS_TO_MOVE_WHEN_SLIDEBAR_BUTTON : 17

  },

/*************************************************************************************************
 * Private init function. Used to initialise everything                                          *
 *************************************************************************************************/
  _init: function() {
  },

  /**
   * Here are things used by the slider buttons...
   */

  /************************ slider functions ***********************/

  // Mouse clicked (DOWN) on something related to the slider, connect the onmousemove and onmouseup with the silder
  sliderDown: function(event, move_slider) {

    // disconnect old ones (maybe a bug or something in the browser)
    if (this.sliderMoveCon != null) dojo.disconnect(this.sliderMoveCon);
    if (this.sliderUpCon != null) dojo.disconnect(this.sliderUpCon);
    this.sliderUpCon = dojo.connect(document, "onmouseup", function() {advancedChart.chartDrawer.sliderHelper.sliderUp.call(advancedChart.chartDrawer.sliderHelper)});

    // Hide graph and show preview layer
    advancedChart.chartDrawer.preparePreview(true);
    clearHTML(); // Remove HTML Data

    var slider = dojo.byId("slider");
    this.startEventX = event.pageX;
    this.startSliderLeft = dojo.style(slider, "left");
    this.startSliderWidth = dojo.style(slider, "width");


    if (this.statics.MOVE_SLIDER_MIDDLE == move_slider) {
      // moving the slider by the middle part
      this.sliderMoveCon = dojo.connect(document, "onmousemove", function(event) {
        advancedChart.chartDrawer.sliderHelper.sliderMove.call(
                 advancedChart.chartDrawer.sliderHelper, event, event.pageX, swx.inv.ChartSliderHelper.prototype.statics.MOVE_SLIDER_MIDDLE) });
    } else {
      // moving left or right buttons


      if (this.statics.MOVE_SLIDER_LEFT == move_slider) {
        this.sliderMoveCon = dojo.connect(document, "onmousemove", function(event) {
          advancedChart.chartDrawer.sliderHelper.sliderMove.call(
                 advancedChart.chartDrawer.sliderHelper, event, event.pageX, swx.inv.ChartSliderHelper.prototype.statics.MOVE_SLIDER_LEFT) });
      } else if (this.statics.MOVE_SLIDER_RIGHT == move_slider) {
        this.sliderMoveCon = dojo.connect(document, "onmousemove", function(event) {
          advancedChart.chartDrawer.sliderHelper.sliderMove.call(
                 advancedChart.chartDrawer.sliderHelper, event, event.pageX, swx.inv.ChartSliderHelper.prototype.statics.MOVE_SLIDER_RIGHT) });
      }
    }
    dojo.stopEvent(event);
  },

  // Mouse unclicked (UP), remove all dojo.connect(document, "onmousemove" ... and draw graph
  sliderUp: function(event) {
    dojo.disconnect(this.sliderMoveCon);
    dojo.disconnect(this.sliderUpCon)
    this.sliderMoveCon = null;
    this.sliderUpCon = null;

    advancedChart.chartDrawer.displayInfotxt("Drawing..."); // TODO translate

    // use this settimeout to be sure the browser changed the preview text...
    setTimeout(dojo.hitch(this, function() {
      advancedChart.draw(true);
      var minIndex = Math.floor(advancedChart.values_domain.id.vals.length * advancedChart.displayedMinPercent);
      var maxIndex = Math.ceil(advancedChart.values_domain.id.vals.length * advancedChart.displayedMaxPercent) - 1;

      updateHTML(minIndex, maxIndex);
    }), 0);
  },

  // Mouse moved with something to do with the slider...
  sliderMove: function(event, pageX, move_slider) {

    // this part is because sliderMove is called more often than the browser draws the graph!
    if (this.moving) { // already doing something
      if (event != null) dojo.stopEvent(event); // stop this event
      // We save the latest x position that we want to draw
      this.waitingMove.pageX = pageX; // save the new position that we will have to draw
      this.waitingMove.move_slider = move_slider;
      clearTimeout(this.waitingMove.timeout);                       // Still drawing... stop old timeout
      this.waitingMove.timeout = setTimeout(
          function() { advancedChart.chartDrawer.sliderHelper.moveWaitingEvent.call(advancedChart.chartDrawer.sliderHelper) }, 50);
      return;
    }
    this.moving = true;  // we say we are now moving around

    if (this.statics.MOVE_SLIDER_MIDDLE == move_slider) {
      this.sliderMiddleMove(pageX);
    } else if (this.statics.MOVE_SLIDER_LEFT == move_slider) {
      this.sliderLeftButtonMove(pageX);
    } else if (this.statics.MOVE_SLIDER_RIGHT == move_slider) {
      this.sliderRightButtonMove(pageX);
    }

    setTimeout(function() { advancedChart.chartDrawer.sliderHelper.moving = false; }, 0);  // wait 0 ms! In fact, wait for the browser to draw everything :)
    if (event != null) dojo.stopEvent(event);
  },

  // full slider moved (middle part)
  sliderMiddleMove: function(pageX) {
    var newSliderLeft = this.startSliderLeft - this.startEventX + pageX;

    this._moveSliderToNewLeft(newSliderLeft, this.startSliderWidth);
  },

  _moveSliderToNewLeft: function(newSliderLeft, sliderWidth) {
    if (newSliderLeft < this._leftLimit) {
      newSliderLeft = this._leftLimit;
    }
    if (newSliderLeft + sliderWidth > this._leftLimit + this._chartLayout.graphWidth) {
      newSliderLeft = this._leftLimit + this._chartLayout.graphWidth - sliderWidth;
    }
    // do the color moving things before the slider itself (looks better)
    this.sliderMoved(newSliderLeft, newSliderLeft + sliderWidth);

    var slider = dojo.byId("slider");
    dojo.style(slider, "left", newSliderLeft);
  },

  // Left button (on slidebar) clicked
  sliderLeftButtonDown: function(event) {
    this._sliderLeftRightButtonDown(event, "left");
  },

  // Right button (on slidebar) clicked
  sliderRightButtonDown: function(event) {
    this._sliderLeftRightButtonDown(event, "right");
  },

  _sliderLeftRightButtonDown: function(event, leftOrRight) {
    this.sliderUpCon = dojo.connect(document, "onmouseup",
        function() {advancedChart.chartDrawer.sliderHelper.sliderButtonsUp.call(advancedChart.chartDrawer.sliderHelper, leftOrRight)}
    );

    if (leftOrRight == "left") {
      dojo.byId("slider_left_button").src = "/javascript/dojo-1.4.2/charts/images/slider-leftButton-down.gif";
    } else if (leftOrRight == "right") {
      dojo.byId("slider_right_button").src = "/javascript/dojo-1.4.2/charts/images/slider-rightButton-down.gif";
    }

    var pixelsToMove = this.statics.PIXELS_TO_MOVE_WHEN_SLIDEBAR_BUTTON;
    if (leftOrRight == "left") pixelsToMove *= -1; // move negatively

    // Hide graph and show preview layer
    advancedChart.chartDrawer.preparePreview(true);
    clearHTML(); // Remove HTML Data

    var slider = dojo.byId("slider");
    var sliderWidth = dojo.style(slider, "width");
    var newSliderLeft = dojo.style(slider, "left") + pixelsToMove;

    this._moveSliderToNewLeft(newSliderLeft, sliderWidth);

    this._leftRightButtonRedrawTimout = setTimeout(dojo.hitch(this, function() {

      this._leftRightButtonRedrawInterval = setInterval(dojo.hitch(this, function() {
        this._moveSliderToNewLeft(dojo.style(slider, "left") + pixelsToMove, sliderWidth);
      }), 50);

    }), 400);
    dojo.stopEvent(event);
  },

  sliderBackgroundDown: function(event) {
    this.sliderUpCon = dojo.connect(document, "onmouseup",
        function() {advancedChart.chartDrawer.sliderHelper.sliderButtonsUp.call(advancedChart.chartDrawer.sliderHelper)}
    );
    // Hide graph and show preview layer
    advancedChart.chartDrawer.preparePreview(true);
    clearHTML(); // Remove HTML Data

    var mouseX = event.pageX;

    var slider = dojo.byId("slider");
    var sliderWidth = dojo.style(slider, "width");
    var sliderLeft = dojo.style(slider, "left");

    var sliderPosition = dojo.coords("slider", true).x;
    var newSliderLeft = sliderLeft;
    if (mouseX < sliderPosition) {
      newSliderLeft -= sliderWidth;
    } else {
      newSliderLeft += sliderWidth;
    }

    this._moveSliderToNewLeft(newSliderLeft, sliderWidth);

    this._leftRightButtonRedrawTimout = setTimeout(dojo.hitch(this, function() {

      this._leftRightButtonRedrawInterval = setInterval(dojo.hitch(this, function() {
        var newLeft = dojo.style(slider, "left"); // this changes with time
        var sliderPosition = dojo.coords("slider", true).x; // this changes with time
        if (mouseX < sliderPosition) {
          newLeft -= sliderWidth;
          this._moveSliderToNewLeft(newLeft, sliderWidth);
        } else if (mouseX > sliderPosition + sliderWidth) {
          newLeft += sliderWidth;
          this._moveSliderToNewLeft(newLeft, sliderWidth);
        } else {
          this.sliderButtonsUp(); // we can not move anymore, stop everything
        }
      }), 50);

    }), 400);

  },

  sliderButtonsUp: function(leftOrRight) {
    dojo.disconnect(this.sliderUpCon)
    this.sliderUpCon = null;

    clearTimeout(this._leftRightButtonRedrawInterval); // stop the waiting for constant move
    clearInterval(this._leftRightButtonRedrawTimout); // stop constant moving

    if (leftOrRight == "left") {
      dojo.byId("slider_left_button").src = "/javascript/dojo-1.4.2/charts/images/slider-leftButton.gif";
    } else if (leftOrRight == "right") {
      dojo.byId("slider_right_button").src = "/javascript/dojo-1.4.2/charts/images/slider-rightButton.gif";
    }

    // use this settimeout to be sure the browser changed the slider background...
    setTimeout(dojo.hitch(this, function() {
      advancedChart.draw(true);
      var minIndex = Math.floor(advancedChart.values_domain.id.vals.length * advancedChart.displayedMinPercent);
      var maxIndex = Math.ceil(advancedChart.values_domain.id.vals.length * advancedChart.displayedMaxPercent) - 1;

      updateHTML(minIndex, maxIndex);
    }), 0);
  },

  // Left button moved
  sliderLeftButtonMove: function(pageX) {
    var newSliderLeft = this.startSliderLeft + pageX - this.startEventX;
    if (dojo.isIE == 6 && newSliderLeft % 2) newSliderLeft += 1; // cheat for IE6 (right side jumping)

    if (newSliderLeft < this._leftLimit) {
      newSliderLeft = this._leftLimit;
    }
    var newSliderWidth = this.startSliderWidth - newSliderLeft + this.startSliderLeft;

    if (newSliderWidth < MIN_SLIDER_WIDTH) {
      newSliderLeft = this.startSliderLeft + this.startSliderWidth - MIN_SLIDER_WIDTH;
      newSliderWidth = MIN_SLIDER_WIDTH;
    }

    var slider = dojo.byId("slider");
    dojo.style(slider, "left", newSliderLeft);
    dojo.style(slider, "width", newSliderWidth);

    this.sliderMoved(newSliderLeft, newSliderLeft + newSliderWidth);
  },

  // Right button moved
  sliderRightButtonMove: function(pageX) {
    var newSliderWidth = this.startSliderWidth + pageX - this.startEventX;

    if (this.startSliderLeft + newSliderWidth > this._leftLimit + this._chartLayout.graphWidth) {
      newSliderWidth = this._leftLimit + this._chartLayout.graphWidth - this.startSliderLeft;
    }
    if (newSliderWidth < MIN_SLIDER_WIDTH) {
      newSliderWidth = MIN_SLIDER_WIDTH;
    }
    var slider = dojo.byId("slider");
    dojo.style(slider, "width", newSliderWidth);
    this.sliderMoved(this.startSliderLeft, this.startSliderLeft + newSliderWidth);
  },

  // function called by a timeout to try to draw a x position we could not draw in the past (busy)
  moveWaitingEvent: function() {
    this.sliderMove(null, this.waitingMove.pageX, this.waitingMove.move_slider);
  },

  // Function really moving the divs and updating the graph
  sliderMoved: function(left, right) {
    advancedChart.displayedMinPercent = (left - this._leftLimit) / this._chartLayout.graphWidth;
    if (advancedChart.displayedMinPercent < 0) advancedChart.displayedMinPercent = 0;
    advancedChart.displayedMaxPercent = (right - this._leftLimit) / this._chartLayout.graphWidth;
    if (advancedChart.displayedMaxPercent > 1) advancedChart.displayedMaxPercent = 1;

    var minIndex = Math.round(advancedChart.values_domain.id.vals.length * advancedChart.displayedMinPercent);
    var maxIndex = Math.ceil(advancedChart.values_domain.id.vals.length * advancedChart.displayedMaxPercent) - 1;

    updateDates(minIndex, maxIndex);

    var width = right - left;
    left = left + this._surface_offset_x;

    // change divs for the selected range to show up
    dojo.style(dojo.byId("zoom_holder_color"), "left", -left);
    var selected_zone = dojo.byId("selected_zone");
    dojo.style(selected_zone, "left", left);
    dojo.style(selected_zone, "width", width);

    if (this.previewable) {
      advancedChart.drawPreview();
    }

    // Remove style for selectedTimeRange if it exists
    var node = dojo.byId("trh_"+selectedTimeRange);
    if (node != null) {
      // change old selected one
      dojo.removeClass(node, "selectedTimeRange");
      dojo.addClass(node, "nonSelectedTimeRange");
    }
  },

  moveSliderToDates: function(startDate, stopDate) {
    // Find the index of the dates for these dates
    var startIndex = 0;
    for (;startIndex<advancedChart.values_domain.id.vals.length; startIndex++) {
      if (advancedChart.values_domain.id.vals[startIndex].d >= startDate) {
        break;
      }
    }
    var stopIndex = 0;
    for (;stopIndex<advancedChart.values_domain.id.vals.length; stopIndex++) {
      if (advancedChart.values_domain.id.vals[stopIndex].d > stopDate) {
        break;
      }
    }

    var leftPixels = this._leftLimit + startIndex / advancedChart.values_domain.id.vals.length * this._chartLayout.graphWidth;
    var rightPixels = this._leftLimit + stopIndex / advancedChart.values_domain.id.vals.length * this._chartLayout.graphWidth;

    this.sliderMoved(leftPixels, rightPixels);

    var slider = dojo.byId("slider");
    dojo.style(slider, "left", leftPixels);
    dojo.style(slider, "width", rightPixels - leftPixels);
  },

  resetSlider: function() {
    this.sliderMoved(this._leftLimit, this._leftLimit + this._chartLayout.graphWidth);

    var slider = dojo.byId("slider");
    dojo.style(slider, "left", this._leftLimit);
    dojo.style(slider, "width", this._chartLayout.graphWidth);

  },

  /************************ end slider functions ***********************/

  /************************ trackball functions ************************/
  trackMove: function(event) {

    if (!this._drawingTrackBar) { // do not try to draw too much! IE shoots himself in the foot!
      this._drawingTrackBar = true;
      var pos = event.pageX - this._surface_coords_x - this._leftLimit;
      if (pos < 0) pos = 0;
      if (pos > this._chartLayout.graphWidth) pos = this._chartLayout.graphWidth;

      this.trackMovedToPosition(pos);

      // Use setTimeout to reset the _drawingTrackBar to false in 0ms. Let's IE recover
      setTimeout(function() { advancedChart.chartDrawer.sliderHelper._drawingTrackBar = false; }, 0);  // wait 0 ms! In fact, wait for the browser to draw everything :)
    }

    if (event != null) dojo.stopEvent(event); // stop this event
  },

  trackMovedToPosition: function(pos) {
    try {
      var index = Math.round(pos * (advancedChart.values_displayed.id.points.length - 1) / this._chartLayout.graphWidth);

      // each point has a i
      var point = advancedChart.values_displayed.id.points[index];

      if (!point.open) {
        // No opening price, we are not on a trade, find the nearest trade (left or right)
        // this is for intraday values for example that are not traded often
        var leftIndex = index - 1;
        while (leftIndex >= 0 && !advancedChart.values_displayed.id.points[leftIndex].open) {
          leftIndex--;
        }
        var rightIndex = index;
        while (rightIndex < advancedChart.values_displayed.id.points.length &&
                 !advancedChart.values_displayed.id.points[rightIndex].open) {
          rightIndex++;
        }
        if (leftIndex >= 0) { // left index is valid
          if ( rightIndex < advancedChart.values_displayed.id.points.length
               && (rightIndex - index) < (index - leftIndex)) {
            // right index is also valid and distance is smaller
            index = rightIndex;
          } else { // right index is invalid, take the left one
            index = leftIndex;
          }
        } else if (rightIndex < advancedChart.values_displayed.id.points.length) {
          // right index is valid, take it
          index = rightIndex;
        } else {
          // NO POINT AT ALL FOR THE WHOLE DAY! treated later
        }
        point = advancedChart.values_displayed.id.points[index];
      }

      var valOpen = advancedChart.values_displayed.id.vals[point.open_i];
      var date = chartGetNiceDate(valOpen.date);

      var valDay = null;

      if (advancedChart.values_displayed.id.valuesType != swx.inv.Chart.prototype.statics.INTRADAY
          && advancedChart.values_displayed.id.valuesType != swx.inv.Chart.prototype.statics.INTERMEDIATE) {
        if (point.days > 1) {
          var valClose = advancedChart.values_displayed.id.vals[point.close_i];
          date += "-"+chartGetNiceDate(valClose.date);
        }
      } else { // intraday value

        valDay = this._getIntradayMaxMinOpen(valOpen, point.open_i);

//        var startRange = new Date(valOpen.date);
//        if (!point.firstTradeOfDay) {
//          startRange.setMinutes( startRange.getMinutes() - swx.inv.ChartValuesHelper.prototype.statics.PAID_INTERVAL_MINS);
//        }
//        var startMins = startRange.getMinutes();
//        if (startMins < 10) startMins = "0"+startMins;
//        time = " ("+startRange.getHours()+":"+startMins;

        var stopRange = new Date(advancedChart.values_displayed.id.vals[point.close_i].date);
        // Cheat for single intraday values (first trade)
        if (point.firstTradeOfDay && point.days == 1) { // add swx.inv.ChartValuesHelper.prototype.statics.PAID_INTERVAL_MINS min
          stopRange.setMinutes( stopRange.getMinutes() + swx.inv.ChartValuesHelper.prototype.statics.PAID_INTERVAL_MINS);
        }
        time = "("+chartGetNiceHourMinutes(stopRange)+") : ";

      }

      var tb = dojo.byId("trackBall");

      dojo.byId("trackDate").innerHTML = date
      if (!point.open
          || (advancedChart.values_displayed.id.valuesType == swx.inv.Chart.prototype.statics.INTRADAY && !valDay)
          || (advancedChart.values_displayed.id.valuesType == swx.inv.Chart.prototype.statics.INTERMEDIATE && !valDay)
          ) {
        dojo.byId("trackOpen").innerHTML = "-";
        dojo.byId("trackHigh").innerHTML = "-";
        dojo.byId("trackLow").innerHTML = "-";
        dojo.byId("trackClose").innerHTML = "-";
        if (advancedChart.values_displayed.id.valuesType == swx.inv.Chart.prototype.statics.INTRADAY) {
          dojo.byId("trackPrice").innerHTML = ": -";
        }

        dojo.style(tb, "left", -1000); // Hide the crosshair if no point to display
        advancedChart.chartDrawer._axisGridDrawer._horiTrackLine.applyTransform({ dy: -1000 });
        advancedChart.chartDrawer._axisGridDrawer._vertTrackLine.applyTransform({ dx: -1000 });
        return; // do nothing with the crosshair
      }

      if (advancedChart.values_displayed.id.valuesType == swx.inv.Chart.prototype.statics.INTRADAY
          || advancedChart.values_displayed.id.valuesType == swx.inv.Chart.prototype.statics.INTERMEDIATE) {
        dojo.byId("trackOpen").innerHTML = chartGetNiceNumber(valDay.open, 2);
        dojo.byId("trackHigh").innerHTML = chartGetNiceNumber(valDay.max, 2);
        dojo.byId("trackLow").innerHTML = chartGetNiceNumber(valDay.min, 2);
        dojo.byId("trackClose").innerHTML = chartGetNiceNumber(valDay.y, 2);
        dojo.byId("trackPrice").innerHTML = time + chartGetNiceNumber(point.close, 2);
      } else {
        dojo.byId("trackOpen").innerHTML = chartGetNiceNumber(point.open, 2);
        dojo.byId("trackHigh").innerHTML = chartGetNiceNumber(point.max, 2);
        dojo.byId("trackLow").innerHTML = chartGetNiceNumber(point.min, 2);
        dojo.byId("trackClose").innerHTML = chartGetNiceNumber(point.close, 2);
      }

      if (advancedChart.graph_values.id.points.length ==
          advancedChart.values_displayed.id.points) {
        // Every point has it's trade values, use the graph values
        var pointPixel = advancedChart.graph_values.id.points[index];
      } else {
        // Some points have no trade, recalculate the pixels of the value
        var pointPixel = {};
        var leftSpace = advancedChart._chartLayout.marginLeft + advancedChart._chartLayout.paddingLeft;
        var topSpace  = advancedChart._chartLayout.marginTop  + advancedChart._chartLayout.paddingTop;
        pointPixel.px = Math.floor(leftSpace + advancedChart._chartLayout.graphWidth * (point.i) / (advancedChart.values_displayed.id.vals.length - 1));
        pointPixel.close = Math.floor(topSpace + advancedChart._chartLayout.graphHeight * (1 - (point.close - advancedChart.values_displayed.id.gMin) / advancedChart.values_displayed.id.gRange));
      }
      // change trackball position
      var left = pointPixel.px;
      var top = pointPixel.close;

      if (advancedChart.chartDrawer.crosshairStyle == swx.inv.ChartDrawer.prototype.statics.CROSSHAIR_SMALL_STYLE) {
        if (dojo.isIE) {
          left += 2;
          top += 1;
        }
        left -=  8;
        top -= 7;
        dojo.style(tb, "left", left);
        dojo.style(tb, "top", top);
      } else if (advancedChart.chartDrawer.crosshairStyle == swx.inv.ChartDrawer.prototype.statics.CROSSHAIR_FULL_STYLE) {
        var oldy = 0;
        var trans = advancedChart.chartDrawer._axisGridDrawer._horiTrackLine.getTransform();
        if (trans != null) {
          oldy = trans.dy;
        }
        var oldx = 0;
        var trans = advancedChart.chartDrawer._axisGridDrawer._vertTrackLine.getTransform();
        if (trans != null) {
          oldx = trans.dx;
        }
        advancedChart.chartDrawer._axisGridDrawer._horiTrackLine.applyTransform({ dy: top - oldy + 1000 });
        advancedChart.chartDrawer._axisGridDrawer._vertTrackLine.applyTransform({ dx: left - oldx + 1000 });
      }


    } catch (ex) {
      console.log("Exception in trackMovedToPosition: "+ex);
    }

  },

  setHistoricalTrackLine: function() {
    dojo.style("trackOpenLabel", "left", "155px");
    dojo.style("trackHighLabel", "left", "250px");
    dojo.style("trackLowLabel", "left", "345px");
    dojo.style("trackCloseLabel", "left", "438px");

    dojo.style("trackPriceLabel", "display", "none");
    dojo.style("trackPrice", "display", "none");
  },

  setDailyTrackLine: function() {
    dojo.style("trackOpenLabel", "left", "77px");
    dojo.style("trackHighLabel", "left", "167px");
    dojo.style("trackLowLabel", "left", "252px");
    dojo.style("trackCloseLabel", "left", "337px");

    dojo.style("trackPriceLabel", "display", "");
    dojo.style("trackPrice", "display", "");
  },

  // Get the Max, Min, Open and Close values for a given day from the intraday
  // values and put them into an object in cache to save time!
  _getIntradayMaxMinOpen: function(value, index) {

    var stringDateKey = ""+value.dayDate+value.month+value.fullyear;

    var retObj = this._intradayMaxMinOpenCache[stringDateKey];
    if (retObj == null) {

      retObj = {};
      retObj.open = value.open;
      retObj.max = value.max;
      retObj.min = value.min;
      retObj.y = value.y;

      // Look for all points the same day before this one
      var tmpIndex = index - 1;
      while (tmpIndex > 0) {
        var tmpVal = advancedChart.values_displayed.id.vals[tmpIndex];
        if (tmpVal.dayDate != value.dayDate) break; // changed day
        if (tmpVal.month != value.month) break;     // changed day
        if (tmpVal.min) retObj.min = this._myMathMinWithNulls(tmpVal.min, retObj.min);
        if (tmpVal.max) retObj.max = this._myMathMaxWithNulls(tmpVal.max, retObj.max);
        if (tmpVal.open) retObj.open = tmpVal.open;
        tmpIndex--;
      }
      // Look for all points the same day after this one
      tmpIndex = index + 1;
      while (tmpIndex < advancedChart.values_displayed.id.vals.length) {
        var tmpVal = advancedChart.values_displayed.id.vals[tmpIndex];
        if (tmpVal.dayDate != value.dayDate) break; // changed day
        if (tmpVal.month != value.month) break;     // changed day
        if (tmpVal.min) retObj.min = this._myMathMinWithNulls(tmpVal.min, retObj.min);
        if (tmpVal.max) retObj.max = this._myMathMaxWithNulls(tmpVal.max, retObj.max);
        if (tmpVal.y) retObj.y = tmpVal.y;
        if (!retObj.open && tmpVal.open) retObj.open = tmpVal.open;
        tmpIndex++;
      }

      this._intradayMaxMinOpenCache[stringDateKey] = retObj;
    }
    return retObj;


  },

  // Overwriting the Math.min and Math.max to only take values which are not null
  _myMathMinWithNulls: function(min1, min2) {
    if (min1 && min2) return Math.min(min1, min2);
    if (min1) return min1;
    return min2;
  },
  _myMathMaxWithNulls: function(max1, max2) {
    if (max1 && max2) return Math.max(max1, max2);
    if (max1) return max1;
    return max2;
  }

  /********************** end trackball functions **********************/

});
