/*
 *	jquery.chart.js - Google Visualisations implementation in JQuery
 *
 *	@author Grant French, Bluestone Creative Limited 2009
 *	@description Converts data in selected DL elements to charts
 *	@dependencies Requires http://www.google.com/jsapi to be loaded prior
 *
 *	options:
 *		type: The chart type to display as, options are line,bar,pie (Default: pie)
 *		width: Width of the chart in px, no units required (Default: 400)
 *		height: Height of the chart in px, no units required (Default: 240)
 *		xLabel: The default x axis label (Default: Response)
 *		yLabel: The default y axis label (Default: Respondants)
 *		is3D: Sets whether the chart should be 3D (Default: true)
 *		defaultTitle: The default chart title (Default: '')
 *		destroyDL: If set to true the DL data source will be replaced by the chart, if set to false the DL will be hidden (Default: true)
 *		classOverridesType: If a class on a DL can override the chart type set in the options (Default: true)
 *
 *	For nested DL's i.e. <dl><dt>test</dt><dd><dl><dt>testsub</dt><dd>1</dd></dl></dd></dl> the chart type will automatically
 *		be set to bar as this is the only type that can represent this data structure.
 *
 *	Chart titles are picked up from the title attribute on a DL
 *	
 *	Function can be chained when destroyDL is set to false
 *
 * 	When classOverridesType is true a class on a DL can set the chart type, available classes are:
 *		chart-line
 *		chart-bar
 *		chart-pie
 *
 * 	Example Usage: 
 *		$('dl#testresult').chart();
 *		$('dl#testresult').chart( { type: 'line', width: 300 } );
 * 
 */

if (typeof(runPollResults) == "undefined") {
  google.load("visualization", "1", {packages:["barchart","piechart","linechart"]});  
} else {
google.load("visualization", "1", {packages:["barchart","piechart","linechart"], callback: runPollResults});
  
} 

$.fn.chart = function( options ) {

	var settings = $.extend({
		type: 'pie',
		width: 700,
		height: 240,
		xLabel: 'Response',
		yLabel: 'Respondants',
		is3D: true,
		defaultTitle: '',
		destroyDL: true,
		classOverridesType: true,
		dates: {
			dateFormat: { /* UK Date format (dd/mm/yy[yy]) */
				validation: /^[0-9]{1,2}\/[0-9]{1,2}\/[0-9]{2,4}$/,
				day: /^([0-9]{1,2})\/[0-9]{1,2}\/[0-9]{2,4}$/,
				month: /^[0-9]{1,2}\/([0-9]{1,2})\/[0-9]{2,4}$/,
				year: /^[0-9]{1,2}\/[0-9]{1,2}\/([0-9]{2,4})$/
			},
			fillMissingDates: false
		}
	}, options);

	$(this).each( function() {

		//Check the item is what we are expecting
		if (this.nodeName.toLowerCase() != 'dl') return;

		//Setup local variables
		var localChartType = settings.type;
		var colCount = 0;
		var objKeys = {};
		var nested = false;

		//Create new data table to hold data
		var data = new google.visualization.DataTable();

		//Look for nested lists
		if ( $("dd dl",this).length > 0 ) {

			//First column should be the questions
			data.addColumn( 'string', 'Question' );

			//Get all terms from the nested lists
			$('dd dl dt',this).each( function() { objKeys[$(this).text()]=true; } );
			for( var strKey in objKeys ) { objKeys[ strKey ] = colCount++; data.addColumn('number', strKey ) }

			//Go through each question
			$("dt",this).each( function() {

				//Get the associated data element
				var dataElem = $(this).next('dd');

				//Get the question text
				var questionText = $(this).text();

				//Nested DLs (group results)
				if ( $('dl',dataElem).length > 0 ) {
					
					//Flag that this is a nested dl (used to force the chart type)
					nested = true;

					//Start an array to define row to add, first col is the question
					var row = [ questionText ];

					//Fill in the other columns in the row
					$('dl dt',dataElem).each( function() {
						var strResponse = $(this).text();
						var numericValue = parseFloat( $(this).next('dd').text() );
						if (numericValue != 'NaN') {
							row[ objKeys[ strResponse ] + 1 ] = numericValue
						}
					});
					
					//Add the row to the data table
					data.addRow( row );
				}
			});

		} else {

			//Single dl list we know there will only be two columns
			data.addColumn( 'string','Response' ); data.addColumn( 'number','Responses' );

			//Go through each question/response
			$('dt',this).each( function() {

				//Get the response text and the number of respondants
				var responseText = $(this).text();
				var responseCount = $(this).next('dd').text();

				//If the response count is a number then add it to the row
				var numericValue = parseFloat( responseCount );
				if (numericValue != 'NaN') data.addRow( [ responseText, numericValue ] );
				
			});
		}

		//Create a new div to contain the chart
		var chartDiv = $('<div></div>');

		//Extract the title from the dl, if not present use default
		var chartTitle = $(this).attr('title');
		if (chartTitle == '') chartTitle = settings.defaultTitle;

		//Determine the chart type
		if ( !nested && ( settings.classOverridesType && $(this).hasClass('chart-line') ) ) {
		  chartClass = google.visualization.LineChart;

		} else if ( !nested && ( settings.classOverridesType && $(this).hasClass('chart-pie') ) ) {
		  chartClass = google.visualization.PieChart;

		} else if ( nested ||  ( settings.classOverridesType && $(this).hasClass('chart-bar') ) ) {
		  chartClass = google.visualization.BarChart;

		} else { 
		  
		  switch (localChartType) {
        case 'line':
        chartClass = google.visualization.LineChart;
           break;
        case 'pie':
         chartClass = google.visualization.PieChart;
           break;
        case 'bar':
          chartClass = google.visualization.BarChart;
           break;
      }  

		  
		}
    
    
		//If the chart type (chartClass) is set then create the chart, else display an error
		if ( chartClass != undefined ) {
		  if (settings.destroyDL) { $(this).replaceWith( chartDiv ); } else { $(this).after( chartDiv ); $(this).hide(); }
		  var chart = new chartClass( chartDiv.get(0) );
		  chart.draw(data, {width: settings.width, height: settings.height, is3D: settings.is3D, title: chartTitle});

		} else {
		  chartDiv.html('<span class="error">Unable to instantiate chart type "' + localChartType +'"</span>'); 
		  $(this).after( chartDiv );

		}

	});

	//Allow chaining if destroyDL is false, otherwise return a blank jquery object
	if ( !settings.destroyDL ) { return this; }
	else { return $(); }

};
