WWL.graph = function ( name, libs )
{
	var prefix = WWL._libbase + 'graph/rgraph/RGraph.';
	var graph_types = [
		'Bar',
		'Bipolar',
		'Fuel',
		'Funnel',
		'Gantt',
		'HBar',
		'HProgress',
		'LED',
		'Line',
		'Meter',
		'Odometer',
		'Pie',
		'Radar',
		'Rose',
		'Rscatter',
		'Scatter',
		'Skeleton',
		'Thermometer',
		'VProgress',
		'Waterfall'
	];
	var commons = [
		'common.adjusting',
		'common.annotate',
		'common.context',
		'common.core',
		'common.effects',
		'common.resizing',
		'common.tooltips',
		'common.zoom'
	];
	var loaded_js = [];
	
	var graph = new WWL ( 'graph', name );

	graph.container = $( graph.name );
	
	if ( graph.container.firstChild && graph.container.firstChild.tagName == 'CANVAS' )
	{
		graph.canvas = graph.container.firstChild;
	}
	else
	{
		graph.canvas = document.createElement ( 'canvas' );
		graph.canvas.id = 'graph-' + graph.name;
		graph.container.appendChild ( graph.canvas );
	}

	graph.draw = function ( params )
	{
		if ( ! params ) return false;
		
		if ( params.gtype ) this.gtype = params.gtype;
		if ( params.width ) this.width = parseInt ( params.width, 10 );
		if ( params.height ) this.height = parseInt ( params.height, 10 );
		if ( params.data ) this.data = params.data;
		if ( params.config ) this.config = params.config;

		if ( ! this.width && ! this.height )
		{
			var size = liwe.dom.get_size ( this.container );
			this.width = size [ 0 ];
			this.height = size [ 1 ];
		}
		
		if ( ! this._check () )
			return false;

		this.canvas.width = this.width;
		this.canvas.height = this.height;

		var self = this;
		var res = this._load_js ( this.gtype, function () { graph._draw.call ( self ); } );
		if ( ! res )
			this._draw ();
	};

	graph._draw = function ()
	{
		var method = RGraph [ this._camelize ( this.gtype ) ];

		if ( this.graph )
			RGraph.Clear ( this.canvas );

		// HACK: dynamic constructor invocation (open for suggestions...)
		var evalstr = 'this.graph = new method ( this.canvas.id';
		if ( this.data )
			for ( var i = 0; i < this.data.length; i++ )
				evalstr += ', this.data [ ' + i + ' ]';
		evalstr += ' )';

		eval ( evalstr );
		
		if ( this.config )
			RGraph.SetConfig ( this.graph, this.config );

		RGraph.AddCustomEventListener ( this.graph, 'onresizeend', function ( obj )
		{
			obj.canvas.style.left = obj.canvas.style.top = 0;
		});
		
		this.graph.Draw ();
	};

	graph._check = function ()
	{
		if ( graph_types.find ( this.gtype ) == -1 )
		{
			console.error ( 'Unknown graph type: %s', this.gtype );
			return false;
		}
		if ( this.width == 0 || this.height == 0 )
		{
			console.error ( 'Wrong size!' );
			return false;
		}
		return true;
	};

	graph._load_js = function ( name, cback )
	{
		if ( loaded_js.find ( name ) != -1 ) return false;
		
		loaded_js.push ( name );
		
		// HACK: Odometer graph is in RGraph.odo.js -- why ?!?
		if ( name == 'odometer' ) name = 'odo';

		var fullpath = prefix + name + '.js';
		liwe.utils.append_js ( fullpath, cback );
		
		return true;
	};

	graph._camelize = function ( s )
	{
		var i = graph_types.find ( s );
		return graph_types [ i ];
	};

	graph._load_js ( 'common.core' ); 

	if ( libs )
	{
		libs.iterate ( function ( v )
		{
			var libname = 'common.' + v;
			if ( commons.find ( libname ) != -1 )
				graph._load_js ( libname );
		});
	}

	return graph;
};

WWL.graph.get_instance = function ( instance_name )
{
	return WWL.get_instance ( 'graph', instance_name );
};


