/*
 * swx.inv.ChartDataUpdater class containing things to get values for investor portal charts
 * and methods to update the chart
 * 
 * $Id: chart_dataUpdater.js,v 1.3 2010/07/05 13:18:27 obo Exp $
 */

dojo.declare("swx.inv.ChartDataUpdater", null, {
  
/*************************************************************************************************
 * Constructor                                                                                   *
 *************************************************************************************************/
  constructor: function(chart) {  // all arrays and complex objects should be declared here
    // save the size
    this._chart = chart;
    
    // the information in the infoline
    this._infoLine = null;
    
    // when to put the next point on the graph (in x minutes)
    this._nextGraphUpdateTime = new Date().getTime() + siteChartConfig.UPDATE_GRAPH_PERIOD;
    
    // save time by knowing if update of graph is needed
    this._needsUpdate = false;
    
    /*
     * downloadedData contains info on the downloaded data for each line (id, ...):
     * 
     * intradayDomain : the biggest intraday values domain we have (1d, 5d, ...)
     * intradayDate   : the oldest intraday values date we have 
     * 
     * intermediateDomain : the biggest historical values domain we have (6m, 1y, ...)
     * intermediateDate   : the oldest historical date
     * 
     * historicalDomain : the biggest historical values domain we have (6m, 1y, ...)
     * historicalDate   : the oldest historical date
     */
    this.downloadedData = {};
  },
  
  setInfoLine: function(infoLine) {
    this._infoLine = infoLine;
    this._updateInfoLineValues();
    
    // set the delay icon correctly and mouseover effect
    var infoDelayIconNode = dojo.byId("chartInfoDelayIcon" + this._chart.key);
    if (infoDelayIconNode) {
      if (infoLine.rt == 0) {
        infoDelayIconNode.src = DELAYED_15_IMG_SRC;
        infoDelayIconNode.title = DELAYED_15_TXT_STR;
      } else {
        infoDelayIconNode.src = DELAYED_0_IMG_SRC;
        infoDelayIconNode.title = DELAYED_0_TXT_STR;
      }
    }
  },
    
  // this is only for minicharts
  _updateInfoLineValues: function() {
    
    var monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
    if (this._infoLine) {

      // Modify lastTime so we don't see the seconds
      var lastTime = this._infoLine.lastTime;
      if (lastTime.indexOf(":") != lastTime.lastIndexOf(":"))
        lastTime = lastTime.substring(0, lastTime.lastIndexOf(":"));
      // update the div
      var infoLastTimeNode = dojo.byId("chartInfoLastTime" + this._chart.key);
      if (infoLastTimeNode)
        infoLastTimeNode.innerHTML = lastTime;

      // Modify closingDelta
      if ("-0.00%" == this._infoLine.closingDelta)
        this._infoLine.closingDelta = "0.00%";
      
      var infoClosingDeltaNode = dojo.byId("chartInfoClosingDelta" + this._chart.key);
      if (infoClosingDeltaNode) {
        infoClosingDeltaNode.innerHTML = this._infoLine.closingDelta;
        var color = "green";
        if (this._infoLine.closingDelta.indexOf("-") != -1) {
          color = "red";
        }
        dojo.style(infoClosingDeltaNode, "color", color);
      }


      // Modify closingPrice
      if (this._infoLine.closingPrice != "") {
        var infoClosingPriceNode = dojo.byId("chartInfoClosingPrice" + this._chart.key);
        if (infoClosingPriceNode)
          infoClosingPriceNode.innerHTML = this._infoLine.closingPrice;
      }


      if (this._infoLine.lastDate) {
        var lastDate = this._infoLine.lastDate;
        var day = lastDate.substring(0,2);
        var month = lastDate.substring(3,5);
        var year = lastDate.substring(8,10);
        // update the div
        var infoLastDateNode = dojo.byId("chartInfoLastDate" + this._chart.key);
        if (infoLastDateNode)
          infoLastDateNode.innerHTML = day + "." + month + "." + year;
      
        // set the javascript base lastDate
        var jsLastDate = new Date();
        jsLastDate.setHours(0);
        jsLastDate.setMinutes(0);
        jsLastDate.setSeconds(0);
        jsLastDate.setMilliseconds(0);
        jsLastDate.setFullYear(lastDate.substring(6,10));
        jsLastDate.setMonth(month-1);
        jsLastDate.setDate(day);
        this._infoLine.javascriptLastDate = jsLastDate;
        
        // Set full-format date if it is defined on the page (e.g. STOXX 2010)
        var fullFormatLastDateNode = dojo.byId("fullFormatLastDate" + this._chart.key);
        if (fullFormatLastDateNode)
          fullFormatLastDateNode.innerHTML =
            day + " " + monthNames[jsLastDate.getMonth()] + " " + jsLastDate.getFullYear();
        
        // do not update the lastDate again
        this._infoLine.lastDate = null; 
      }

      if (this._infoLine.movie && !this._chart.skipMovie) {
        var quotePlayer = new swx.QuotePlayer(this._infoLine.movie, 
                                              dojo.hitch(this, this._autoUpdateFromMovie), 
                                              dojo.hitch(this, this._autoGraphUpdate));
        // save the quoteplayer, it will be ticked automatically
        this._chart.quotePlayer = quotePlayer;
        
        // Do not use this movie again
        this._infoLine.movie = null;
      }
    }
  },
  
  _autoUpdateFromMovie: function(updateEvent) {
  	
    var what = updateEvent.columnid;
    
    // trim down the string and do nothing if it is empty
    // Also remove codes 0xA0 = 160 (comes in IE : non breaking space)
    if (updateEvent.newValue.replace(/^\s+|\s+$/g, '').replace(/\u00A0/g, "") == "") return; // nothing to do
    
    if (what == "ClosingDelta") {
      this._infoLine.closingDelta = updateEvent.newValue;
    } else if (what == "ClosingPrice") {
      this._infoLine.closingPrice = updateEvent.newValue;
      this._needsUpdate = true;
    } else if (what == "LastTime") {
      this._infoLine.lastTime = updateEvent.newValue;
    } else if (what == "LastDate") {   // if we changed date, reload the whole data
      this._needsUpdate = false; // stop updating graph, we will reload a new one
      this._chart.changeId(this._chart.id, true);
    }
    
  },
  
  _autoGraphUpdate: function(actualTime) {
  
    this._updateInfoLineValues();
    
    // we update the graphic every UPDAT_GRAPH_PERIOD
    if (actualTime > this._nextGraphUpdateTime && this._needsUpdate) {
      
      this._needsUpdate = false; // reset update info
      
      var lastTime = this._infoLine.lastTime;
      
      if (this._chart.useIntradayValues) {
        var hours = lastTime.substring(0,2);
        var mins  = lastTime.substring(3,5);
        var secs  = lastTime.substring(6,8);
        
        var lastDateTime = new Date(this._infoLine.javascriptLastDate);
        lastDateTime.setHours(hours);
        lastDateTime.setMinutes(mins);
        lastDateTime.setSeconds(secs);
        
        // check where to put the closingPrice knowing the lastDateTime
        this._updateIntraValues(lastDateTime, this._infoLine.closingPrice);
      } else {
        // change the value of the last day
        this._chart.values_domain.id.vals[this._chart.values_domain.id.vals.length - 1].y = this._infoLine.closingPrice;
      }
      try {
        this._chart.draw(true);  // try only to update the line if possible
      } catch (Exception) {}; // Sometimes an exception is thrown if we change values while updating the graph. (overview page)
      
      this._nextGraphUpdateTime = new Date().getTime() + siteChartConfig.UPDATE_GRAPH_PERIOD;
    }
  }, 
  
  _updateIntraValues: function(lastDateTime, closingPrice) {
    var i = 0;
    for (i=this._chart.values_domain.id.vals.length-1; i>0; i--) {
      var val = this._chart.values_domain.id.vals[i];
      if (val.d < lastDateTime) {
      	// we went too much back
      	if (i < this._chart.values_domain.id.vals.length-2) {
      	  val = this._chart.values_domain.id.vals[i+1]; // update the next point (if possible)
      	}
      	val.y = closingPrice;
      	return;
      }
    }
  },
  
  // Returns the values type according to the specified time range
  getValuesTypeFromDomain: function(timeRange) {
      var index = timeRange.indexOf("d");
      if (index > 0 && timeRange.substring(0,index) <= 10) {
        return swx.inv.Chart.prototype.statics.INTRADAY;
      } else {
        return swx.inv.Chart.prototype.statics.HISTORICAL;
      }
  },
  
  /*
   * This method will download all data needed to render the actual graph. It returns true if we had to do a ajax request
   */
  calculateAndDownloadDataIfNeeded: function(timeRange, callbackFunction, newDate, forceType) {
    if (timeRange == "ytd") {
      if (this._chart.type == this._chart.statics.ADVANCED) {
        timeRange = "1y"; // don't fool around with ytd, go for 1y in advanced charts
      }
    }
        
    var arraysToDownloadAndCalculate = this._getArraysToDownloadAndCalculate(timeRange, forceType);
     
    if (arraysToDownloadAndCalculate.arrayOfQueryStringsToDownload.length == 0) {
      return arraysToDownloadAndCalculate; // nothing to download, everything is in memory
    }
     
    // If we get here, we need to download some data to render the graph
    var queryString = balancerIdDefinition + "&id="+ this._chart.id +"&type="+ this._chart.type + "&"+ 
                      arraysToDownloadAndCalculate.arrayOfQueryStringsToDownload.join("&");
                      
    if (newDate) {
      // We are changing dates, force the chart to not use caching
      queryString += "&nd=true";
    }
    
    if (forceType) {
      queryString += "&fvt=" + forceType;
    }
        
    // do the downloading here with the queryString
    this._getAjaxValuesAndCall(queryString, callbackFunction);
     
     
    return arraysToDownloadAndCalculate;
  },
  
  downloadZoomedIntradayValues: function(arrayOfQueryStringsToDownload, callbackFunction) {
              
    var queryString = balancerIdDefinition + "&id="+ this._chart.id +"&type="+ this._chart.type 
                    + "&fvt=intraday&"      // We force the server to give us back intraday values
                    + arrayOfQueryStringsToDownload.join("&");
    
    // do the downloading here with the queryString
    this._getAjaxValuesAndCall(queryString, callbackFunction);
  },
  
  downloadZoomedIntermediateValues: function(arrayOfQueryStringsToDownload, callbackFunction) {
              
    var queryString = balancerIdDefinition + "&id="+ this._chart.id +"&type="+ this._chart.type 
                    + "&fvt=intermediate&"      // force values type
                    + arrayOfQueryStringsToDownload.join("&");
    
    // do the downloading here with the queryString
    this._getAjaxValuesAndCall(queryString, callbackFunction);
  },
      
  /*
   * returns null or an array of queryString items we need to download to show this timerange
   * forceType is used to avoid the 1m dilemna. If historical are needed for 1m, we can force.
   */
  _getArraysToDownloadAndCalculate: function(timeRange, forceType) {
    var retObj = {};
    retObj.arrayOfQueryStringsToDownload = [];
    retObj.arrayOfLineTypesToCalculate = [];
    
    var valuesType = this.getValuesTypeFromDomain(timeRange);
    if (forceType) valuesType = forceType;
    
    var showingTechIndicators = false;
    for (var lineType in this._chart.showedLines) {
      if (this._chart.showedLines[lineType] && lineType.indexOf("ti") == 0) {
        showingTechIndicators = true;
        break;
      }
    }
    
    var localTimeRange = timeRange;
    for (var lineType in this._chart.showedLines) {
      if (lineType == "id" && showingTechIndicators) {
        // For id, we might have to add some time for indicators like SMA
        localTimeRange = getIdTimeRangeDependingOnTechnicalIndicators(timeRange, valuesType, this._chart);
      }
      if (this._chart.showedLines[lineType] && 
          this._hasToDownloadOrCalculateDataForLineType(lineType, localTimeRange, valuesType)) {
        if (lineType.indexOf("ti") == 0 &&
            hasToCalculateDataForTechnicalIndicator(lineType, this._chart)) {
          // calculate data, do not download
          retObj.arrayOfLineTypesToCalculate.push([lineType, localTimeRange, valuesType]);
        } else {
          // set this lineType, etc... to the download queue
          try{
            var qstd = this._getQueryStringOfItemToDownload(lineType, localTimeRange, valuesType);
            retObj.arrayOfQueryStringsToDownload.push(qstd);
          } catch (error){console.error(error);}
        }
        
      } 
    }
    
    for (var eventType in this._chart.showedEvents) {
      if (this._chart.showedEvents[eventType] && 
          this._hasToDownloadOrCalculateDataForEvent(eventType)) {
        // set this lineType, etc... to the download queue
        var qs2 =  this._getQueryStringOfItemToDownload(eventType, localTimeRange, valuesType, true);
        retObj.arrayOfQueryStringsToDownload.push( qs2 );
      }
    }
    
    return retObj;
  },
  
  calculateData : function (arrayToCalculate) {
    var lineType = arrayToCalculate[0];
    var timeRange = arrayToCalculate[1];
    var valuesType = arrayToCalculate[2];
    
    if (lineType.indexOf("ti") == 0) {
      calculateDataForTechnicalIndicator(lineType, timeRange, valuesType);
      // set it as 'downloaded' = calulated
      this._setDownloadedDomainForLineType(lineType, timeRange, "", valuesType);
    }
  },
      
  _hasToDownloadOrCalculateDataForLineType: function(lineType, timeRange, valuesType) {
          
    if (!this.downloadedData[lineType]) return true; // nothing downloaded yet!

    if (valuesType==swx.inv.Chart.prototype.statics.INTRADAY) {
      if (!this.downloadedData[lineType].intradayDomain) return true; // no intraday downloaded yet
      var daysToDownload = timeRange.substring(0, timeRange.indexOf("d"));
      var daysDownloaded = this.downloadedData[lineType].intradayDomain.substring(0, 
                                  this.downloadedData[lineType].intradayDomain.indexOf("d"));
      return (parseInt(daysToDownload) > parseInt(daysDownloaded)); 
    
    } else if (valuesType==swx.inv.Chart.prototype.statics.INTERMEDIATE) {
      if (!this.downloadedData[lineType].intermediateDomain) return true; // no intermediate data downloaded yet
      
      var dateToDownload = domainDatesMap["_"+timeRange];
      var dateDownloaded = domainDatesMap["_"+this.downloadedData[lineType].intermediateDomain];
      return (dateToDownload < dateDownloaded); 
      
    } else {
      if (!this.downloadedData[lineType].historicalDomain) return true; // no historical data downloaded yet
      
      var dateToDownload = domainDatesMap["_"+timeRange];
      var dateDownloaded = domainDatesMap["_"+this.downloadedData[lineType].historicalDomain];
      
      return (dateToDownload < dateDownloaded);      
    }
    
  },
  
  _hasToDownloadOrCalculateDataForEvent: function(eventType) {
    // Take only the first word before "," separator
    var index = eventType.indexOf(",");
    if (index > 0) eventType = eventType.substring(0,index);
    if (this._chart.events[eventType]) {
      return false; // already loaded
    }
    return true;
  },
  
  _getQueryStringOfItemToDownload: function(lineType, timeRange, valuesType, isEvent) {
    if (isEvent) {
      return "event="+lineType+","+this._chart.showedEvents[lineType]; // showedEvents has language
    }
    
    // LineType, start and stop are always needed
    var queryString = "line=" + 
                      lineType +","+ 
                      timeRange +","+ 
                      this._getStopDomain(lineType, valuesType);
      
    if (lineType == "id") { // Basic line (add width)
      queryString += ","+ this._chart._chartLayout.graphWidth;

      //TODO: here go remaining Eurex PK attributes (expirationDate etc.)
      queryString += ","+ (this._chart.expirationDate != undefined ? this._chart.expirationDate : "");
      queryString += ","+ (this._chart.contractType != undefined ? this._chart.contractType : "");
      queryString += ","+ (this._chart.strikePrice != undefined ? this._chart.strikePrice : "");
      
      
    } else if (lineType.substring(0,3) == "idx") { // comparing to another security (add security id)
      queryString += ","+ this._chart.showedLines[lineType];
      
    } else if (lineType.substring(0,2) == "ti") { // technical indicator (add technical indicator id)
      queryString += ","+ this._chart.showedLines[lineType];
      
    }
    return queryString;
  },
  
  // finds the stop domain depending on the already downloaded domain
  _getStopDomain: function(lineType, valuesType) {
    if (! this.downloadedData[lineType]) this.downloadedData[lineType] = {}; // create object
    
    var domainType = "historicalDomain";
    if (valuesType==swx.inv.Chart.prototype.statics.INTRADAY) {
      domainType = "intradayDomain";
    } else if (valuesType==swx.inv.Chart.prototype.statics.INTERMEDIATE) {
      domainType = "intermediateDomain";
    }
    
    var alreadyDownloaded = this.downloadedData[lineType][domainType];
    
    if (alreadyDownloaded) {
      return alreadyDownloaded;
    } else {
      return "";
    }
  },
  
/*************************************************************************************************
 * getAjaxValues function. Used to init the chart values                                  *
 *************************************************************************************************/
  _getAjaxValuesAndCall: function(queryString, callbackFunction) {
        
    this._chart.chartDrawer.displayLoading();
    var _url = siteChartConfig.CHART_DATA_URL + "?" + queryString;
    var savedThis = this;

    dojo.xhrGet( {
        url          : _url,
        handleAs     : "json",
        timeout      : 20000,      // in miliseconds
        preventCache : true,

        load: function(response, ioArgs) {
            //console.log("ajax call");
            //console.log(response);
            savedThis._setDownloadedDomainForQueryString(queryString, response);
            savedThis._chart.chartDrawer.hideLoading();
            if (savedThis._chart.type != swx.inv.Chart.prototype.statics.SIMPLE)
              savedThis._chart.chartDrawer.displayInfotxt("Transforming..."); // TODO translate
            // use this settimeout to be sure the browser changed the preview text... to transforming
            setTimeout( function() {savedThis._consumeAjaxValues(response, callbackFunction);}, 0);
        },      // end load

        error: function(response, ioArgs) {
            savedThis._chart.chartDrawer.hideLoading();
            savedThis._chart.chartDrawer.displayInfotxt("Error..."); // TODO translate
            console.log("AJAX Error, HTTP status code: " + ioArgs.xhr.status +"\n"+response);
            //alert("Ajax error loading graph values... please try again later! Error code: " + ioArgs.xhr.status);
            return response;
        }       // end error

    } );        // end dojo.xhrGet

  },
  
  _setDownloadedDomainForQueryString: function(queryString, ajaxResponse) {
    
    var queryObject = dojo.queryToObject(queryString);
    
    if (queryObject.line) {
      var lines = [].concat(queryObject.line);
      for (var i in lines) {
        var elements = lines[i].split(",");
        var lineType = elements[0];
        var startDomain = elements[1];
        var stopDomain = elements[2];
        var valuesType = swx.inv.Chart.prototype.statics.HISTORICAL;
   
        if (ajaxResponse[lineType].historical) {
          valuesType = swx.inv.Chart.prototype.statics.HISTORICAL;
        } else if (ajaxResponse[lineType].intraDay) {
          valuesType = swx.inv.Chart.prototype.statics.INTRADAY;
        } else if (ajaxResponse[lineType].intermediate) {
          valuesType = swx.inv.Chart.prototype.statics.INTERMEDIATE;
        }
        this._setDownloadedDomainForLineType(lineType, startDomain, stopDomain, valuesType);   
      }
    }
    
    if (queryObject.event) {
      var events = [].concat(queryObject.event);
      for (var i in events) {
        var elements = events[i].split(",");
        var eventType = elements[0];
        
        this._chart.events[eventType] = {}; // put an empty object, might be filled with data
      }
    }
  },
  
  _setDownloadedDomainForLineType: function(lineType, startDomain, stopDomain, valuesType) {
    if (! this.downloadedData[lineType]) this.downloadedData[lineType] = {};
    
    if (startDomain.length == 8) {
      // start domain is a date, not a period
      this.downloadedData[lineType].lastRequestStart = startDomain;
      if (stopDomain.length==8) this.downloadedData[lineType].lastRequestStop = stopDomain;
      return;
    } 
    
    // if the request was done with a domain, reset these fields
    this.downloadedData[lineType].lastRequestStart = null;
    this.downloadedData[lineType].lastRequestStop = null;
    
    if (!valuesType) valuesType = this.getValuesTypeFromDomain(startDomain); 
    if (valuesType==swx.inv.Chart.prototype.statics.INTRADAY) {
      this.downloadedData[lineType].intradayDomain = startDomain;
    } else if (valuesType==swx.inv.Chart.prototype.statics.INTERMEDIATE) {
      this.downloadedData[lineType].intermediateDomain = startDomain;
    } else if (valuesType==swx.inv.Chart.prototype.statics.HISTORICAL) {
      this.downloadedData[lineType].historicalDomain = startDomain;
    }
  },
  
  _findExpectedStartDate : function(lineType) {
    var startDate = null;
    if (this.downloadedData[lineType]) startDate=this.downloadedData[lineType].lastRequestStart;
    if (startDate!=null)startDate = this._getDateFromFqsString(startDate);
    return startDate;
  },
  
  _findExpectedStopDate : function(lineType) {
    var stopDate=null;
    if (this.downloadedData[lineType]) stopDate=this.downloadedData[lineType].lastRequestStop;
    if (stopDate!=null) stopDate = this._getDateFromFqsString(stopDate); 
    return stopDate;  
  },
  
  _getDateFromFqsString : function(fqsDate) {
    var result = new Date();result.setDate(fqsDate.substring(6,8));result.setMonth(fqsDate.substring(4,6)-1);result.setYear(fqsDate.substring(0,4));result.setHours(0);result.setMinutes(0);result.setSeconds(0);result.setMilliseconds(0);return result;
  },
  
  _consumeAjaxValues: function(ajaxResponse, callbackFunction) {
    if (typeof ajaxResponse == "string") {
      alert("Ajax error");
      return;
    }
    // Do id first,we need it know which dates are ok! 
    if (ajaxResponse.id) {
      this._consumeAjaxValuesByLineType("id", ajaxResponse.id);
    }

    for (var lineType in ajaxResponse) {
      if ("id" == lineType) continue; // skip it, already done!
      if ("events" == lineType) continue; // skip events
      var err = this._consumeAjaxValuesByLineType(lineType, ajaxResponse[lineType]);
      
      if (err) {
        // remove the add on as no more data was found
        _addOn("", lineType);        
      }
    }
    // Do events if needed
    if (ajaxResponse.events) {
      this._consumeEvents(ajaxResponse.events);
    }
    
    if (this._chart.type == this._chart.statics.ADVANCED) {
            
      var isEmpty = true;
      for (var i in ajaxResponse) { isEmpty = false; break; } 

      if (!isEmpty) {
        // Call the callback function, (generally displayes values and redraws the graph)
        callbackFunction.call();
      } else {
        this._chart.draw(true);
      }
      
      // Now that the data is loaded, connect time range/style/volume buttons to make javascript calls
      if (!this._chart._functionsActive) {
        makeConnects();
        this._chart._functionsActive = true;
      }
    }
    
  },
  
  // return true if error
  _consumeAjaxValuesByLineType: function(lineType, ajaxResponse) {
    
    var somethingFound = false;
    
    var expectedStart = this._findExpectedStartDate(lineType);
    var expectedStop = this._findExpectedStopDate(lineType);
    
      // try to fill all that we can
    if (ajaxResponse.intraDay && (ajaxResponse.intraDay.vals || ajaxResponse.intraDay.oldClose)) {
      if (this._chart.values_intra[lineType]) {
        var newVals = [];
        var oldClose = this._chart.values_intra[lineType].oldClose;
        
        // We already have some intraday values, mix them with the new ones received
        var valsReceived = this._chart.valuesHelper.transformIntraValues( ajaxResponse.intraDay, true, lineType ).vals;
        var firstDateReceived = valsReceived[0].d;
        var index = 0;
        while (index < this._chart.values_intra[lineType].vals.length) {
          if (this._chart.values_intra[lineType].vals[index].d > firstDateReceived) break;
          index++;
        }
        
        if (index > 0) {
          // Set the new values = values received + old values after values received
          var oldValsBeforeReceived = this._chart.values_intra[lineType].vals.slice(0, index-1);
          newVals = oldValsBeforeReceived;
        } else {
          // the values received go before the old ones
          oldClose = ajaxResponse.intraDay.oldClose;
        }
        
        var lastDateReceived = valsReceived[valsReceived.length - 1].d;
        index = 0;
        while (index < this._chart.values_intra[lineType].vals.length) {
          if (this._chart.values_intra[lineType].vals[index].d > lastDateReceived) break;
          index++;
        }
        // Set the new values = values received + old values after values received
        var oldValsAfterReceived = this._chart.values_intra[lineType].vals.slice(index, this._chart.values_intra[lineType].vals.length);
        
        // Put it all together
        newVals = newVals.concat(valsReceived).concat(oldValsAfterReceived); 
        this._chart.values_intra[lineType].vals = newVals;
        this._chart.values_intra[lineType].oldClose = oldClose;
      } else {
        this._chart.values_intra[lineType] = this._chart.valuesHelper.transformIntraValues( 
          ajaxResponse.intraDay, this._chart.type == this._chart.statics.ADVANCED, lineType 
        );
      }
      somethingFound = true;
    }
    
    if (ajaxResponse.intermediate && (ajaxResponse.intermediate.vals || ajaxResponse.intermediate.oldClose)) {   
      if (this._chart.values_inter[lineType]) {
        var newVals = [];
        var oldClose = this._chart.values_inter[lineType].oldClose;
        
        // We already have some intraday values, mix them with the new ones received
        var valsReceived = this._chart.valuesHelper.transformIntermediateValues( ajaxResponse.intermediate, true, lineType, expectedStart, expectedStop).vals;
        var firstDateReceived = valsReceived[0].d;
        var index = 0;
        while (index < this._chart.values_inter[lineType].vals.length) {
          if (this._chart.values_inter[lineType].vals[index].d > firstDateReceived) break;
          index++;
        }
        if (index > 0) {
          // Set the new values = values received + old values after values received
          var oldValsBeforeReceived = this._chart.values_inter[lineType].vals.slice(0, index-1);
          newVals = oldValsBeforeReceived;
          valsReceived[0].newDay = true; // the first day is a new one
        } else {
          // the values received go before the old ones
          oldClose = ajaxResponse.intermediate.oldClose;
        }
        
        var lastDateReceived = valsReceived[valsReceived.length - 1].d;
        index = 0;
        while (index < this._chart.values_inter[lineType].vals.length) {
          if (this._chart.values_inter[lineType].vals[index].d > lastDateReceived) break;
          index++;
        }
        // Set the new values = values received + old values after values received
        var oldValsAfterReceived = this._chart.values_inter[lineType].vals.slice(index, this._chart.values_inter[lineType].vals.length);
        if (oldValsAfterReceived[0]) {
          oldValsAfterReceived[0].newDay = true; // in intermediate, first day of old ones is a new day
        }
        // Put it all together
        newVals = newVals.concat(valsReceived).concat(oldValsAfterReceived); 
        this._chart.values_inter[lineType].vals = newVals;
        this._chart.values_inter[lineType].oldClose = oldClose;
      } else {
        this._chart.values_inter[lineType] = this._chart.valuesHelper.transformIntermediateValues(ajaxResponse.intermediate, this._chart.type == this._chart.statics.ADVANCED, lineType, expectedStart, expectedStop);
      }
      somethingFound = true;
    }
    
    if (ajaxResponse.historical && ajaxResponse.historical.vals) {
      if (this._chart.values_days[lineType]) {
        // slice the actual values by removing the first data to avoid volume errors
        // but what if the data is not in ajaxresponse, check it
        var oldVals = this._chart.values_days[lineType].vals;
        var newVals = this._chart.valuesHelper.transformDailyValues( ajaxResponse.historical, true, lineType).vals;
        
        // we can have one (and no more) value that is in the two arrays
        if (newVals.length>0){
          if (oldVals[0].d==newVals[newVals.length-1].d) oldVals.slice(1, oldVals.length);
          if (newVals[0].d==oldVals[oldVals.length-1].d) newVals.slice(1, newVals.length);
        }
        
        this._chart.values_days[lineType].vals = newVals.concat(
              oldVals.slice(1, oldVals.length)
          );
      } else {
        this._chart.values_days[lineType] = this._chart.valuesHelper.transformDailyValues( 
          ajaxResponse.historical, this._chart.type == this._chart.statics.ADVANCED, lineType
        );
      }
      somethingFound = true;
    }
    
    if (ajaxResponse.infoLine) {
      this.setInfoLine(ajaxResponse.infoLine);
      somethingFound = true;
    }
    
    if (!somethingFound) {
      //alert("No data found!");
      return true;
    }
    if (this._chart.type == this._chart.statics.SIMPLE) {
      // set the correct values to be drawn for the simple case
      if (ajaxResponse.intraDay && (ajaxResponse.intraDay.vals || ajaxResponse.intraDay.oldClose)) {
        this._chart.useIntradayValues = true;
        this._chart.values_domain = this._chart.values_intra;
      } else if (ajaxResponse.intermediate && (ajaxResponse.intermediate.vals || ajaxResponse.intermediate.oldClose)) {
        this._chart.useIntradayValues = false;
        this._chart.values_domain = this._chart.values_inter;
      } else {
        this._chart.useIntradayValues = false;
        this._chart.values_domain = this._chart.values_days;
      }
      this._chart.draw();
    }
    return false;
  },
  
  /*
   * This method will download all events for the chart
   */
  downloadEventsIfNeeded: function(eventId, language, callbackFunction) {
    if (this._chart.events[eventId]) {
      return false; // already loaded
    }
    
    // If we get here, we need to download some data to render the graph
    var queryString = balancerIdDefinition + "&id="+ this._chart.id +"&type="+ this._chart.type +
                      "&event="+eventId+","+language;

    // do the downloading here with the queryString
    this._getAjaxValuesAndCall(queryString, callbackFunction);
     
    return true;
  },
  
  _consumeEvents: function(events) {
    if (events.divs) {
      this._chart.events.divs = this._chart.valuesHelper.transformDivsEvents( events.divs );
      this._chart.showedEvents.divs = true; // should be language but ok, since we already have them
    }
    if (events.news) {
      this._chart.events.news = this._chart.valuesHelper.transformNewsEvents( events.news );
      this._chart.showedEvents.news = true;
    }
    if (events.splits) {
      this._chart.events.splits = this._chart.valuesHelper.transformSplitEvents( events.splits );
      this._chart.showedEvents.splits = true;
    }
    if (events.generalMeetings) {
      this._chart.events.generalMeetings = this._chart.valuesHelper.transformGeneralMeetingsEvents( events.generalMeetings );
      this._chart.showedEvents.generalMeetings = true;
    }
    if (events.managementTransaction) {
      this._chart.events.managementTransaction = this._chart.valuesHelper.transformManagementTransactionEvents( events.managementTransaction );
      this._chart.showedEvents.managementTransaction = true;
    }
    if (events.amalgamations) {
      this._chart.events.amalgamations = this._chart.valuesHelper.transformAmalgamationEvents( events.amalgamations );
      this._chart.showedEvents.amalgamations = true;
    }
    if (events.ccychanges) {
      this._chart.events.ccychanges = this._chart.valuesHelper.transformCcyChangeEvents( events.ccychanges );
      this._chart.showedEvents.ccychanges = true;
    }
  }
    
});
    
    
