var EasyFilter = {};
EasyFilter.Filters = {};

EasyFilter.DataModel = Class.create();
EasyFilter.DataModel.prototype = {
	initialize: function( dataRows ) {
       		this.observers = [];
		this.dataRows = [];
		this.filters = [];
		var self = this;
		var ind = 0;
		$A(dataRows).each( function( dr ) { self.dataRows.push( { visible: true, data: dr, index: ind } ); ind++; } );
	},
	addFilter: function( filter ) {
		this.filters.push( filter );
	},
	addObserver: function( observer ) {
		this.observers.push( observer );
	},
	dataRowCount: function() {
		return this.dataRows.length;
	},
	dataRow: function( ind ) {
		return this.dataRows[ind].data;
	},
	isVisible: function( ind ) {
		return this.dataRows[ind].visible;
	},
	setVisible: function( ind, visible ) {
		if ( this.dataRows[ind].visible != visible )
		{
			this.dataRows[ind].visible = visible;
			var self = this;
			this.observers.each( function( o ) { try { o.visibilityChanged( self, ind, visible ); } catch( e ) {} } );
		}
	},
	updateFilters: function() {
		var self = this;
		this.dataRows.each( function( dr ) {
			var visible = true;
			self.filters.each( function( filter ) {
				if ( filter.filter( dr.data ) == false ) { visible = false; }
			} );
			self.setVisible( dr.index, visible );
		} );
	}
};

EasyFilter.TableView = Class.create();
EasyFilter.TableView.prototype = {
	initialize: function( parent, model, template ) {
		this.template = new JSTemplate( template );
		this.parent = $(parent);
		this.model = model;
		this.model.addObserver( this );
		this.itemsByIndex = {};
		this.createViewItems();
	},
	createViewItems : function() {
		for(var i = 0; i < this.model.dataRowCount(); i++ )
		{
			this.itemsByIndex[i] = this.template.create( this.model.dataRow( i ) );
			this.itemsByIndex[i].style.display = this.model.isVisible( i ) ? 'block' : 'none';
			this.parent.appendChild( this.itemsByIndex[i] );
		}
	},
	visibilityChanged: function( sender, index, visible ) {
		if ( visible == false )
			new Effect.Fade( this.itemsByIndex[ index ], { duration: 1 } );
		else
			new Effect.Appear( this.itemsByIndex[ index ], { duration: 1 } );
	}
};

EasyFilter.Filters.SingleSelect = Class.create();
EasyFilter.Filters.SingleSelect.prototype = {
	initialize: function( parent, model, field, values ) {
		this.parent = $(parent);
		this.model = model;
		this.field = field;
		this.values = values;
		this.createDropDown();
		this.model.addFilter( this );
		this.model.updateFilters();
	},
	createDropDown: function() {
		this.elSelect = document.createElement('select');
		var self = this;

		this.elSelect.onchange = function() { self.model.updateFilters(); };

		var elAllOption = document.createElement( 'option' );
		elAllOption.value = '';
		elAllOption.appendChild( document.createTextNode( 'All' ) );
		self.elSelect.appendChild( elAllOption );

		for( var key in this.values ) {
			var value = this.values[ key ];
			var elOption = document.createElement( 'option' );
			elOption.value = key;
			elOption.appendChild( document.createTextNode( value ) );
			self.elSelect.appendChild( elOption );
		}

		this.parent.appendChild( this.elSelect );
	},
	filter: function( data ) {
		var value = this.elSelect.options[ this.elSelect.selectedIndex ].value.toString();
		if ( value == null || value.length == 0 )
			return true;
		return value == data[ this.field ].toString();
	}
};

EasyFilter.Filters.RangeSelect = Class.create();
EasyFilter.Filters.RangeSelect.prototype = {
	initialize: function( parent, model, field, values ) {
		this.parent = $(parent);
		this.model = model;
		this.field = field;
		this.values = values;
		this.createDropDown();
		this.model.addFilter( this );
		this.model.updateFilters();
	},
	createDropDown: function() {
		this.elSelect = document.createElement('select');
		var self = this;

		this.elSelect.onchange = function() { self.model.updateFilters(); };

		var elAllOption = document.createElement( 'option' );
		elAllOption.value = '';
		elAllOption.appendChild( document.createTextNode( 'All' ) );
		self.elSelect.appendChild( elAllOption );

		this.values.each( function( item, ind ) {
			var elOption = document.createElement( 'option' );
			elOption.value = ind;
			elOption.appendChild( document.createTextNode( item.name ) );
			self.elSelect.appendChild( elOption );
		} );

		this.parent.appendChild( this.elSelect );
	},
	filter: function( data ) {
		var value = this.elSelect.options[ this.elSelect.selectedIndex ].value.toString();
		if ( value == null || value.length == 0 )
			return true;
		var ind = parseInt( value );
		var value = parseFloat( data[this.field] );
		return ( value >= this.values[ind].low && value <= this.values[ind].high );
	}
};

EasyFilter.Filters.Text = Class.create();
EasyFilter.Filters.Text.prototype = {
	initialize: function( parent, model, fields ) {
		this.parent = $(parent);
		this.model = model;
		this.fields = $A(fields);
		this.timer = null;
		this.createTextField();
		this.model.addFilter( this );
		this.model.updateFilters();
	},
	createTextField: function() {
		this.elText = document.createElement('input');
		this.elText.type = 'text';

		var self = this;
		this.elText.onkeyup = function() { self.onKeyUp(); };

		this.parent.appendChild( this.elText );
	},
	onKeyUp: function() {
		var self = this;
		if ( this.timer != null ) { window.clearTimeout( this.timer ); this.timer = null; }
		this.timer = window.setTimeout( function() { self.onUpdate(); }, 200 );
	},
	onUpdate: function() {
		this.model.updateFilters();
		this.timer = null;
	},
	filter: function( data ) {
		var value = this.elText.value.toLowerCase();
		if ( value.length == 0 )
			return true;
		var found = false;
		this.fields.each( function( f ) {
			if ( data[f] != null && data[f].toLowerCase().indexOf( value ) >= 0 ) found = true;
		} );
		return found;
	}
};

EasyFilter.Filters.MultiSelect = Class.create();
EasyFilter.Filters.MultiSelect.prototype = {
	initialize: function( parent, model, field, values ) {
		this.parent = $(parent);
		this.model = model;
		this.field = field;
		this.values = values;
		this.valueChecks = [];
		this.selectedValues = null;
		this.allowAll = false;
		this.createCheckboxes();
		this.model.addFilter( this );
		this.model.updateFilters();
	},
	createCheckboxes: function() {
		var self = this;
		this.values.each( function( value, ind ) {
			var elCheck = document.createElement('input');
			elCheck.type = 'checkbox';
			elCheck.checked = 'checked';
			elCheck.defaultChecked = true;
			elCheck.onchange = function() { self.updateSelectedValues(); };
			elCheck.value =	ind;
			elCheck.id = self.field+'_'+ind;
			self.valueChecks.push( elCheck );
			self.parent.appendChild( elCheck );

			var elLabel = document.createElement('label');
			elLabel.appendChild( document.createTextNode( value.name ) );
			self.parent.appendChild( elLabel );

			self.parent.appendChild( document.createTextNode( ' ' ) );
		} );
	},
	updateSelectedValues: function() {
		var self = this;
		this.selectedValues = {};
		self.valueChecks.each( function( elCheck, ind ) {
			if ( elCheck.checked == true || elCheck.checked == 'checked' ) self.selectedValues[ self.values[ ind ].value ] = true;
		} );
		
		this.allowAll = ( $H(this.selectedValues).keys().length == this.values.length );
		
		self.model.updateFilters();
	},
	filter: function( data ) {
		if ( this.selectedValues == null ) this.updateSelectedValues();
		if ( this.allowAll ) return true;
		var self = this;
		var found = false;
		data[ this.field ].each( function( item ) {
			if ( self.selectedValues[ item ] != null )
				found = true;
		} );
		return found;
	}
};
