SearchForm = Class.create();



SearchForm.prototype = {
		
	initialize: function(elementOrId , datasource , form , options) {
		
		this.element = $(elementOrId);
		
		this.formValues = form;

		this.criteria = {};
		this.criteria.cities = [];
		this.criteria.districts = [];
		this.criteria.types = [];
		this.criteria.prices = [];
		
		this.selection = [];
		
		this.datasource = datasource;
		
		
		this.options = {};
		this.options.showSearchFields = ['cities' , 'types' , 'prices'];
		
		
		Object.extend(this.options, options || {});
		if(form.FORSALE == 'false')	{	
			this.options.forsale = false;
			}
		else
			this.options.forsale = true;
			
		
		/*
		 * Zet de waardes in het formulier om naar criteria.
		 */
		if(form.CITY)
			this.criteria.cities = form.CITY.split(",");
		if(form.DISTRICT) 
			this.criteria.districts = form.DISTRICT.split(",");
		if(form.PRICE)
			this.criteria.prices[0] = parseInt(form.PRICE);
		
		if(form.TYPE) {
			arr = form.TYPE.toString().split(",");
			arr.each(function(e){
				e = this.getTypeMaskRev().get(e);
			}.bind(this));
			this.criteria.types = arr;
		}
		
		
		var koopHuur = this.getSaleRent();
		if(koopHuur.sale == 0) {
			this.options.forsale = false;
		}
		this.criteria.forsale = this.options.forsale;
		if( form.FORSALE == "false" ) {
			this.criteria.forsale = false;
		}
		if( form.FORSALE == "true" ) {
			this.criteria.forsale = true;
		}
		
		
		/*
		 * Hieronder wordt het formulier gebouwd.
		 */
		this.form = new Element('FORM' , {'method':'post','id':'mySearchForm'});
		
		// koop huur selectie 
		
		
		if(koopHuur.sale || koopHuur.rent) {
			this.koopOption = new Element('INPUT' , {'type':'radio', 'name': 'forsale', 'value': 'true', 'id': 'koopHuurSelectie_koop', 'checked': this.criteria.forsale == true});
			this.huurOption = new Element('INPUT' , {'type':'radio', 'name': 'forsale', 'value': 'false', 'id': 'koopHuurSelectie_huur','checked': this.criteria.forsale == false});
			
			this.koopOption.observe('change' , this.updateForSale.bind(this));
			this.huurOption.observe('change' , this.updateForSale.bind(this));
			
			var koopHuurOptions = new Element('DIV');
			koopHuurOptions.addClassName('koop-huur-options');

			var koopLabel = new Element('LABEL',{'for':'koopHuurSelectie_koop'});
			koopLabel.update("Koop (" + koopHuur.sale + ")");
			var huurLabel = new Element('LABEL',{'for':'koopHuurSelectie_huur'});
			huurLabel.update("Huur (" + koopHuur.rent + ")");
			
			koopHuurOptions.appendChild( this.koopOption );
			koopHuurOptions.appendChild( koopLabel  );
			koopHuurOptions.appendChild( this.huurOption );
			koopHuurOptions.appendChild( huurLabel  );
			
			this.form.appendChild(koopHuurOptions);
		} else if(!koopHuur.sale && koopHuur.rent) {
			this.criteria.forsale = false;
		}
		
		/*
		 * Zet de prijs categorie op ieder object
		 */
		 this.datasource.each(this.setPriceCategory.bind(this));
		
		if(this.options.showSearchFields.indexOf('cities') != -1) {
			var citiesBox = new Element('DIV');
			citiesBox.addClassName ('city_search_form optionbox');
			citiesBox.appendChild(new Element('DIV').addClassName('header').update('Plaatsen')); 
			
			this.citiesContainer = new Element('DIV');
			this.citiesContainer.addClassName('options');
			citiesBox.appendChild(this.citiesContainer);
			
			this.form.appendChild(citiesBox);
		}
		
		if(this.options.showSearchFields.indexOf('districts') != -1) {
		
			var districtBox = new Element('DIV');
			districtBox.addClassName('district_search_form optionbox');
			districtBox.appendChild(new Element('DIV').addClassName('header').update('Wijken')); 
			
			this.districtContainer = new Element('DIV');
			this.districtContainer.addClassName('options');
			districtBox.appendChild(this.districtContainer);
		
			this.form.appendChild(districtBox);
		}
		
		if(this.options.showSearchFields.indexOf('types') != -1) {
			var typesBox = new Element('DIV');
			typesBox.addClassName('types_search_form optionbox');
			typesBox.appendChild(new Element('DIV').addClassName('header').update('Types')); 
			
			this.typesContainer = new Element('DIV');
			this.typesContainer.addClassName('options');
			typesBox.appendChild(this.typesContainer);
			
			this.form.appendChild(typesBox);
		}
		
		if(this.options.showSearchFields.indexOf('prices') != -1) {
			var pricesBox =  new Element('DIV');
			pricesBox.addClassName('price_search_form optionbox');
			pricesBox.appendChild(new Element('DIV').addClassName('header').update('Prijsklasse'));
			
			this.pricesContainer =  new Element('DIV');
			this.pricesContainer.addClassName('options');
			pricesBox.appendChild(this.pricesContainer);
			
			this.form.appendChild(pricesBox);
		}
		
		
		// de reset button
		this.resetButton = new Element('INPUT' , 
			{'type': 'button' , 'value': 'wissen'}).observe(
				'click' , this.reset.bind(this)
		);
		this.resetButton.addClassName('button reset');
		// de sbumit button
		this.submitButton = new Element('INPUT' , 
			{'type': 'button' ,'value': 'verstuur'}).observe(
				'click' , this.submit.bind(this)
		);
		this.submitButton.addClassName('button submit');
		
		
		var orderby = new Element('SELECT' , {'id':'orderby','name':'orderby'});
		//orderby.options[orderby.options.length] = new Option('Wijk','district');
		orderby.options[orderby.options.length] = new Option('Plaats','city');
		orderby.options[orderby.options.length] = new Option('Prijs','price');
		orderby.options[orderby.options.length] = new Option('Type' , 'type');
		orderby.options[orderby.options.length] = new Option('Woonoppervlakte','livingspace');
		orderby.options[orderby.options.length] = new Option('Bouwjaar','buildyear');
		
		
		if(form.ORDERBY) 
			$A(orderby.options).each(function(e){if(form.ORDERBY == e.value) e.selected = 'selected';});
		
		var direction = new Element('SELECT' , {'id':'direction','name':'direction'});
		direction.options[direction.options.length] = new Option('Oplopend','ASC');
		direction.options[direction.options.length] = new Option('Aflopend','DESC');
		
		if(form.DIRECTION)
			$A(direction.options).each(function(e){if(form.DIRECTION == e.value) e.selected = 'selected';});
		
		
		this.cityField = new Element('INPUT' , {'type':'hidden' , 'name': 'city'});
		this.districtField = new Element('INPUT' , {'type':'hidden' , 'name': 'district'});
		
		this.typeField = new Element('INPUT' , {'type':'hidden' , 'name': 'type'});
		this.priceField = new Element('INPUT' , {'type':'hidden' , 'name': 'price'})
		this.priceFromField = new Element('INPUT' , {'type':'hidden' , 'name': 'priceFrom'});
		this.priceToField = new Element('INPUT' , {'type':'hidden' , 'name': 'priceTo'});
		
		
		var fields = new Element('DIV').addClassName('fields');
		fields.appendChild(new Element('SPAN').addClassName('label').update('Sorteren op:'));
		
		fields.appendChild(orderby);
		fields.appendChild(direction);
		
		fields.appendChild(this.cityField);
		fields.appendChild(this.districtField);
		fields.appendChild(this.typeField);
		fields.appendChild(this.priceField);
		fields.appendChild(this.priceFromField);
		fields.appendChild(this.priceToField);
		fields.appendChild(this.resetButton);
		fields.appendChild(this.submitButton);
		
		this.form.appendChild(fields);
		
		this.element.appendChild(this.form);
		
		document.fire("searchForm:build");
		
		
		this.build();
	},
	/*
	 * Returns an array of price categories.
	 */
	getPriceMask: function(i) {
		if(this.criteria.forsale == false) {
			return [
				{text:'< - &euro; 400', from: -1, to:399, for_rent: true},
				{text:'&euro; 400 - &euro; 500',from: 400, to:499, for_rent: true},
				{text:'&euro; 500 - &euro; 700',from: 500, to:699, for_rent: true},
				{text:'&euro; 700 - &euro; 1000',from: 700, to:999, for_rent: true},
				{text:'&euro; 1000 - &euro; 1500',from: 1000, to:1500, for_rent: true},
				{text:'&euro; 1500 - &euro; 2000',from: 1500, to:1999, for_rent: true},
				{text:'&euro; 2000 - ',from: 2000, to:999999999, for_rent: true}
			];
		} else {
			return [
				{text:'< - &euro; 100.000', from: -1, to:99999, for_sale: true},
				{text:'&euro; 100.000 - &euro; 200.000',from: 100000, to:199999, for_sale: true},
				{text:'&euro; 200.000 - &euro; 300.000',from: 200000, to:299999, for_sale: true},
				{text:'&euro; 300.000 - &euro; 400.000',from: 300000, to:399999, for_sale: true},
				{text:'&euro; 400.000 - &euro; 500.000',from: 400000, to:499999, for_sale: true},
				{text:'&euro; 500.000 - &euro; 750.000',from: 500000, to:749999, for_sale: true},
				{text:'&euro; 750.000 - &euro; 1.000.000',from: 750000, to:999999, for_sale: true},
				{text:'&euro; 1.000.000 - &euro; 1.500.000',from: 1000000, to:1499999, for_sale: true},
				{text:'&euro; 1.500.000 -  geen max.',from: 1500000, to:99999999999999999, for_sale: true}
			];
		}
		
	},
	/*
	 * Places the right priceCetegory on the objects.
	 */
	setPriceCategory: function(obj) {
		obj.priceCategory = 0;
		
		
		
		this.getPriceMask().each(function(prm , i){
			if(obj.price_rent >= prm.from && obj.price_rent  <= prm.to && this.criteria.forsale == false){
				obj.priceCategory = i;
				
			} else if(obj.price_sale >= prm.from && obj.price_sale  <= prm.to) {
				obj.priceCategory = i;
			}
			
			
		}.bind(this));
		
		
	},
	
	
	/*
	 * Creates a selection of objects based on the selected criteria
	 */
	filter: function() {
		// clear the current selection
		this.selection = [];
		

		
		var i = 0;
		for (i = 0 ; i < this.datasource.length ; i++) {
//			alert('criteria.types=' + this.criteria.types + " << " + this.datasource[i].type_id + " >> " + this.criteria.types.indexOf(this.datasource[i].type_id));
			if(
				(this.criteria.cities.indexOf(this.datasource[i].city) != -1 || !this.criteria.cities.length )&& 
				(this.criteria.districts.indexOf(this.datasource[i].district) != -1 || !this.criteria.districts.length )&&
				(this.criteria.types.indexOf(this.datasource[i].type_id) != -1 || !this.criteria.types.length ) &&
				(include(this.criteria.prices, this.datasource[i].priceCategory ) || !this.criteria.prices.length) &&
				((this.criteria.forsale == true && (this.datasource[i].for_sale == true || ( this.datasource[i].for_sale == false && this.datasource[i].for_rent == false))) ||
				  (this.criteria.forsale == false && this.datasource[i].for_rent == true)))
			{
				this.selection.push(this.datasource[i]);
			}
		}
		if(!this.selection.length) {
			//window.alert("Geen resultaten.");
			
		}
	},
	getSaleRent: function(){
		
		var saleRent = {sale:0,rent:0};
		for(i = 0 ; i < this.datasource.length ; i++) {
			if(this.datasource[i].for_rent == true) {
				saleRent.rent++;
			}
			if(this.datasource[i].for_sale == true) {
				saleRent.sale++;
			}
			
		}
		return saleRent;
	},
	updateForSale: function() {
		
		if(this.koopOption.checked) {
			this.criteria.forsale = true;
		} else {
			this.criteria.forsale = false;
		}
		this.datasource.each(this.setPriceCategory.bind(this));
		this.reset();
		
		
		
	},
	getCities: function() {
		var i = 0;
		var cities = new Hash();
		
		this.selection.each(function(s){
			if(cities.get(s.city) != undefined ) {
				cities.set(s.city , cities.get(s.city) + 1);
			} else {
				cities.set(s.city , 1);
			}
		});
		// vul aan met geselecteerde plaatsen die 0 resultaten hebben.
		this.criteria.cities.each(function(e){
			if(cities.get(e) == undefined) {
				cities.set(e,0)	
			}
		});
		return cities;
	},
	getDistricts: function() {
		var i = 0;
		var districts = new Hash();
		
		this.selection.each(function(s){
			//window.alert(s.district + " " + districts.get(s.district));
			if(districts.get(s.district) != undefined ) {
				districts.set(s.district , districts.get(s.district) + 1);
			} else {
				districts.set(s.district , 1);
			}
		});
		// vul aan met geselecteerde plaatsen die 0 resultaten hebben.
		this.criteria.districts.each(function(e){
			if(districts.get(e) == undefined) {
				districts.set(e,0)	
			}
		});
		return districts;
	},
	getTypes: function() {
		
		var i = 0;
		var types = new Hash();
		var typeMask = this.getTypeMaskRev();
		
		this.selection.each(function(s){
			if(types.get(s.type) != undefined ) {
				types.set(s.type , types.get(s.type)+1);
			} else {
				types.set(s.type , 1);
			}
		});
		// vul aan met geselecteerde types die 0 resultaten hebben.
		this.criteria.types.each(function(e){
			e = typeMask.get(e);
			if(types.get(e) == undefined) {
				types.set(e,0)	
			}	
		});
		return types;
	},
	getPrices: function() {
		
		var i = 0;
		var prices = new Hash();
	
		this.selection.each(function(s){
			if(prices.get(s.priceCategory) != undefined ) {
				prices.set(s.priceCategory , prices.get(s.priceCategory)+1);
			} else {
				prices.set(s.priceCategory , 1);
			}
		});
		// vul aan met geselecteerde prijzen die 0 resultaten hebben.
		this.criteria.prices.each(function(e){
			if(prices.get(e) == undefined) {
				prices.set(e,0)	
			}
		});
		return prices;
	},
	/*
	 * Maakt een hash van de types waarbij de type naam de key is.
	 */
	getTypeMask: function() {
		if( this.typeMask == undefined ) {
			var i = 0;
			this.typeMask = new Hash();
			for(i = 0 ; i < this.datasource.length ; i++) {
				this.typeMask.set(this.datasource[i].type , this.datasource[i].type_id );
			}
		}
		return this.typeMask;
	},
	/*
	 * Maakt een hash van de types waarbij de type id de key is.
	 */
	getTypeMaskRev: function() {
		if( this.typeMaskRev == undefined ) {
			var i = 0;
			this.typeMaskRev = new Hash();
			for(i = 0 ; i < this.datasource.length ; i++) {
				this.typeMaskRev.set(this.datasource[i].type_id, this.datasource[i].type );
			}
		}
		return this.typeMaskRev;
	},
	buildTypes: function() {
		if(this.options.showSearchFields.indexOf('types') != -1) {
			
			this.typesContainer.getElementsBySelector('DIV.searchOption').invoke( 'remove' );
			
			var types = this.getTypes();
			var keyArray = this.getTypes().keys().sort();
			keyArray.each(function(key) {
				var zoekCriteria = "";
				 this.getTypeMaskRev().each(function(pair) {
					if (pair.value == key) {
						if (zoekCriteria.length > 0) {
							zoekCriteria += ",";
						}
						zoekCriteria += pair.key;
					}
				});
				var el = new SearchOption(key + " (" + types.get(key) + ")", zoekCriteria, this , 'types');
				el.element.observe('click' , function() {
					if (this.parent.criteria[this.scope].indexOf(this.value) == -1) {
						var typeArr = this.value.split(",");
						for (var i = 0; i < typeArr.length; i++) {
							this.parent.criteria[this.scope].push(typeArr[i]);
						}
						this.element.addClassName('selected');
					} else {
						this.parent.criteria[this.scope] = this.parent.criteria[this.scope].without(this.value);
						this.element.removeClassName('selected');	
					}
					this.parent.filter();
					this.parent.buildCities();
					this.parent.buildPrices();
					this.parent.buildDistricts();
//					if (!this.parent.typesContainer.getElementsBySelector('DIV.selected').length) {
						this.parent.buildTypes();
	//				}
					document.fire("searchForm:clicked");
				}.bind(el));
				this.typesContainer.appendChild(el.element);
				if(this.criteria.types.indexOf( zoekCriteria ) != -1) {
					el.element.addClassName('selected');
				}
			}.bind(this));
		}
	},
	buildCities: function(){
		if(this.options.showSearchFields.indexOf('cities') != -1) {
			
			this.citiesContainer.getElementsBySelector('DIV.searchOption').invoke( 'remove' );
			
			var cities = this.getCities();
			var keyArray = this.getCities().keys().sort();
			keyArray.each(function(key){
				var el = new SearchOption( key + " (" + cities.get(key) + ")" , key  , this , 'cities');
				el.element.observe(
					'click' , function(){
					
					if(this.parent.criteria[this.scope].indexOf(this.value) == -1) {
						this.parent.criteria[this.scope].push(this.value);
						this.element.addClassName('selected');
					} else {
						this.parent.criteria[this.scope] = this.parent.criteria[this.scope].without(this.value);
						this.element.removeClassName('selected');	
					}
					this.parent.filter();
					this.parent.buildTypes();
					this.parent.buildPrices();
					this.parent.buildDistricts();
					
					if(!this.parent.citiesContainer.getElementsBySelector('DIV.selected').length) {
						this.parent.buildCities();
					}
					
					document.fire("searchForm:clicked");
					
				}.bind(el));
				this.citiesContainer.appendChild(el.element);
				if(this.criteria.cities.indexOf(key) != -1) {
					el.element.addClassName('selected');
				}
				
				
			}.bind(this));
		}
	},
	
	buildDistricts: function(){
		if(this.options.showSearchFields.indexOf('districts') != -1) {
			
			this.districtContainer.getElementsBySelector('DIV.searchOption').invoke( 'remove' );
			
			var districts = this.getDistricts();
			var keyArray = this.getDistricts().keys().sort();
			keyArray.each(function(key){
				var el = new SearchOption( key + " (" + districts.get(key) + ")" , key  , this , 'districts');
				
				el.element.observe(
				'click' , function(){
					
					if(this.parent.criteria[this.scope].indexOf(this.value) == -1) {
						this.parent.criteria[this.scope].push(this.value);
						this.element.addClassName('selected');
					} else {
						this.parent.criteria[this.scope] = this.parent.criteria[this.scope].without(this.value);
						this.element.removeClassName('selected');	
					}
					this.parent.filter();
					this.parent.buildTypes();
					this.parent.buildPrices();
					this.parent.buildCities();
					if(!this.parent.districtContainer.getElementsBySelector('DIV.selected').length) {
						this.parent.buildDistricts();
					}
					
					document.fire("searchForm:clicked");
					
				}.bind(el));
				this.districtContainer.appendChild(el.element);
				if(this.criteria.districts.indexOf(key) != -1) {
					el.element.addClassName('selected');
				}
				
				
			}.bind(this));
		}
	},
	
	buildPrices: function(){
		if(this.options.showSearchFields.indexOf('prices') != -1) {
			
			this.pricesContainer.getElementsBySelector('DIV.searchOption').invoke( 'remove' );
			
			var prices = this.getPrices();
		
			var keyArray = this.getPrices().keys().sort(function(a,b){return a-b;});
			var prMask = this.getPriceMask();
			keyArray.each(function(key){
				key = parseInt(key);
				var el = new SearchOption( prMask[key].text  + " (" + prices.get(key) + ")" , parseInt(key)  , this , 'prices');
				el.element.observe(
				'click' , function(){
					if(this.parent.criteria[this.scope].indexOf(this.value) == -1) {
						this.parent.criteria[this.scope].clear();
						this.parent.criteria[this.scope].push(this.value);
						this.element.addClassName('selected');
					} else {
						this.parent.criteria[this.scope] = this.parent.criteria[this.scope].without(this.value);
						this.element.removeClassName('selected');	
					}
					this.parent.filter();
					this.parent.buildCities();
					this.parent.buildTypes();
					this.parent.buildPrices();
					this.parent.buildDistricts();
					
					document.fire("searchForm:clicked");
					
				}.bind(el));
				
				this.pricesContainer.appendChild(el.element);
				if(this.criteria.prices.indexOf(key) != -1) {
					el.element.addClassName('selected');
				}
			}.bind(this));
		}
	},
	build: function(){
		this.filter();
		this.buildCities();
		this.buildTypes();
		this.buildPrices();
		this.buildDistricts();
	},
	reset: function() {
		this.criteria.cities = [];
		this.criteria.prices = [];
		this.criteria.types = [];
		this.criteria.districts = [];
		this.build();
		
		document.fire("searchForm:resetted");
	},
	submit: function() {
		
		this.cityField.value = this.criteria.cities.join();
		this.typeField.value = this.criteria.types.join();
		this.priceField.value = this.criteria.prices.join();
		this.districtField.value = this.criteria.districts.join();
		
		if( this.criteria.prices.length ) {
			prMask = this.getPriceMask();
			this.priceFromField.value = prMask[this.criteria.prices[0]].from;
			this.priceToField.value = prMask[this.criteria.prices[0]].to;
		}	
		this.form.submit();
		
		
		document.fire("searchForm:submitted");
	}
}

var SearchOption = Class.create();

SearchOption.prototype = {
	
	initialize: function(text,value,parent,scope) {
		this.text = text;
		this.value = value;
		this.parent = parent;
		this.scope = scope;
		this.element = new Element('DIV').addClassName('searchOption').update(this.text).observe( 
			'mouseover' , this.over.bind(this)).observe( 
			'mouseout', this.out.bind(this));
		
	},
	over: function() {
		 this.element.addClassName('over');	
	},
	out: function() {
		this.element.removeClassName('over');
	}
		
		
	
		
}

function include(arr, obj) {
        for(var i = -1, j = arr.length; ++i < j;)
            if(arr[i] === obj) return true;
        return false;
	}

