/*
  Defines ActiveInterface if it doesn’t already exist, using the boolean OR operator
  to provide a default value if one isn’t found.
  Could also use
    if(!window.ActiveInterface) ActiveInterface = {};
*/
var ActiveInterface = window.ActiveInterface || {};

ActiveInterface.IndicatorViews = (function() {

  // Private members
  var privateMember1 = false;
  var months = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
  function privateMethod1() {
    ;
  }

  // -------------------------------------------------------------------------
  function makeHtmlTitle(csettings, mid, charttitle) {

    var cstitle = csettings.title.replace("|","<br/>");
    var mover = csettings.measureOverrides["m"+mid];
    if (typeof(mover) != "undefined" && mover.length > 0 && mover[0].length > 0) { 
      cstitle = cstitle.replace("?",mover[0]);
    }
    if (charttitle)
      cstitle += "<br/>" + charttitle;
    return cstitle;
  }

  // -------------------------------------------------------------------------
  function addCommas(nStr, precision) {
    nStr += '';
    if (nStr.indexOf('.') != -1 && precision) {
      nStr = parseFloat(nStr).toFixed(precision).toString();
    }
    x = nStr.split('.');
    x1 = x[0];
    x2 = x.length > 1 ? '.' + x[1] : '';
    var rgx = /(\d+)(\d{3})/;
    while (rgx.test(x1)) {
      x1 = x1.replace(rgx, '$1' + ',' + '$2');
    }
    return x1 + x2;
  }

  // -------------------------------------------------------------------------
  function singleRecentColumn(indata,tsettings) {

    var mrv, mrfv;
    var region;
    var col;
    var rc = indata.getNumberOfRows();
    var cc = indata.getNumberOfColumns();

    // build new horizontally flattened table
    var outdata = new google.visualization.DataTable();
    outdata.addColumn('string', 'Region');
    outdata.addColumn('number', 'Value');

    outdata.addRows(rc);

    var c1 = indata.getColumnLabel(cc-1);

    if (typeof(tsettings) != "undefined") {
      if (tsettings.columnFormat == "year") {
        c1 = c1.substring(0,4);
      } else if (tsettings.columnFormat.length > 0) {
        c1 = tsettings.columnFormat;
      } else {
        // default HACK: use latest period for new table column
        c1 = c1.substring(0,4)
      }
    } else {
      // default HACK: use latest period for new table column
      c1 = c1.substring(0,4)
    }

    outdata.setColumnLabel(1,c1);

    for (var i = 0; i < rc; i++) {
       col = cc-1;

       do {
          mrv = indata.getValue(i, col);
          mrfv = indata.getFormattedValue(i, col);
       } while (mrv == null && --col >= 0 );
       if (mrv == null) {
         mrv = 0;
         mrfv = "0";
       }

       outdata.setValue(i, 1, mrv);
       outdata.setFormattedValue(i, 1, mrfv);

       region = indata.getValue(i, 0);
// HACK - only works for years
       if (col != cc-1)
          region += " (" + indata.getColumnLabel(col).substring(0,4) + ")";
       outdata.setValue(i, 0, region);
    }
    return outdata;

  }

  // -------------------------------------------------------------------------
  function addBenchmarkRow(data,numfmt) {

    var rc = data.getNumberOfRows();
    var s = 0; // non pgh sum
    var hadBench = false;
    var dv;

    for (var i = 0; i < rc; i++) {
      dv = data.getValue(i, 0);
      if (dv.substring(0,5) == "Bench") {
         hadBench = true;
         break;
      } else if (dv.indexOf(this.benchmarkRegion) == -1) {
        s += data.getValue(i, 1);
      }
    }

    if (!hadBench) {
      rc--;
      // add benchmark row
      data.insertRows(rc,1);
      data.setValue(rc, 0, "Benchmark avg");
      // set value to average
      dv = s/rc;
      data.setValue(rc, 1, dv);
      data.setFormattedValue(rc, 1, dv.numberFormat(numfmt));
    }
  }

  // -------------------------------------------------------------------------
  function addBenchmarkRow2(data) {
    var rc = data.getNumberOfRows();
    var s1 = 0; // non pgh col1 sum
    var s2 = 0; // non pgh col2 sum
    var dv;

    for (var i = 0; i < rc; i++) {
      dv = data.getValue(i, 0);
      if (dv.indexOf(this.benchmarkRegion) == -1) {
        s1 += data.getValue(i, 1);
        s2 += data.getValue(i, 2);
      }
    }

    rc--;
    // add benchmark row
    data.insertRows(rc, 1);
    data.setValue(rc, 0, "Benchmark avg");
    // set value to average
    data.setValue(rc, 1, s1/rc);
    data.setValue(rc, 2, s2/rc);

  }

  // -------------------------------------------------------------------------
  function log(func, msg) {
    try {
      ; //console.info('ActiveInterface.IndicatorViews::' + func + '(): ' + msg);
    } catch(e) {}
  }


  // Everything returned in the object literal is public, but can access the
  // members in the closure created above.
  return {
    
    // Public members
    dataTables : null,
    viewElements : null,
    viewSettings : null,
    viewType: 'table',
    benchmarkRegion: 'Pittsburgh',
    
    // Methods
    
    init : function(vsettings) {
      this.viewSettings = vsettings;
      this.dataTables = new Object();
      log('init', 'Begin initiation');
    },

    // ---------------------------------------------------------------
    setDataSourceInfo: function(csettings, mid)
    {
    var mover = csettings.measureOverrides["m"+mid];
    // if measure overrides
    if (typeof(mover) != "undefined") {
      // if override has a "source label"
      if (mover[3].length > 0 ) {
        // if override has a "source url"
        if (mover[4].length > 0 ) {
          $("#subbody .datasourceinfo").html("<a href='" +mover[4]+ " '>" +mover[3]+ "</a>");
        } else {
          $("#subbody .datasourceinfo").text(mover[3]);
        }
      }
    }
    },

    // ---------------------------------------------------------------
    showRawTable : function(dataname, target1, target2, tsettings, csettings, mid) {

       var data = this.dataTables[dataname];
       var rh;
       var dv;
       var nf;
       var s;
       var pghrow;
       var comprow = -1;

       var cc = data.getNumberOfColumns();
       var rc = data.getNumberOfRows();

       if (tsettings.columnFormat == "year") {
         var c1;
         for (var j = 1; j < cc; j++) {
            c1 = data.getColumnLabel(j);
            data.setColumnLabel(j,c1.substring(0,4));
         }
       }
       if (tsettings.rowFormat == "month") {
         data.insertColumn(0, "string", "Month");
         for (var i = 0; i < rc; i++) {
            rh = data.getValue(i, 1);
            data.setValue(i, 0, months[parseInt(rh)-1]);
         }
         data.removeColumn(1);

         // add total row at bottom
         data.insertRows(rc,1);
         data.setValue(rc, 0, "Year to date");
         for (var j = 1; j < cc; j++) {
           nf = data.getColumnPattern(j);
           s = 0;
           for (var i = 0; i < rc; i++) {
             s += data.getValue(i, j);
           }
           data.setValue(rc, j, s);
           data.setFormattedValue(rc, j, s.numberFormat(nf));
         }

       } else {

         // add benchmark row (if needed)
         if (this.viewSettings.calcAvg) {
          for (var i = 0; i < rc; i++) {
           dv = data.getValue(i, 0);
           if (dv.substring(0,5) == "Bench") {
             comprow = i;
             break;
           }
          }
          // no bench found - add one
          if (comprow == -1) {
           data.insertRows(rc,1);
           data.setValue(rc, 0, "Benchmark avg");
           for (var j = 1; j < cc; j++) {
             nf = data.getColumnPattern(j);
             // sum across regions
             s = 0;
             for (var i = 0; i < rc; i++) {
              dv = data.getValue(i, 0);
              if (dv.indexOf(this.benchmarkRegion) == -1 && dv.substring(0,2) != "US") {
                s += data.getValue(i, j);
              }
             }
             dv = s/rc;
             data.setValue(rc, j, dv);
             data.setFormattedValue(rc, j, dv.numberFormat(nf));
           }
           comprow = rc;
          }
         } //if (calcAvg)
  
       } //rowformat == "month"

       var t = new google.visualization.Table(document.getElementById(target1));
       t.draw(data, {showRowNumber: false});


       if (target2 == null) {

         var title = makeHtmlTitle(csettings, mid, null);
         $("#chart_title").html(title);

       } else {

       // find pgh row
       for (var i = 0; i < rc; i++) {
         region = data.getValue(i, 0);
         if (region.indexOf(this.benchmarkRegion) != -1)
            pghrow = i;
       }


       $("#"+target2).empty();
       var data2 = new google.visualization.DataTable();
       data2.addRows(cc-1);

       nf = data.getColumnPattern(1);

       data2.addColumn('string', 'Period');
       data2.addColumn('number', data.getValue(pghrow, 0));
       data2.addColumn('number', data.getValue(comprow, 0));

       var vstitle = data.getValue(pghrow, 0) + " vs. " + data.getValue(comprow, 0);
       var title = makeHtmlTitle(csettings, mid, vstitle);
       $("#chart_title").html(title);

       for (var j = 1; j < cc; j++) {
         data2.setValue(j-1, 0, data.getColumnLabel(j));

         dv = data.getValue(pghrow, j);
         data2.setValue(j-1, 1, dv);
         data2.setFormattedValue(j-1, 1, dv.numberFormat(nf));

         dv = data.getValue(comprow, j);
         data2.setValue(j-1, 2, dv);
         data2.setFormattedValue(j-1, 2, dv.numberFormat(nf));
       }

/*
// test code
// This seems to have same effect as doing a setFormattedValue and
// in fact takes precedence over it. But it doesn't change the y-axis
// formatting
var formatter = new google.visualization.NumberFormat(
  {
    groupingSymbol:',', 
    decimalSymbol: '.',
    fractionDigits: 1,
    suffix: '%'
  }
);
formatter.format(data2, 1);
formatter.format(data2, 2);
*/


       var c = new google.visualization.LineChart(document.getElementById(target2));
       c.draw(data2, {colors:['#cb2027','#686868'],backgroundColor:'#ebebeb',legendBackgroundColor:'#ebebeb',axisFontSize:12,legendFontSize:12,titleFontSize:12,width:csettings.width,height:csettings.height,is3D:false,reverseAxis:false,legend:'bottom'});

       google.visualization.events.addListener(t, 'select', 
         function () {
            comprow = t.getSelection()[0].row;
            vstitle = data.getValue(pghrow, 0) + " vs. " + data.getValue(comprow, 0);
            title = makeHtmlTitle(csettings, mid, vstitle);
            $("#chart_title").html(title);
            data2.setColumnLabel(2,data.getValue(comprow, 0));
            for (var j = 1; j < cc; j++) {
              data2.setValue(j-1, 0, data.getColumnLabel(j));
              data2.setValue(j-1, 1, data.getValue(pghrow, j));
              data2.setValue(j-1, 2, data.getValue(comprow, j));
            }
            c.draw(data2, {colors:['#cb2027','#686868'],backgroundColor:'#ebebeb',legendBackgroundColor:'#ebebeb',axisFontSize:12,legendFontSize:12,titleFontSize:12,width:csettings.width,height:csettings.height,is3D:false,reverseAxis:false,legend:'bottom'});

         }
       );
         
       } // if (target2)

    },

    // ---------------------------------------------------------------
    showChangeTable : function(dataname, target1, target2, tsettings, csettings, mid) {
       var data = this.dataTables[dataname];

       var rc = data.getNumberOfRows();
       var cc = data.getNumberOfColumns();
       var c1, t1, t2, ac, pc;
       var pghrow;
       var comprow;
       var region;
       var formatter;
       var s;
       var nf;
       var dv;

       // since we calculate delta, new table will have one fewer value columns
       var newcc = cc - 1; 

       // add benchmark row
       data.insertRows(rc,1);
       data.setValue(rc, 0, "Benchmark avg");
       for (var j = 1; j < cc; j++) {
          nf = data.getColumnPattern(j);
          // sum across regions
          s = 0;
          for (var i = 0; i < rc; i++) {
            s += data.getValue(i, j);
          }
          dv = s/rc;
          data.setValue(rc, j, dv);
          //data.setFormattedValue(rc, j, dv.numberFormat(nf));
       }

       var data2 = new google.visualization.DataTable();
       data2.addRows(rc+1); // add one for benchmark

       data2.addColumn('string', 'Region');
       for (var j = 1; j < newcc; j++) {
          c1 = data.getColumnLabel(j+1);
          if (tsettings.columnFormat == "year") {
            c1 = c1.substring(0,4);
          } else if (tsettings.columnFormat == "month") {
            c1 = months[parseInt(c1)-1];
          }
          data2.addColumn('number', c1);
       }

       for (var i = 0; i < rc+1; i++) {
         region = data.getValue(i, 0);
         if (region.indexOf(this.benchmarkRegion) != -1)
            pghrow = i;
         data2.setValue(i, 0, region);
         for (var j = 1; j < newcc; j++) {
           t1 = data.getValue(i, j);
           t2 = data.getValue(i, j+1);
           if (t1 != null && t2 != null && t1 != 0) {
             ac = (t2-t1);
             pc = ac / t1 * 100;
             data2.setValue(i, j, pc);
             data2.setFormattedValue(i, j, pc.toFixed(1) + "%");
           }
         }
       }

       if (tsettings.showBar == true) {
         formatter = new google.visualization.TableBarFormat({width:40,showValue:false});
       } else {
         formatter = new google.visualization.NumberFormat(
           {fractionDigits:1, suffix: '%', negativeColor: 'firebrick', negativeParens: false}
         );
       }

       for (var j = 1; j < newcc; j++) {
         formatter.format(data2, j);
       }
       $("#"+target1).empty();
       var t = new google.visualization.Table(document.getElementById(target1));
       t.draw(data2, {allowHtml: true, showRowNumber: false});

       if (target2 != null) {

       $("#"+target2).empty();
       //jQuery('<span>').attr("id","cmsg").appendTo("#table2_div").text("Click on a region to see chart of values");

       var data3 = new google.visualization.DataTable();
       data3.addRows(newcc-1);

       // default to comparing to added benchmark row
       comprow = rc;

       data3.addColumn('string', 'Period');
       data3.addColumn('number', data2.getValue(pghrow, 0));
       data3.addColumn('number', data2.getValue(comprow, 0));

       var vstitle = data2.getValue(pghrow, 0) + " vs. " + data2.getValue(comprow, 0);
       var title = makeHtmlTitle(csettings, mid, vstitle);
       $("#chart_title").html(title);

       for (var j = 1; j < newcc; j++) {
         data3.setValue(j-1, 0, data2.getColumnLabel(j));
         data3.setValue(j-1, 1, data2.getValue(pghrow, j));
         data3.setValue(j-1, 2, data2.getValue(comprow, j));
       }

       var c = new google.visualization.LineChart(document.getElementById(target2));
       c.draw(data3, {colors:['#cb2027','#686868'],backgroundColor:'#ebebeb',legendBackgroundColor:'#ebebeb',axisFontSize:12,legendFontSize:12,titleFontSize:12,width:csettings.width,height:csettings.height,is3D:false,reverseAxis:false,legend:'bottom'});

       google.visualization.events.addListener(t, 'select', 
         function () {
            //$("#"+target2+ " #cmsg").empty();
            comprow = t.getSelection()[0].row;

            vstitle = data2.getValue(pghrow, 0) + " vs. " + data2.getValue(comprow, 0);
            title = makeHtmlTitle(csettings, mid, vstitle);
            $("#chart_title").html(title);

            data3.setColumnLabel(2,data2.getValue(comprow, 0));
            for (var j = 1; j < newcc; j++) {
              data3.setValue(j-1, 0, data2.getColumnLabel(j));
              data3.setValue(j-1, 1, data2.getValue(pghrow, j));
              data3.setValue(j-1, 2, data2.getValue(comprow, j));
            }
            c.draw(data3, {colors:['#cb2027','#686868'],backgroundColor:'#ebebeb',legendBackgroundColor:'#ebebeb',axisFontSize:12,legendFontSize:12,titleFontSize:12,width:csettings.width,height:csettings.height,is3D:false,reverseAxis:false,legend:'bottom'});

         }
       );

       } // if (target2)

    },

    // ---------------------------------------------------------------
    showStandardTable : function(dataname, target, tsettings) {
       var indata = this.dataTables[dataname];
       var rc = indata.getNumberOfRows();
       if (rc == 0) {
           $("#"+target).empty();
           return;
       }

       var numfmt = indata.getColumnPattern(1);

       var data = singleRecentColumn(indata,tsettings);

       if (this.viewSettings.calcAvg) {
         addBenchmarkRow(data,numfmt);
       }

       var rc = data.getNumberOfRows();

       if (tsettings.showBar == true) {
         data.addColumn('number', '');
       }

       if (tsettings.showBar == true) {
         data.addColumn('number', '');
         for (var i = 0; i < rc; i++) {
            data.setValue(i, 2, data.getValue(i, 1));
         }
         var formatter = new google.visualization.TableBarFormat({width:120,showValue:false});
         formatter.format(data, 2);
       }

       var t = new google.visualization.Table(document.getElementById(target));
       t.draw(data, {sortColumn:1, sortAscending:false, allowHtml: true, showRowNumber: false});

    },

    // ---------------------------------------------------------------
    showMonthYearLineChart : function(dataname, charttarget, tabletarget, csettings, tsettings) {
       var data = this.dataTables[dataname];

       var rc = data.getNumberOfRows();
       var cc = data.getNumberOfColumns();

       var data2 = new google.visualization.DataTable();

       var seriescolors = new Array();

       data2.addColumn('string', 'Month');
       for (var j = 1; j < cc; j++) {
         data2.addColumn('number', data.getColumnLabel(j).substring(0,4));
       }

       data2.addRows(rc);

       for (var i = 0; i < rc; i++) {
         data2.setValue(i, 0, months[i]);
         for (var j = 1; j < cc; j++) {
           data2.setValue(i, j, data.getValue(i, j));
         }
       }

       var data3 = new google.visualization.DataTable();
       data3.addColumn('string', 'Year');
       data3.addColumn('number', 'Total Traffic');
       data3.addRows(cc-1);

       var s;
       for (var j = 1; j < cc; j++) {
         data3.setValue(j-1, 0, data.getColumnLabel(j).substring(0,4));
         s = 0;
         for (var i = 0; i < rc; i++) {
           s += data.getValue(i, j);
         }
         data3.setValue(j-1, 1, s);
       }

       $("#"+charttarget).empty();
       var c = new google.visualization.LineChart(document.getElementById(charttarget));
       c.draw(data2, {colors:seriescolors, axisFontSize:12, legendFontSize:12, titleFontSize:12, width:csettings.width, height:csettings.height, title:csettings.title, is3D: false, reverseAxis: false, legend:'bottom'});
       $("#"+tabletarget).empty();

       var t = new google.visualization.Table(document.getElementById(tabletarget));
       t.draw(data3, {sortAscending:true, allowHtml: true, showRowNumber: false});


    },

    // ---------------------------------------------------------------
    showYearMonthColumnChart : function(dataname, target, csettings) {

       var data1 = this.dataTables[dataname];

       var rc = data1.getNumberOfRows();
       var cc = data1.getNumberOfColumns();

       var data3 = new google.visualization.DataTable();
       var seriescolors = new Array();

       data3.addColumn('string', 'Year');
       for (var j = 1; j < cc; j++) {
         data3.addColumn('number', months[j]);
         seriescolors[j-1] = '#336798';
       }

       data3.addRows(rc);

       for (var i = 0; i < rc; i++) {
         data3.setValue(i, 0, data1.getValue(i, 0).toString());
         for (var j = 1; j < cc; j++) {
           data3.setValue(i, j, data1.getValue(i, j));
         }
       }

       $("#"+target).empty();
       var c = new google.visualization.ColumnChart(document.getElementById(target));
       c.draw(data3, {colors:seriescolors, axisFontSize:12, titleFontSize:12, width:csettings.width, height:csettings.height, title:csettings.title, is3D: false, reverseAxis: false, titleX:'yyyy-mm', legend:'none'});

    },

    // ---------------------------------------------------------------
    showPackedColumnChart : function(dataname, target, csettings) {

       var data1 = this.dataTables[dataname];
       var rc = data1.getNumberOfRows();
       var cc = data1.getNumberOfColumns();

       var data2 = new google.visualization.DataTable();
       data2.addColumn('string', 'Year');

       for (var j = 1; j < cc; j++) {
         data2.addColumn('number', data1.getColumnLabel(j));
       }
       data2.addRows(rc);
       for (var i = 0; i < rc; i++) {
         data2.setValue(i, 0, data1.getValue(i, 0).toString());
         for (var j = 1; j < cc; j++) {
           data2.setValue(i, j, data1.getValue(i, j));
         }
       }


       $("#"+target).empty();
       var c = new google.visualization.ColumnChart(document.getElementById(target));
       c.draw(data2, {axisFontSize:12, legendFontSize:12, titleFontSize:12, width:csettings.width, height:csettings.height, title:csettings.title, is3D: false, reverseAxis: false, legend:'right'});

    },

    // ---------------------------------------------------------------
    showPghVsBenchChart : function(dataname, charttarget, tabletarget, csettings, tsettings) {

       var data = this.dataTables[dataname];
       var numfmt = data.getColumnPattern(1);

       var rc = data.getNumberOfRows();
       var cc = data.getNumberOfColumns();
       var s = 0; // non pgh sum
       var p = 0; // pgh value
       var ac = 0; // actual regions in avg
       var dv;
       var l;

       data2 = new google.visualization.DataTable();
       data2.addColumn('string', 'Year');
       data2.addColumn('number', this.benchmarkRegion);
       if (this.viewSettings.calcAvg) {
         data2.addColumn('number', 'Benchmark avg');
       }

       data2.addRows(rc);

       for (var i = 0; i < rc; i++) {
         data2.setValue(i, 0, data.getValue(i, 0).toString());
         s = 0;
         ac = 0;
         dv = 0;

         for (var j = 1; j < cc; j++) {
           l = data.getColumnLabel(j);
           dv = data.getValue(i, j);
           if (dv != 0) {
             if (l.indexOf(this.benchmarkRegion) == -1) {
               s += dv;
               ac++;
             } else {
               p = dv;
             }
           }
         }

         data2.setValue(i, 1, p);
         data2.setFormattedValue(i, 1, p.numberFormat(numfmt));
         if (this.viewSettings.calcAvg) {
           dv = s/ac;
           data2.setValue(i, 2, dv);
           data2.setFormattedValue(i, 2, dv.numberFormat(numfmt));
         }
       }

       var rc = data.getNumberOfRows();

       var chdsval = csettings.range;

       // build labels string
       var chxlval = "0:";
       for (var i = 0; i < rc; i++) {
         chxlval += "|" + data2.getValue(i, 0);
       }
       chxlval += "|1:" + csettings.labels;

       var seriescolors = new Array();
       var legendpos = "none";
       seriescolors[0] = csettings.colors[1];
       if (this.viewSettings.calcAvg) {
         seriescolors[1] = csettings.colors[2];
         legendpos = "bottom";
       }

       $("#"+charttarget).empty();
//       var c = new google.visualization.LineChart(document.getElementById(charttarget));
//       var c = new google.visualization.ImageLineChart(document.getElementById(charttarget));
       var c = new google.visualization.ImageChart(document.getElementById(charttarget));
//       c.draw(data2, {colors:seriescolors, axisFontSize:12, legendFontSize:12, titleFontSize:12, width:csettings.width, height:csettings.height, title:csettings.title, is3D: false, reverseAxis: false, legend:legendpos});
//       c.draw(data2, {colors:seriescolors, width:csettings.width, height:csettings.height, title:csettings.title, legend:legendpos});
       c.draw(data2, {cht:'lc', chds: chdsval, chxl: chxlval, colors:seriescolors, width:csettings.width, height:csettings.height, title:csettings.title, legend:legendpos});
       $("#"+tabletarget).empty();

       var t = new google.visualization.Table(document.getElementById(tabletarget));
       t.draw(data2, {sortAscending:true, allowHtml: true, showRowNumber: false});


    },

    // ---------------------------------------------------------------
    showStandardBarChart : function(dataname, target, csettings) {
       var indata = this.dataTables[dataname];
       var data = singleRecentColumn(indata);
       var numfmt = indata.getColumnPattern(1);

       if (this.viewSettings.calcAvg) {
         addBenchmarkRow(data,numfmt);
       }

       var data2 = new google.visualization.DataTable();
       data2.addColumn('string', 'Region');
       data2.addColumn('number', 'bench');
       data2.addColumn('number', 'pgh');
       data2.addColumn('number', 'avg');


       // sort and split region/pgh/bench into 3 columns for coloring bars

       var ria = data.getSortedRows([{column: 1}]);
       var rc = ria.length;

       data2.addRows(data.getNumberOfRows());

       var dv;
       var dv2;
       data.addColumn('number', 'Value');
       data.addColumn('number', 'Value');
       data.addColumn('number', 'Value');
       for (var i = 0; i < rc; i++) {
         dv = data.getValue(ria[i], 0);
         dv2 = data.getValue(ria[i], 1);

         data2.setValue(i, 0, dv);

         if (dv.substring(0,5) == "Bench") {
           data2.setValue(i, 1, 0);
           data2.setValue(i, 2, 0);
           data2.setValue(i, 3, dv2);
         } else if (dv.indexOf(this.benchmarkRegion) != -1) {
           data2.setValue(i, 1, 0);
           data2.setValue(i, 2, dv2);
           data2.setValue(i, 3, 0);
         } else {
           data2.setValue(i, 1, dv2);
           data2.setValue(i, 2, 0);
           data2.setValue(i, 3, 0);
         }

       }


       $("#"+target).empty();

       var c = new google.visualization.BarChart(document.getElementById(target));

       c.draw(data2, {width:csettings.width, height:csettings.height, title: csettings.title, isStacked:true,legend:'none', colors:csettings.colors, axisFontSize:12, titleFontSize:12, reverseAxis:false});

    },

    // ---------------------------------------------------------------
    showStandardChart : function(dataname, target, csettings, mid) {

       var indata = this.dataTables[dataname];
       var rc = indata.getNumberOfRows();
       if (rc == 0) {
           $("#"+target).empty();
           return;
       }

       var data = singleRecentColumn(indata);
       var numfmt = indata.getColumnPattern(1);

       if (this.viewSettings.calcAvg) {
         addBenchmarkRow(data,numfmt);
       }

       // add column for colors 
       data.addColumn('number', 'Color');

       // bar colors
       var rc = data.getNumberOfRows();
       var s = 0;
       var dv;
       for (var i = 0; i < rc; i++) {
         dv = data.getValue(i, 0);
         if (dv.indexOf(this.benchmarkRegion) != -1) {
           data.setValue(i, 2, 1);
         } else if (dv.substring(0,5) == "Bench") {
           data.setValue(i, 2, 2);
         } else {
           data.setValue(i, 2, 0);
         }
       }

       var colors = csettings.colors;

       // get sorted 
       var ria = data.getSortedRows([{column: 1}]);
       var rc = ria.length;

       // build labels string
       var chxl = "1:";
       for (var i = 0; i < rc; i++) {
         chxl += "|" + data.getValue(ria[i], 0);
       }

       // build values and colors strings
       var chd = "t:";
       var chco = "";
       var v;
       for (var i = rc-1; i >= 0; i--) {
         // value
         v = data.getValue(ria[i], 1);
         if (v != null)
           chd += v.toFixed(3);
         else
           chd += "0";
         // color
         chco += colors[data.getValue(ria[i], 2)];
         if (i > 0) {
           chd += ",";
           chco += "|";
         }
       }

       // deal with measure specific settings

       // first try with view
       var mover = csettings.measureOverrides["m"+mid+"imagechartandtable"];
       if (typeof(mover) == "undefined")
         // then without
         mover = csettings.measureOverrides["m"+mid];

       var title = csettings.title;
       if (typeof(mover) != "undefined" && mover.length > 0 && mover[0].length > 0) { 
         title = title.replace("?",mover[0]);
       }
       if (typeof(mover) != "undefined" && mover[1].length > 0 && csettings.force != "yes") { 
         chxl += "|0:" + mover[1];
       } else if (csettings.labels.length > 0) {
         chxl += "|0:" + csettings.labels;
       }
       var range;
       if (typeof(mover) != "undefined" && mover[2].length > 0 && csettings.force != "yes") { 
         range = mover[2];
       } else {
         range = csettings.range;
       }

       var url = "http://chart.apis.google.com/chart";
       url += "?cht=bhg";
       url += "&chs=" + csettings.width +"x"+csettings.height;
       url += "&chds=" + range;
       url += "&chd=" + chd;
       url += "&chxt=" + "x,y";
       url += "&chxr=" + "0,"+range;
       url += "&chtt=" + encodeURIComponent(title);
       url += "&chxl=" + encodeURIComponent(chxl);
       url += "&chco=" + chco;
       url += "&chbh=" + csettings.barsize;

       var imgchart = document.getElementById(target).getElementsByTagName("IMG")[0];

       imgchart.setAttribute("src", url);
       imgchart.setAttribute("title", csettings.title);


       //jQuery('<img>').attr("src",url).appendTo("#chart_div");

    },

    // ---------------------------------------------------------------
    showChange : function(dataname, charttarget, tabletarget, csettings, tsettings, type, mid) {
       var data = this.dataTables[dataname];
       var numfmt = data.getColumnPattern(1);

       if (this.viewSettings.calcAvg) {
         addBenchmarkRow2(data);
       }

       // add table for absolute change and relative change
       // this way we have option to sort both charts the same
       var data2 = new google.visualization.DataTable();
       data2.addColumn('string', 'Region');

       // basically hard-code to assume is year for now
       data2.addColumn('number', data.getColumnLabel(1).substring(0,4));
       data2.addColumn('number', data.getColumnLabel(2).substring(0,4));

       data2.addColumn('number', 'Change');
       data2.addColumn('number', '%Change');

       // color column
       data2.addColumn('number', 'Color');

       data2.addRows(data.getNumberOfRows());

       // do the change calc
       var rc = data2.getNumberOfRows();

       var t1, t2, ac, pc;
       var ri;
       var city;

       for (var i = 0; i < rc; i++) {

         city = data.getValue(i, 0);
         data2.setValue(i, 0, city);
         t1 = data.getValue(i, 1);
         t2 = data.getValue(i, 2);

         data2.setValue(i, 1, t1);
         if (t1 != null)
           data2.setFormattedValue(i, 1, t1.numberFormat(numfmt));
         data2.setValue(i, 2, t2);
         if (t2 != null)
           data2.setFormattedValue(i, 2, t2.numberFormat(numfmt));

         if (t1 != null && t2 != null) {

           ac = (t2-t1);
           data2.setValue(i, 3, ac);
           data2.setFormattedValue(i, 3, ac.numberFormat(numfmt));

           if (t1 != 0) {
           pc = ac / t1 * 100;
           data2.setValue(i, 4, pc);
           data2.setFormattedValue(i, 4, pc.toFixed(2) + "%");
           }

         } // if (t1 && t2)

         if (city.indexOf(this.benchmarkRegion) != -1) {
           data2.setValue(i, 5, 1);
         } else if (city == "Benchmark avg") {
           data2.setValue(i, 5, 2);
         } else {
           data2.setValue(i, 5, 0);
         }

       }

       // deal with measure specific settings
       // first try with view
       var view = "";
       switch (type) {
         case "pct":
           view = "percentchange";
           break;
         case "abs":
           view = "absolutechange";
           break;
         case "both":
           view = "absoluteandpercentchange";
           break;
         case "vchartptable":
           view = "valuechartpercenttable";
           break;
         case "vchartatable":
           view = "valuechartabsolutetable";
           break;
       }
       var mover = csettings.measureOverrides["m"+mid+view];
       if (typeof(mover) == "undefined")
         // then without
         mover = csettings.measureOverrides["m"+mid];

       var title = csettings.title;
       if (typeof(mover) != "undefined" && mover.length > 0 && mover[0].length > 0) { 
         title = title.replace("?",mover[0]);
       }

       if (type == "vchartptable" || type == "vchartatable") {

       // draw chart of last periods values

       var ria = data.getSortedRows([{column: 2}]);
       var rc = ria.length;

       var chxl = "1:";
       for (var i = rc-1; i >= 0; i--) {
         chxl += "|" + data.getValue(ria[i], 0);
       }

       if (typeof(mover) != "undefined" && mover[1].length > 0 && csettings.force != "yes") { 
         chxl += "|0:" + mover[1];
       } else if (csettings.labels.length > 0) {
         chxl += "|0:" + csettings.labels;
       }

       var range;
       if (typeof(mover) != "undefined" && mover[2].length > 0 && csettings.force != "yes") { 
         range = mover[2];
       } else {
         range = csettings.range;
       }

       var chd = "t:";
       var chco = "";
       var v;
       for (var i = 0; i < rc; i++) {
         v = data.getValue(ria[i], 2)
         if (v != null)
           chd += v.toFixed(3);
         else
           chd += "0";
         chco += csettings.colors[data2.getValue(ria[i], 5)];
         if (i < rc-1) {
           chd += ",";
           chco += "|";
         }
       }

       } else { // is "pct", "abs", or "both"

       // draw the relative change chart

       var ria;
       if (type != "pct")
         ria = data2.getSortedRows([{column: 3, desc: true}]);
       else
         ria = data2.getSortedRows([{column: 4, desc: true}]);

       rc = ria.length;

       var chxl = "1:";
       for (var i = rc-1; i >= 0; i--) {
         chxl += "|" + data2.getValue(ria[i], 0);
       }

       if (typeof(mover) != "undefined" && mover[1].length > 0 && csettings.force != "yes") { 
         chxl += "|0:" + mover[1];
       } else if (csettings.labels.length > 0) {
         chxl += "|0:" + csettings.labels;
       }

       var range;
       if (typeof(mover) != "undefined" && mover[2].length > 0 && csettings.force != "yes") { 
         range = mover[2];
       } else {
         range = csettings.range;
       }

       var chd = "t:";
       var chco = "";
       var v;
       for (var i = 0; i < rc; i++) {
         if (type != "pct")
           v = data2.getValue(ria[i], 3)
         else
           v = data2.getValue(ria[i], 4);
         if (v != null)
           chd += v.toFixed(3);
         else
           chd += "0";
         chco += csettings.colors[data2.getValue(ria[i], 5)];
         if (i < rc-1) {
           chd += ",";
           chco += "|";
         }
       }

       } //if (type == "vchartptable")

       url = "http://chart.apis.google.com/chart";
       url += "?cht=bhg";
       url += "&chs=" + csettings.width +"x"+csettings.height;
       url += "&chds=" + range;
       url += "&chd=" + chd;
       url += "&chxt=" + "x,y"
       url += "&chxr=" + "0,"+range;
       url += "&chtt=" + encodeURIComponent(title);
       url += "&chxl=" + encodeURIComponent(chxl);
       url += "&chco=" + chco;
       url += "&chbh=" + csettings.barsize;

       var imgchart = document.getElementById(charttarget).getElementsByTagName("IMG")[0];

       imgchart.setAttribute("src", url);
       imgchart.setAttribute("title", csettings.title);
 
       // remove color column
       data2.removeColumn(5);

       if (type == "abs" || type == "vchartatable")
         data2.removeColumn(4);
       else if (type == "pct" || type == "vchartptable")
         data2.removeColumn(3);

/*
       var formatter = new google.visualization.NumberFormat(
             {fractionDigits:0, negativeColor: 'red', negativeParens: false});
       formatter.format(data2, 1);
       formatter.format(data2, 2);
       formatter.format(data2, 3);
*/

       var formatter = new google.visualization.ColorFormat();
       formatter.addRange(null, 0, 'firebrick');
       formatter.addRange(0, null, 'black');
       formatter.format(data2, 3);

       if (type == "pct" || type == "both") {
         formatter = new google.visualization.NumberFormat(
             {suffix: '%', negativeColor: 'firebrick', negativeParens: false});
         formatter.format(data2, (type=="pct"?3:4));
       }

       var sc = (type == "vchartptable" || type == "vchartatable") ? 2 : 3;

       var t = new google.visualization.Table(document.getElementById(tabletarget));
       t.draw(data2, {sortColumn:sc, sortAscending:false, allowHtml: true, showRowNumber: false});

    }

  };
})();
