$(function(){


//FILTERING

		//initializes the filter, with the route for ajax requests, and the css selector class for the type of boxes that will be filtered
		$.fn.Filtering = function(controllerRoute, boxClass){

			var $this = this;

			//target the result box area
			var boxlist = $("#boxlist");
			
			//and the collection of boxes in it
			var boxCollection = $(boxClass, boxlist);


			//This stores a reference current booking api ajax request object, if any
			//so outstanding requests can be cancelled
			var currentRequest = null;



			//EXTRACT BASIC DATA FROM HOTEL BOXES IN BASE RESULT SET
			var getBoxDetails = function(boxCollection){

				var boxDetails = {};

				boxCollection.each(function(){

					boxDetails[$(this).attr("id")] = JSON.parse( decodeURIComponent(this.getAttribute("data-details")) );
				});

				return boxDetails;
			};

			var boxDetails = getBoxDetails(boxCollection);
			

			//external getter for current collection
			this.collectionLength = boxCollection.length;






			//JQUERY SELECTORS FOR FORM INPUTS
			var selectors = {
				city : $("#cityselect"),
				stars : $("#stars_select"),
				features : $("#features_select"),
				categories : $("#offers_select"),
				brands : $("#brand_select")
			};


			var inputs = {
				city : selectors.city.val(),
				stars : $("input", selectors.stars),
				features : $("input", selectors.features),
				categories : $("input", selectors.categories),
				brands : $("input", selectors.brands)
			};

			//GET AVAILABLE STARS/FEATURES/CATEGORIES/BRANDS
			//makes an object to get all available aspects from the base result set in one pass
			//the controls will be enabled/disabled/built based on the results

			var getAvailable = function(collection){

				//get list of available stars and features in filtered collection
				var filteredStarSet = [], filteredFeatureSet = [], filteredCategorySet = [], filteredBrandSet = [];

				//for brands, if 'other' is found, push it to the end of the results
				var otherflag = false;

				_(collection).each(function(element){

					if (element.stars) filteredStarSet.push(element.stars);
					if (element.features_names) filteredFeatureSet.push(element.features_names);
					if (element.offer_category) filteredCategorySet.push(element.offer_category+'=>'+element.offer_category_name);
					if (element.brand) {
						if (element.brand == "Other" || element.brand == "Andere") { otherflag = true; }
						else { filteredBrandSet.push(element.brand); }
					}
				});

				var avl = {
					stars : _.uniq(filteredStarSet),
					features : _.uniq(_.flatten(filteredFeatureSet)),
					categories : _.uniq(filteredCategorySet),
					brands : _.uniq(filteredBrandSet)
				};

				if (otherflag) {
					if (window.lang == "en"){
						avl.brands.push("Other");
					} else {
						avl.brands.push("Andere");
					}
				}
				
				return avl;
				

			};






				//BUILD CONTROLS for aspects that depend on what is in the base result set.

				//Generalised control builder for exclusive filters
				var buildCheckboxSet = function(container, type, rowClass, containerSelector, initiallyChecked){

					var set = getAvailable(boxDetails)[type];

					var setHtml = ich.checkboxSet({ controls :
						_(set).map(function(control){
							return {
								type: rowClass,
								label: control.split("=>")[1] ? control.split("=>")[1] : control.split("=>")[0],
								value: control.split("=>")[0],
								id: control.split("=>")[0].split(" ").join("_"),
								check: (initiallyChecked) ? 'checked="checked"' : ""
							};
						})
					});

					//create and insert html if more than one brand found.
					//assign jquery selector for new brand inputs
					if (set.length > 0) {
						$(containerSelector, container).html( setHtml );
						container.css({ display : "block" });
						inputs[type] = $( "input", container );
					} else {
						container.css({ display : "none" });
					}
//					console.log(container, type);
				};



				//Build form controls for BRAND
				this.buildBrandFilter = function(container){
					return buildCheckboxSet(container, "brands", "brandField", ".brand", true);
				};

				//Build form controls for FEATURES
				this.buildFeaturesFilter = function(container){
					return buildCheckboxSet(container, "features", "featureField", ".checkset", false);
				};

				//Build form controls for (offer) CATEGORIES
				this.buildCategoriesFilter = function(container){
					return buildCheckboxSet(container, "categories", "categoryField", ".checkset", true);
				};



					//FILTER FUNCTIONS - these filter the json data based on what is selected in the form controls
					var filterByStars = function(inputCollection){

						var starSet = [],
							filtered = _.clone(inputCollection);

						inputs.stars.each(function(){
							var $this = $(this);
							if ( $this.attr('checked') && !$this.attr('disabled') ) starSet.push( parseInt($this.val(), 10) );
						});

						//filter by stars (HAS OR)
						filtered = _(filtered).select(function(element){
							return  _(starSet).detect(function(star){
								return parseInt(element.stars, 10) == star;
							});
						});

						return filtered;
					};



					var filterByBrand = function(inputCollection){

							var brandSet = [],
								filtered = _.clone(inputCollection);

							$("input", $("#brand_select")).each(function(){
								var $this = $(this);
								
								if ( $this.attr('checked') && !$this.attr('disabled') ) {
									brandSet.push( $this.val());
								}
								
							});

							//filter by brand (HAS OR)
							filtered = _(filtered).select(function(element){
                                                        return  _(brandSet).detect(function(brand){
                                                                        return element.brand == brand;
                                                        });
                                        });

							return filtered;
					};



					var filterByCategory = function(inputCollection){

							var categorySet = [],
								filtered = _.clone(inputCollection);

							inputs.categories.each(function(){

								var $this = $(this);

								if ( $this.attr('checked') && !$this.attr('disabled') ) categorySet.push( $this.val() );

							});

							filtered = _(filtered).select(function(element){
                                                        return  _(categorySet).detect(function(cat){
                                                                        return element.offer_category == cat;
                                                        });
                                        });

							return filtered;
					};



					var filterByFeatures = function(inputCollection){

							var featureSet = [],
								filtered = _.clone(inputCollection);

							inputs.features.each(function(){
								var $this = $(this);
								if ( $this.attr('checked') && !$this.attr('disabled') ) featureSet.push( $this.val() );
							});

							//filter by features (HAS AND)
							if (featureSet.length > 0){
								filtered = _(filtered).select(function(element){
									//check if all features for this hotel are in the required features array (featureSet)
									return _(featureSet).all(function(requiredFeature){
													return _(element.features).detect(function(elemFeature){
															return elemFeature == requiredFeature; });
									});
								});
							}
							return filtered;
					};


					var filterByCity = function(inputCollection){

							var filtered = _.clone(inputCollection);

							//filter by city (IS)
							if (inputs.city != ""){
								filtered = _(filtered).select(function(element){
									return element.city.code == inputs.city;
								});
							}
							return filtered;
					};

					//DISABLE FORM CONTROLS BASED ON AVAILABLE STARS/FEATURES/CATEGORIES
					var disableStars = function(stars){
						inputs.stars.each(function(){

							var $this = $(this);

							if ( _(stars).detect(function(star){ return parseInt($this.val(),10) == star; }) ){
								$this.removeAttr('disabled').parent("div").css('opacity',1);

							} else {
								$this.attr('disabled','disabled').parent("div").css('opacity',0.4);
							}
						});
					};

					var disableBrands = function(brands){
						inputs.brands.each(function(){

							var $this = $(this);

							if ( _(brands).detect(function(brand){ return $this.val() == brand; }) ){
								$this.removeAttr('disabled').parent("div").css('opacity',1);

							} else {
								$this.attr('disabled','disabled').parent("div").css('opacity',0.4);
							}
						});
					};

					var disableFeatures = function(features){

						
						inputs.features.each(function(){
							var $this = $(this);
							
							$this.attr('disabled','disabled').parent("div").css('opacity',0.4);
							
							//// check if the faeture is available on the search result /////
							var isAvail = _(features).detect(function(feature){
									var regExp = $this.val() + "=>";
									return  feature.indexOf(regExp) === 0 ? 1 : 0; }
									);
								
							if (isAvail){
								$this.removeAttr('disabled').parent("div").css('opacity',1);	
							} 
						});
					};

					var disableCategories = function(categories){

						inputs.categories.each(function(){

							var $this = $(this);

							if ( _(categories).detect(function(cat){ return $this.val() == cat; }) ){
								$this.removeAttr('disabled').parent("div").css('opacity',1);
							} else {
								$this.attr('disabled','disabled').parent("div").css('opacity',0.4);
							}
						});
					};



















					//FILTERING ANIMATION
					var applyFilter = function(filteredCollection){

						var filteredSelector = _(filteredCollection).map(function(element){
							var id = element.id || element.offer_id;
							return "#" + id;
						})
						.join(",");

						//hide all boxes
						boxlist.fadeOut(200,function(){
														   
								boxCollection.css({ display : "none" });	
								$(filteredSelector, boxlist).css({ display : "block" });
														   
								//show those that match
								boxlist.fadeIn(100, function(){
									
									$("body").trigger("filterEnd");
								});							   
						});					

					};





					//PERFORM ACTIONS BASED ON WHAT IS CURRENTLY BEING ALTERED




					//if city or dates being altered
					this.byCity = function(urlParam, city, datefrom, dateto, promocode){

								var getData = {
									datefrom : datefrom || $(".date:first").data("dateinput").getValue("dd.mm.yyyy"),
									dateto : dateto || $(".date:last").data("dateinput").getValue("dd.mm.yyyy"),
									promocode : promocode || $("#promocode").val()
								};

								var urlParam = urlParam || "city";
								var city = city || $("#cityselect").val();

								getData[urlParam] = city;


								if (city !== ""){

									//if any activeapi ajax requests, abort them
									if (currentRequest != null) {
										currentRequest.abort();
									}

									//ajax GET the url for that city, i.e. hotels.php?city=Berlin
									currentRequest = $.get( controllerRoute, getData, function(data){

										if (data.length > 1){

											//$.fn.clear_overlay();

                                            /// loads a sertain parts of the newly generated html into the layout
                                            partialContentLoader(data);


											boxlist.fadeOut(200,function(){

												data = $(data).find("#boxlist").html();

												//extract hotel box set and load into current page
												boxlist.html( data ).fadeIn(200,function(){

													//console.trace();

													//update high-level boxlist and cloned boxlist variables based on new html
													boxlist = $("#boxlist");
													boxCollection = $(boxClass, boxlist);

													//update boxDetails
													boxDetails = getBoxDetails(boxCollection);

													//get available for city
													var available = getAvailable(boxDetails);
													

													//disable stars/features controls based on that
													if (inputs.stars.length > 0) {
														//reset checking of all stars
														inputs.stars.each(function(){
															$(this).attr('checked', "checked");
														});
														disableStars(available.stars);
													}

													//rebuild brands
													if (inputs.brands.length > 0) {
														$this.buildBrandFilter(selectors.brands);
													}

													//rebuild features
													if (inputs.features.length > 0) {
        												$this.buildFeaturesFilter(selectors.features);
													}

													//rebuild categories
													if (inputs.categories.length > 0) {
														$this.buildCategoriesFilter(selectors.categories);
													}

													var filteredCollection = boxDetails;

													if (inputs.stars.length > 0) filteredCollection = filterByStars(filteredCollection);

													//initialize lightboxes, if any
													$.fn.initializeLightBoxes();
                                                                                                        enableEditor();
                                                                                                        eventsMngr();
												});
											});
										}
									},'html');



								}

					};

					//if stars being altered
					this.byStars = function(evt,callback){

								boxDetails = getBoxDetails(boxCollection);

								//filter, get features available for city / stars
								var boxDetails = filterByStars( boxDetails );

								if (boxDetails.length == 0){

									if (evt) evt.preventDefault();

								} else {

									var available = getAvailable( boxDetails );

									//disable features / brands controls based on that
									disableFeatures(available.features);

									if (inputs.brands) disableBrands(available.brands);

									var filteredCollection = filterByFeatures( boxDetails );

									if (callback) callback();

									//refilter, factoring in disabled
									applyFilter(filteredCollection);
								}
					};


					//if stars being altered
					this.byBrand = function(evt,callback){

								boxDetails = getBoxDetails(boxCollection);

								//filter, get features available for city / stars
								var boxDetails = filterByBrand( boxDetails );

								if (boxDetails.length == 0){

									if (evt) evt.preventDefault();

								} else {

									var available = getAvailable( boxDetails );
									
									//disable features controls based on that
									if (inputs.features.length > 0) {
										disableFeatures(available.features);
									}
									
									var filteredCollection = filterByStars( boxDetails );

									if (callback) callback();

									//refilter, factoring in disabled
									applyFilter(filteredCollection);
								}
					};




					//if features being altered
					this.byFeatures = function(evt,callback){

								boxDetails = filterByStars( filterByFeatures(getBoxDetails(boxCollection)));

								if (boxDetails.length == 0){
									if (evt) evt.preventDefault();
								} else {
									if (callback) callback();
									//filter, factoring in disabled
									applyFilter(boxDetails);
								}
					};          
    




					//if category being altered
					this.byCategory = function(evt,callback){
                                           
                                            boxDetails = filterByCategory(getBoxDetails(boxCollection));
                                            if (boxDetails.length == 0){
                                                    if (evt) evt.preventDefault();
                                            } else {
                                                    if (callback) callback();

                                                    applyFilter(boxDetails);
                                            }
					};



					//disables things on pageload
					this.generalDisable = function(){

						var boxDetails = getBoxDetails(boxCollection);
						var available = getAvailable(boxDetails);

						//disable stars/features/brands controls based on that
						if (inputs.stars.length > 0) {
							//reset checking of all stars
							inputs.stars.each(function(){
								$(this).attr('checked', "checked");
							});
							disableStars(available.stars);
						}

						if (inputs.brands) {
							inputs.brands.each(function(){
								$(this).attr('checked', "checked");
							});
							disableBrands(available.brands);
						}

						if (inputs.features.length > 0) disableFeatures(available.features);
						if (inputs.categories.length > 0) disableCategories(available.categories);


					};




		};



});
