
// debug to firefox and chrome without erroring IE
function dlog( pMsg ) {
  if( typeof console != "undefined" && typeof console.log != "undefined" ) {
    console.log( pMsg );
  }
}

// format various data for display (commas, datetimes, time in seconds -> time in h/m/s format)
function ssFormatValue( pKey, pValue ) {
  var ret;
  switch( pKey ) {
    case 'total_time':
    case 'best_time':
      ret = ssFormatTime( pValue );
      break;
    case 'datetime':
      var d = new Date();
      d.setTime( pValue );
      m = d.getMonth() + 1;
      day = d.getDate();
      y = d.getFullYear();
      ret = m+"/"+day+"/"+y;
      break;
    case 'complete_ratio':
      ret = Math.round( pValue ) + "%";
      break;
    case 'name':
      ret = pValue;
      break;
    default:
      ret = ssAddCommas( Math.round( 100 * pValue ) / 100 );
      break;
  };

  return ret;
}

// add commas to a number
function ssAddCommas(pStr)
{
	pStr += '';
	x = pStr.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;
}


// given seconds, create a Xh Xm Xs format
function ssFormatTime( pSeconds, pShowSeconds ) {


  var h = Math.floor( pSeconds / 60 / 60 );
  pSeconds -= h * 60 * 60;
  var m = Math.floor( pSeconds / 60 );
  var s = pSeconds % 60;

  if( "undefined" == typeof pShowSeconds ) {
    // default behavior: only show seconds if there are hours
    if( h > 0 ) {
      pShowSeconds = false;
    } else {
      pShowSeconds = true;
    }
  }

  var ret = "";

  if( h > 0 ) {
    ret += h + "h ";
  }
  if( m > 0 ) {
    ret += m + "m";
  }
  if( pShowSeconds ) {
    ret += " " + s + "s";
  }

  return ret;
}

// get a stat from the skirmish log data
function ssGetLogStat( pRun, pStat ) {
  var stat = null;
  switch( pStat ) {
    case 'smph':
      stat = 60 * 60 * pRun[ 'sm' ] / pRun[ 'total_time' ];
      break;
    default:
      stat = pRun[ pStat ];
      break;
  };
  return stat;
}

// defines how to handle roll up of most stats.
// best time is a min() function, all the rest are additive
var ssRollUpStat = function( pStat, pOldValue, pNewValue ) {
  if( null == pOldValue ) {
    result = pNewValue;
  } else {
    switch( pStat ) {
      case 'best_time':
        result = (pNewValue < pOldValue) ? pNewValue : pOldValue;
        break;
      default:
        result = pOldValue + pNewValue;
        break
    };
  }
  return result;
};

// gets the display for the stats panel for any stat.
// iterates through all relevant overall stats data and performs
// whatever it needs to do to get the display value (additions, running averages,
// mins, etc)
function ssGetStatTotal( pStat, pSkirmish, pSize ) {
  if( undefined == pSkirmish ) {
    pSkirmish = 0;
  }
  if( undefined == pSize ) {
    pSize = 0;
  }

  result = null;
  count = 0;
  total_sm = 0;
  total_time = 0;
  attempts = 0;
  complete = 0;

  jQuery.each( overall_stats, function( skirmish, skirmish_stats ) {
    if( 0 == pSkirmish || skirmish == pSkirmish ) {
      jQuery.each( skirmish_stats, function( size, stats ) {
        if( 0 == pSize || size == pSize ) {
          switch( pStat ) {
            case 'smph':
              total_sm += stats[ 'sm' ];
              total_time += stats[ 'total_time' ];
              result = Math.round( 100 * 60 * 60 * total_sm / total_time ) / 100;
              break;
            case 'complete_ratio':
              attempts += stats[ 'attempts' ];
              complete += stats[ 'complete' ];
              result = 100 * complete / attempts;
              break;
            default:
              result = ssRollUpStat( pStat, result, stats[ pStat ], count );
              break;
          };
        }
      } );
    }
  } );

  return result;
}

// simple tooltip show
function showTooltip(x, y, contents) {
  jQuery('<div class="tooltip" id="tooltip">' + contents + '</div>').css( {
    top: y + 5,
    left: x + 5
  }).appendTo("body").fadeIn(200);
}

// determine what to show on pie chart hover
var ssPieHover = function( event, pos, item ) {
  if (item) {
    if ("undefined" == typeof previousPoint || previousPoint != item.datapoint) {
      previousPoint = item.datapoint;

      jQuery("#tooltip").remove();
      //showTooltip(item.pageX, item.pageY, item.series.label + " of " + x + " = " + y);
      showTooltip(pos.pageX, pos.pageY,
        '<div><span></span>'+item.series.label+'</div>'
        + '<div><span></span>'+Math.round(item.series.percent)+'% of '+jQuery('#stat option:selected').text()+'</div>'
      );
    }
  }
  else {
    jQuery("#tooltip").remove();
    previousPoint = null;            
  }
};

// determine what to show on bar chart hover.
// given the chart item selected, finds the relevant skirmish data and format a tooltip
var ssBarHover = function (event, pos, item) {
  if (item) {
    if ("undefined" == typeof previousPoint || previousPoint != item.datapoint) {
      previousPoint = item.datapoint;
      jQuery("#tooltip").remove();
      var x = item.datapoint[0].toFixed(2),
          y = item.datapoint[1].toFixed(2);
                
      //showTooltip(item.pageX, item.pageY, item.series.label + " of " + x + " = " + y);
      var xInt = parseInt( x );
      srun = gCurrentLog[ xInt ];
      if( undefined != srun ) {
        //showTooltip(item.pageX, item.pageY,             // anchor to top of bar
        //showTooltip(800,800,                            // anchor to static location
        showTooltip(pos.pageX, pos.pageY,                       // anchor to cursor
          '<div><span></span><strong>'+skirmish_names[ srun.skid ]+'</strong></div>'
        + '<div><span>'+ssFormatValue( 'datetime', srun.datetime )+'</span>Date:</div>'
        + '<div><span>'+ssFormatValue( 'ssize', srun.ssize )+'</span>Size:</div>'
        + '<div><span>'+ssFormatValue( 'difficulty', srun.difficulty )+'</span>Tier:</div>'
        + '<div><span>'+ssFormatValue( 'sm', srun.sm )+'</span>Marks:</div>'
        + '<div><span>'+ssFormatValue( 'kills', srun.kills )+'</span>Kills:</div>'
        + '<div><span>'+ssFormatValue( 'total_time', srun.total_time )+'</span>Duration:</div>'
        );
      }
    }
  }
  else {
    jQuery("#tooltip").remove();
    previousPoint = null;            
  }
};

var ssSetTipTable = function( pData, pAutoFormat ) {
  if( "undefined" == typeof pAutoFormat ) {
    pAutoFormat = true;
  }
  var keys = ['name','ssize','sm','smph','datetime','difficulty','kills','total_time'];
  for( i = 0; i < keys.length; i++ ) {
    if( pData[ keys[ i ] ] ) {
      if( pAutoFormat ) {
        value = ssFormatValue( keys[ i ], pData[ keys[ i ] ] );
      } else {
        value = pData[ keys[ i ] ];
      }
    } else {
      value = '';
    }
    jQuery("#tip_"+keys[ i ]).html( value );
  }
};

var ssBarStaticHover = function (event, pos, item) {

  if( 'day' == gBarMode ) {
    // determine the data index that the mouse is over.
    // find the difference between the chart X and the min X, divide by the step amount
    barData = cBar.getData()[ 0 ];
    idx = Math.floor( (pos.x - barData.xaxis.datamin) / (1000 * 60 * 60 * 24 * gNumDaysGroup ) );
    maxIdx = barData.data.length;
  } else {
    var idx = Math.floor( pos.x );
    var maxIdx = gCurrentLog.count;
  }

  // get the position inside the actual plot area so we don't update the tooltip for
  // bars off the left side in the label area.
  inChartX = pos.pageX - cBar.offset().left;

  if (inChartX > 0 && (typeof(previousIdx) == "undefined" || previousIdx != idx)) {
    if( idx >= 0 && idx < maxIdx ) {
      if(typeof(previousIdx) != "undefined") {
        cBar.unhighlight( 0, previousIdx );
      }
      
      // just in case, remove any tooltip from the pie chart since it might itnerfere with the display
      jQuery("#tooltip").remove();

      previousIdx = idx;

      // highlight the bar
      cBar.highlight( 0, idx, "#fc0" );

      if( 'day' == gBarMode ) {
        dayData = gCurrentLog[ idx ];

        if( dayData ) {
          ssSetTipTable( {
            sm:         ssFormatValue( 'sm', dayData.sm ),
            name:       ssFormatValue( 'datetime', dayData.datetime ),
            datetime:   ssFormatValue( 'sm', dayData.runs ) + " run" + (dayData.runs == 1 ? "" : "s"),           // format value like skirmish marks (ie add commas)
            smph:       ssFormatValue( 'smph', dayData.smph ),
            kills:      ssFormatValue( 'kills', dayData.kills ),
            total_time: ssFormatValue( 'total_time', dayData.total_time ),
            ssize:      "n/a",
            difficulty: "n/a"
          }, false );
        } else {
          // determine timestamp from chart x value
          datetime = ssRoundTimestampToDay( pos.x, gNumDaysGroup );
          ssSetTipTable( {
            name:       ssFormatValue( 'datetime', datetime ),
            datetime:   "None"           // format value like skirmish marks (ie add commas)
          },
          false);
        }
      } else {
        //showTooltip(item.pageX, item.pageY, item.series.label + " of " + x + " = " + y);
        srun = gCurrentLog[ idx ];

        // display the specific information about this skirmish
        ssSetTipTable( {
          name: skirmish_names[ srun.skid ],
          ssize: srun.ssize,
          sm: srun.sm,
          smph: 60 * 60 * srun.sm / srun.total_time,
          datetime: srun.datetime,
          difficulty: srun.difficulty,
          kills: srun.kills,
          total_time: srun.total_time
        } );
      }
    }
  }
};




function ssArraySum( pArray ) {
  var sum = 0;
  for( var i = 0; i < pArray.length; i++ ) {
    sum += pArray[ i ];
  }
  return sum;
}

function ssArrayAverage( pArray ) {
  avg = ssArraySum( pArray ) / pArray.length;
  return avg;
}

/////////////////// GET DATA ///////////////////////////////

function ssGetLogDataByRun( pSize, pSkirmish, pStat ) {
  var data = [];
  var avgData = [];
  var avgSet = [];

  // null out the global reference to bar chart X axis => run info
  gCurrentLog = {}

  var i = 0;
  jQuery.each( log_stats, function( skirmish_run, skirmish_run ) {
    if( undefined == pSize || 0 == pSize || skirmish_run[ 'ssize' ] == pSize ) {
      if( undefined == pSkirmish || 0 == pSkirmish || pSkirmish == skirmish_run[ 'skid' ] ) {


        logStat = ssGetLogStat( skirmish_run, pStat );

        // push stat onto normal chart
        data.push( [ i, logStat ] );

        // push current value onto moving average set
        avgSet.push( logStat );
        if( avgSet.length > gMovingAverageLength ) {
          avgSet.shift();
        }

        // 0.375 is half of 0.75 which is the width of the bars
        avgData.push( [ i + 0.375, ssArrayAverage( avgSet ) ] );

        // add current run to global current log array
        gCurrentLog[ i ] = skirmish_run;

        i++;
      }
    }
  });

  gCurrentLog.count = i;

  if( undefined == pSkirmish || 0 == pSkirmish ) {
    skirmish_label = "All Skirmishes";
  } else {
    skirmish_label = skirmish_names[ pSkirmish ];
  }

  if( undefined == pSize || 0 == pSize ) {
    size_label = 'All Sizes';
  } else {
    size_label = size_names[ pSize ];
  }

  var stat_name = jQuery("#stat option:selected").text();

  var dataset = [
    {
      data: data,
      label: stat_name+" - "+skirmish_label+" - "+size_label,
      bars:  {
        show: true,
        barWidth: 0.75,
        lineWidth: 1,
        fill: 0.5
      },
      color: gThemeColors[ gTheme ].bar
    },
    {
      data: avgData,
      label: "Moving "+gMovingAverageLength+"-Run Average",
      lines: {
        show: true
      },
      color: gThemeColors[ gTheme ].avgLine
    }
  ];

  return dataset;
}

function ssRoundTimestampToDay( pTimestamp, pNumDays ) {
  if( !pNumDays ) {
    pNumDays = 1;
  }
  millisecondsPerDay = 1000 * 60 * 60 * 24 * pNumDays;
  return Number( millisecondsPerDay * Math.floor( pTimestamp / millisecondsPerDay ) );
}

function ssGetLogDataByDay( pSize, pSkirmish, pStat ) {
  var data = [];
  var dateSummary = {};

  // null out the global reference to bar chart X axis => run info
  // day log doesn't have a tooltip yet until i figure out what makes sense to put there
  gCurrentLog = {}

  var minTimestamp = null, maxTimestamp = null;

  var i = 0;
  jQuery.each( log_stats, function( skirmish_run, skirmish_run ) {
    if( undefined == pSize || 0 == pSize || skirmish_run[ 'ssize' ] == pSize ) {
      if( undefined == pSkirmish || 0 == pSkirmish || pSkirmish == skirmish_run[ 'skid' ] ) {

        timestamp = ssRoundTimestampToDay( skirmish_run.datetime, gNumDaysGroup );

        if( null == minTimestamp || timestamp < minTimestamp ) {
          minTimestamp = timestamp;
        }
        if( null == maxTimestamp || timestamp > maxTimestamp ) {
          maxTimestamp = timestamp;
        }
        
        // init the hash if needed
        if( !dateSummary[ timestamp ] ) {
          dateSummary[ timestamp ] = {
            datetime: timestamp,
            runs: 0
          };
        }

        statsToTrack = ['sm', 'kills', 'smph', 'total_time' ];
        var stat;
        for( var j = 0; j < statsToTrack.length; j++ ) {
          stat = statsToTrack[ j ];
          dateSummary[ timestamp ][ stat ] = ssRollUpStat( stat, dateSummary[ timestamp ][ stat ], ssGetLogStat( skirmish_run, stat ) );
        }
        dateSummary[ timestamp ][ 'runs' ]++;
      }
    }
  });

  var idx = 0;
  for( var i = minTimestamp; i <= maxTimestamp; i += 1000 * 60 * 60 * 24 * gNumDaysGroup ) {

    // regenerate skirmish marks per hour here since we have all the data
    if( dateSummary && dateSummary[ i ] ) {
      dateSummary[ i ][ 'smph' ] = 60 * 60 * dateSummary[ i ][ 'sm' ] / dateSummary[ i ][ 'total_time' ];
    }

    if( dateSummary && dateSummary[ i ] && dateSummary[ i ][ pStat ] ) {
      datum = dateSummary[ i ][ pStat ];
    } else {
      datum = 0;
    }

    data.push( [ i, datum ] );

    // build the current log for tooltip reference
    if( dateSummary && dateSummary[ i ] ) {
      gCurrentLog[ idx ] = dateSummary[ i ];
    } else {
    }
    idx++;
  }

  if( undefined == pSkirmish || 0 == pSkirmish ) {
    skirmish_label = "All Skirmishes";
  } else {
    skirmish_label = skirmish_names[ pSkirmish ];
  }

  if( undefined == pSize || 0 == pSize ) {
    size_label = 'All Sizes';
  } else {
    size_label = size_names[ pSize ];
  }

  var stat_name = jQuery("#stat option:selected").text();

  var dataset = [
    {
      bars: {
        show: true,
        barWidth: 0.75 * 1000 * 60 * 60 * 24 * gNumDaysGroup,
        lineWidth: 1,
        fill: 0.5
      },
      data: data,
      label: stat_name+" - "+skirmish_label+" - "+size_label,
      color: gThemeColors[ gTheme ].bar
    }
  ];

  return dataset;
}

function ssGetLogData( pSize, pSkirmish, pMode, pStat ) {
  var data;
  switch( pMode ) {
    case 'day':
      data = ssGetLogDataByDay( pSize, pSkirmish, pStat );
      break;
    case 'run':
    default:
      data = ssGetLogDataByRun( pSize, pSkirmish, pStat );
      break;
  }

  return data;
}

function ssGetLogOptions( pDataset, pSize, pSkirmish, pMode, pStat ) {
  if( 'day' == pMode ) {

    var length = pDataset[0].data.length - 1;
    var minIdx = (length > 50) ? length - 50 : 0;
    var max;
    if( length < 25 ) {
      // if there isn't a lot of data, set the max x-axis value 25 days in the future from the first day
      max = pDataset[0].data[ minIdx ][0] + (1000 * 60 * 60 * 24 * 25)
    } else {
      max = pDataset[0].data[ length ][0] + (1000 * 60 * 60 * 24 * gNumDaysGroup);
    }
    var ret = {
      xaxis: {
        mode: "time",
        timeformat: "%m/%d",
        min: pDataset[0].data[ minIdx ][0],
        max: max
      },
      yaxis: {
        tickFormatter: function( pVal, pAxis ) {
          return ssFormatValue( pStat, pVal );
        },
        min: 0,   
        labelWidth: 50
      },
      grid: {
        tickColor: "#333",
        hoverable: true,
        autoHighlight: false
      },
      legend: {
        container: "#skirmishbarlegend",
        noColumns: 2
      }
    };
  } else {
    var ret = {
      xaxis: {
        // if lots of bars, default to showing the last 50
        min: (pDataset[0].data.length > 100) ? (pDataset[0].data.length) - 100 : 0,
        // make sure to show no less than 25 bars
        max: (pDataset[0].data.length < 25) ? 25 : pDataset[0].data.length,
        ticks: 0
      },
      yaxis: {
        tickFormatter: function( pVal, pAxis ) {
          return ssFormatValue( pStat, pVal );
        },
        min: 0,   
        labelWidth: 50
      },
      grid: {
        tickColor: "#333",
        hoverable: true,
        autoHighlight: false
      },
      legend: {
        container: "#skirmishbarlegend",
        noColumns: 2
      }
    };
  }

  return ret;
}

function ssGetZoomOptions( pDataset, pMode ) {
  var zoom_options;
  
  if( 'day' == pMode ) {
    var max;
    if( pDataset.length < 25 ) {
      // if there isn't a lot of data, set the max x-axis value 25 days in the future from the first day
      max = pDataset[0][0] + (1000 * 60 * 60 * 24 * 25)
    } else {
      max = pDataset[ pDataset.length - 1 ][0] + (1000 * 60 * 60 * 24 * gNumDaysGroup);
    }

    zoom_options = {
      legend: {show: false},
      xaxis: {
        ticks: [],
        mode: "time",
        min: pDataset[0][0],
        max: max
      },
      yaxis: {
        ticks: [],
        min: 0,
        autoscaleMargin: 0.1,
        labelWidth: 50
      },
      selection: { mode: "x" }
    };
  } else {
    zoom_options = {
      legend: {show: false},
      xaxis: { ticks: [], mode: "time", min: 0, max: (bar_chart.data[0].data.length < 50) ? 50 : bar_chart.data[0].data.length },
      yaxis: { ticks: [], min: 0, autoscaleMargin: 0.1, labelWidth: 50 },
      selection: { mode: "x" }
    };
  }

  return zoom_options;
}

/////////////////// GET CHARTS ///////////////////////////////

// get the plot data for the bar chart based on filters
function ssGetLogChart( pSize, pSkirmish, pMode, pStat ) {

  var dataset = ssGetLogData( pSize, pSkirmish, pMode, pStat );

  var options = ssGetLogOptions( dataset, pSize, pSkirmish, pMode, pStat ); 

  var chart = { data: dataset, options: options };

  return chart;
}

// get the pie chart plot data based on filter selections
function ssGetPieChart( pSize, pSkirmish, pStat ) {
  var dataSet = [];
  var colors = [];

  var cur_slice = 0;

  var sliceColors = gThemeColors[ gTheme ].pie;

  // loop through the overall stats, get the data, push onto pie chart.
  // also set up color data here
  jQuery.each( overall_stats, function( skirmish, skirmish_stats ) {
    // only look at skirmish specific overall stats (ignore summary)
    if( 0 != skirmish ) {
      stat_total = ssGetStatTotal( pStat, skirmish, pSize );
      if( stat_total > 0 ) {
        dataSet.push( { label: skirmish_names[ skirmish ], data: stat_total } );
        r = sliceColors[ cur_slice % sliceColors.length ].r;
        g = sliceColors[ cur_slice % sliceColors.length ].g;
        b = sliceColors[ cur_slice % sliceColors.length ].b;

        if( 0 == pSkirmish ) {
          a = 0.75;
        } else {
          if( skirmish == pSkirmish ) {
            a = 0.75;
          } else {
            a = 0.1;
          }
        }
        colors.push( "rgba("+r+","+g+","+b+","+a+")" );

        cur_slice++;
      }
    }
  } );

  // this determines if the last slice and first slice will use the same color.
  // if so, change the last slice color to the 2nd slice color.
  // this doesn't really help if using 2 colors.
  if( (cur_slice - 1) % sliceColors.length == 0 ) {
    // cur_slice is 1 over the last element so leaving it be for this iwll grab the next color
    r = sliceColors[ cur_slice % sliceColors.length ].r;
    g = sliceColors[ cur_slice % sliceColors.length ].g;
    b = sliceColors[ cur_slice % sliceColors.length ].b;
    // we can just use the leftover alpha var from the above loop since it'll be correct.
    // also have to use cur_slice - 1 since colors is a zero-indexed array
    colors[ cur_slice - 1 ] = "rgba("+r+","+g+","+b+","+a+")";
  }

  var options = {
    series: {
      pie: {
        show: true,
        radius: 1,
        stroke: {color: gThemeColors[ gTheme ].pieStroke },
        label: {
          show: true,
          radius: 3/4,
          formatter: function(label, series){
              //return '<div style="font-size:7pt;text-align:center;padding:2px;color:white;">'+label+'</div>';
              return '';
          }
        }
      }
    },
    colors: colors,
    legend: {
      show: false
    },
    grid: {
      borderWidth: 0,
      hoverable: true
    }
  };
 
  var chart = { data: dataSet, options: options };

  return chart;
}

// get the stats table based on filter selections
var ssGetStatsTable = function( pSize, pSkirmish ) {
  if( undefined == pSize ) {
    pSize = 0;
  }
  if( undefined == pSkirmish ) {
    pSkirmish = 0;
  }

  var stats_to_show = {
    sm: 'Skirmish Marks',
    total_time: 'Play Time',
    complete: 'Skirmishes Completed',
    attempts: 'Skirmishes Attempted',
    complete_ratio: 'Completion Ratio',
    best_time: 'Best Time',
    smph: 'SM Per Hour',
    sm_cp: 'SM from Control Points',
    sm_def: 'SM from Defenders',
    sm_enc: 'SM from Encounters',
    kills: 'Monster Kills',
    kills_l: 'Lieutenant Kills',
    sold_l: 'Soldiers Lost',
    def_s: 'Defenders Saved',
    def_l: 'Defenders Lost',
    cp: 'Control Points Taken',
    enc_complete: 'Encounters Completed'
  };

  var t = '';
  t  = '<div class="stats_scrollsizer"><table class="stats-table">';
  jQuery.each( stats_to_show, function( key, label ) {

    value = ssGetStatTotal( key, pSkirmish, pSize );

    t += '<tr>';
    t += ' <td class="stats-left">' + label + '</td>';
    t += ' <td class="stats-right">' + ssFormatValue( key, value ) + '</td>';
    t += '</tr>';
  });
  t += '</table></div>';

  return t;
};

// run all the updates when a filter is changed
function ssUpdateScreen() {
  if( typeof overall_stats !== 'undefined' ) {
    // weird name because of weird JS issues with scope?
    lSize     = jQuery("#ssize option:selected").val();
    lSkirmish = jQuery("#ssid option:selected").val();
    lStat     = jQuery("#stat option:selected").val();
    lBarMode  = gBarMode;


    jQuery("#tooltip").remove();

    // clear our the static "tooltip" section above the bar chart
    ssSetTipTable( {} );

    try {
      pie_chart = ssGetPieChart( lSize, lSkirmish, lStat );
      bar_chart = ssGetLogChart( lSize, lSkirmish, lBarMode, lStat );

      var setZoomSelection = false;

      if( 'day' == lBarMode ) {
        if( null == gZoomOptions ) {
          // get the full chart to determine true min and max values
          full_chart = ssGetLogChart( 0, 0, lBarMode, lStat );

          gZoomOptions = ssGetZoomOptions( full_chart.data[0].data, lBarMode );
          zoomFrom = full_chart.options.xaxis.min;
          zoomTo   = full_chart.options.xaxis.max;

          // set a local flag to set the zoom selection once the chart has been drawn.
          // this should only happen when changing the bar chart grouping.
          setZoomSelection = true;
        } else {
          // do nothing, keep the same zoom options
        }
      } else {
        // for run mode, always get zoom options on every change
        gZoomOptions = ssGetZoomOptions( bar_chart.data[0].data, lBarMode );
        zoomFrom = bar_chart.options.xaxis.min;
        zoomTo   = bar_chart.options.xaxis.max;
        setZoomSelection = true;
      }

      zoomRanges = { xaxis: { from: zoomFrom, to: zoomTo } };

      // render bar chart
      cBar = jQuery.plot(jQuery("#skirmishbar"), bar_chart.data, bar_chart.options );
      cZoom = jQuery.plot(jQuery("#skirmishbarzoom"), bar_chart.data, gZoomOptions );

      if( setZoomSelection ) {
        // set the default selected area on zoom chart
        cZoom.setSelection( zoomRanges );
      }

      if( 'day' == gBarMode ) {
        cZoom.setSelection( gBarRanges );
        cBar.setSelection( gBarRanges );
      }
      
      // render pie
      dlog( 'bar chart render time' );
      jQuery("#pie-title-size").text(jQuery("#ssize option:selected").text());
      jQuery("#pie-title-stat").text(jQuery("#stat option:selected").text());
      cPie = jQuery.plot(jQuery("#skirmishpie"), pie_chart.data, pie_chart.options );
    } catch ( err ) {
      // ignore exception, just keep chugging along
      dlog( err );
      // TODO: handle widget movement from narrow column to wide column, complains about xaxis off a null
    }


    // render stats panel
    jQuery("#skirmishstats").html(ssGetStatsTable( lSize, lSkirmish ));

    // make stats widget scrollable
    jQuery(".stats_scrollsizer").jScrollPane( {showArrows:true, animateTo:true, scrollbarWidth:15, scrollbarMargin:0} );
  }
}

function ssInitScreen ( ) {
  // regsiter on change events
  if( typeof overall_stats !== 'undefined' ) {
    jQuery("#ssize").change( function() { ssUpdateScreen() } );
    jQuery("#ssid").change( function() { ssUpdateScreen() } );
    jQuery("#stat").change( function() { ssUpdateScreen() } );


    // change bar chart type and refresh screen
    jQuery("#bar_by_run").click( function() {
      gBarMode = 'run';
      // clear the zoom options so we re-determine them
      gZoomOptions = null;
      ssUpdateScreen();
    });
    jQuery("#bar_by_day").click( function() {
      gBarMode = 'day';
      gZoomOptions = null;
      ssUpdateScreen();
    });

    // set up tooltips/hovers
    jQuery("#skirmishbar").bind("plothover", ssBarStaticHover );
    jQuery("#skirmishpie").bind("plothover", ssPieHover );

    // set up zoom bar selection handling
    jQuery("#skirmishbar").bind("plotselected", function (event, ranges) {
      // do the zooming
      cBar = jQuery.plot(jQuery("#skirmishbar"), bar_chart.data,
                    jQuery.extend(true, {}, bar_chart.options, {
                        xaxis: { min: ranges.xaxis.from, max: ranges.xaxis.to }
                    }));

      // don't fire event on the overview to prevent eternal loop
      cZoom.setSelection(ranges, true);

      gBarRanges = ranges;
    });

    jQuery("#skirmishbarzoom").bind("plotselected", function (event, ranges) {
      cBar.setSelection(ranges);
    });


    // update the screen the first time on page load
    ssUpdateScreen();
  }
}

// register various hooks when the page is ready including the default state of all charts
jQuery(document).ready(function() {
  ssInitScreen( );
});

// global hash that contains a copy of skirmish data based on the current filter selections.
// this exists so that the chart data indices can be matched up with skirmish log to know
// which skirmish detail to show in tooltips
var gCurrentLog = {};

var gMovingAverageLength = 10;

// define and set default bar mode (day or run)
var gBarMode = 'day';

var gBarRanges = {};

var gNumDaysGroup = 1;

// let the charts be global;
var cBar;
var cZoom;
var cPie;

var gZoomOptions = null;

var gTheme = 'elf';

// colors to use for the pie chart slices
var gThemeColors = {
  dwarf: {
    bar: "#9F4419",
    avgLine: "#FFFFFF",
    pie: [ {r: 221, g: 95,  b: 35},
           {r: 159, g: 68,  b: 25},
           {r: 128, g: 55,  b: 20} ],
    pieStroke: "#561F06"
  },
  hobbit: {
    bar: "#538D2E",
    pie: [ {r: 117, g: 194, b: 68},
           {r: 83,  g: 141, b: 46},
           {r: 67,  g: 113, b: 37} ],
    avgLine: "#FFFFFF",
    pieStroke: "#1A4D11"
  },
  elf: {
    bar: "#5C60B1",
    avgLine: "#FFFFFF",
    pie: [ {r: 204, g: 102, b: 255},
           {r: 153, g: 51,  b: 204},
           {r: 102, g: 0,   b: 204} ],
    pieStroke: "#46008C"
  },
  race_of_man: {
    bar: "#633706",
    pie: [ {r: 194, g: 147, b: 68},
           {r: 141, g: 105, b: 46},
           {r: 113, g: 84,  b: 37} ],
    avgLine: "#FFFFFF",
    pieStroke: "#513A14"
  }
}

// register a callback for when a widget is moved
moveCallbacks[ 'skirmishcharts' ] = ssInitScreen;

