



	/**
	 * Rates Matrix 
	 * @param {Object} options
	 */
	var RatesMatrix = base2.Base.extend({
		constructor: function(options) {
			this.SetOptions(options);
			this.LoadTemplates();
			this.SetEvents();
			this.ShowLoading();
			this.GetRates();
		},

		Defaults: {
			APIRates: GBPServiceUrl + "/{channelID}/rates/all",
			APIRatesUpdate: GBPServiceUrl + "/{channelID}/rates/all/update",
			Channel: GBPCHANNELS.PureTasmania,
			ContainerSelector: "#rates",
			Template: "/gbp/templates/gbp_bar.html",
			TemplateRatesMatrix: "/gbp/templates/gbp_ratesmatrix.html",
			TemplateDestination: "/gbp/templates/gbp_bar_destination.html",
			TemplateProductType: "/gbp/templates/gbp_bar_producttype.html",
			TemplateProvider: "/gbp/templates/gbp_bar_provider.html",
			TemplateProduct: "/gbp/templates/gbp_bar_product.html",
			TemplateSalesConfig: "/gbp/templates/gbp_bar_salesconfig.html",
			SelectedDate: new Date(),
			FilterDestination: null,
			FilterProvider: null,
			ActivateProvider: null,
			OnComplete: function() {}
		},

		Options: {},
		
		Templates: {},

		Data: {},
		
		Container: null,
		
		SalesConfigurations: new base2.Array2(),
		
		Products: new base2.Array2(),

		SetOptions: function(options) {
			this.Options = jQuery.extend({}, this.Defaults, options);
			
			this.Container = jQuery(this.Options.ContainerSelector);

		},
		
		UseCustomFilters: function() {
			return (this.Options.FilterDestination != null && this.Options.FilterProvider != null)
		},
		
		LoadTemplates: function() {
			this.Templates.BAR = LoadTemplate(this.Options.Template);
			this.Templates.Destination = LoadTemplate(this.Options.TemplateDestination);
			this.Templates.ProductType = LoadTemplate(this.Options.TemplateProductType);
			this.Templates.Provider = LoadTemplate(this.Options.TemplateProvider);
			this.Templates.Product = LoadTemplate(this.Options.TemplateProduct);
			this.Templates.SalesConfiguration = LoadTemplate(this.Options.TemplateSalesConfig);
			
			this.Container.append(jQuery(this.Templates.BAR));
			this.HideLoading();
		},


		SetEvents: function() {
			var object = this;
			
			this.Container.delegate(".accordion .provider-name a ", "click", function() {
				var trigger = jQuery(this);
				var parent = trigger.parent();
				var rates = parent.next();

				if (trigger.parent().hasClass("active")) {
					// already open...close it
					rates.removeClass("active");
					parent.removeClass("active");
				} else {
					// already closed...open it
					rates.addClass("active");
					parent.addClass("active");
					
					//Adjust row cell heights to match col 1
					var rows = rates.find(".tr");
					base2.Array2.forEach(rows, function(row){
						row = jQuery(row);
						var col1 = row.find(".col1");
						var col1Height = col1.height();
						var cellPadding = Math.floor((col1Height - 14) / 2);
						
						var currentPadding = parseInt(row.find(".td:first").css("paddingTop").replace("px", ""));
						
						var newPadding = cellPadding + currentPadding;
						row.find(".day, .col2").css({
							paddingTop: newPadding,
							paddingBottom: newPadding
						});
					});
				}

				return false;
			});
			
			// Sales Configuration mouse enter
			this.Container.delegate(".bookingRates .tr", "mouseenter", function() {
				jQuery(this).addClass("hover");
			})
			// Sales Configuration mouse leave
			this.Container.delegate(".bookingRates .tr", "mouseleave", function() {
				jQuery(this).removeClass("hover");
			});
			
			// Navigate to URL
			this.Container.delegate(".bookingRates .tr", "click", function() {
				var url = jQuery(this).find(".col2 a").attr("href");
				window.location = url;
			})
		},


		ShowLoading: function() {
			var loader = this.Container.find(".loadingRates");
			loader.stop(true, false).animate({ height: 50});
		},

		HideLoading: function() {
			var loader = this.Container.find(".loadingRates");
			loader.stop(true, false).animate({ height: 0}, function(){ loader.stop(true, false).delay(1000).hide(); });
		},


		SetDateFromDate: function(date) {
			
			this.Options.SelectedDate = date;

			this.GetRatesUpdate();
		},

		SetDate: function(year, month, day) {

			var date = Date.parseExact(year+"/"+month+"/"+day, "yyyy/M/d");
			this.SetDateFromDate(date);
		},

		SetDatePickers: function(date) {
			var datepicker = this.Container.find(".datepicker");
			var dateValue = datepicker.find("#date1 span");
			dateValue.html(this.Options.SelectedDate.toString("dd MMM yyyy"));
			
			datepicker.find(".datepopup").datepicker("setDate", this.Options.SelectedDate);
			
		},


		SetDateLabels: function(date) {

			var rateTables = this.Container.find(".bookingRatesBest");

			base2.Array2.forEach(rateTables, function(rateTable) {
				var dateCells = rateTable.find(".thead .th.day");

				var currentDate = Date.parse(date.toString("yyyy/MM/dd"));

				base2.Array2.forEach(dateCells, function(dateCell) {
					dateCell = jQuery(dateCell);
					dateCell.html(currentDate.toString("ddd<br>dd MMM"));

					currentDate.add(1).days()
				})
				
			});
		},
		
		FixCellHeights: function() {
			if (!this.IsHeightsFixed) {
				//Adjust row cell heights to match col 1
				var rows = this.Container.find(".tr");
				base2.Array2.forEach(rows, function(row){
					row = jQuery(row);
					var col1 = row.find(".col1");
					var col1Height = col1.height();
					var cellPadding = (col1Height - 14) / 2; //Math.floor((col1Height - 14) / 2);
					
					
					var currentPadding = parseInt(row.find(".td:first").css("paddingTop").replace("px", ""));
					
					var newPadding = cellPadding + currentPadding;
					row.find(".day, .col2").css({
						paddingTop: newPadding,
						paddingBottom: newPadding
					});
				});
				
				this.IsHeightsFixed = true;
			}
		},


		GetRates: function() {
			var url = this.Options.APIRates.replace("{channelID}", this.Options.Channel);

			var data = { StartDate: this.Options.SelectedDate.toString("yyyy/MM/dd") }

			var response = new APIHandler({
				Url: url,
				Data: JSON.stringify(data),
				Method: APIMETHODS.POST,
				Async: true,
				Callback:  jQuery.proxy(this.GetRatesHandler, this)
			}).Response;
			
		},

		GetRatesHandler: function(response) {
			if (response.Result) {

				// Hide loading 
				this.HideLoading();
				
				
				this.data = response.Value;

				var destinations = this.data.Destinations ;
			
				if (this.UseCustomFilters()) {
					
					base2.Array2.forEach(destinations, jQuery.proxy(function(destination) {
						if (destination.ID == this.Options.FilterDestination) {
					this.AddDestination(destination);
						}
					}, this));
				}
				else {
					base2.Array2.forEach(destinations, jQuery.proxy(function(destination){
						this.AddDestination(destination);
					}, this));
				}
				
				// Call the callback and pass in this object
				this.Options.OnComplete(this);
				
			} else {
				alert(response.Message);
			}
			
		},
		
		GetRatesUpdate: function() {
			var url = this.Options.APIRatesUpdate.replace("{channelID}", this.Options.Channel);

			// Get entire list of Products
			var productIDs = this.Products.pluck("ProductCode");

			var data = { 
				StartDate: this.Options.SelectedDate.toString("yyyy/MM/dd"),
				ProductIDs: productIDs 
			}

			jQuery(".bookingItems").hide();
			this.ShowLoading();
			
			var response = new APIHandler({
				Url: url,
				Data: JSON.stringify(data),
				Method: APIMETHODS.POST,
				Async: true,
				Callback:  jQuery.proxy(this.GetRatesUpdateHandler, this)
			}).Response;
		},
		
		GetRatesUpdateHandler: function(response) {
			if (response.Result) {
				this.UpdateRatesMatrix(response.Value.SalesConfigurations);
				jQuery(".bookingItems").show();
				this.HideLoading();
			} else {
				// Problem querying for new rates
			}
			
		},
		

		
		AddDestination: function(destination) {
			
			var destinationTemplate = jQuery(this.Templates.Destination);
			destinationTemplate.find(".destination-name").html(destination.Name);
			destinationTemplate.data("destination", destination);
			destinationTemplate.addClass(destination.Colour);
			this.Container.append(destinationTemplate);
			
			
			var containerProductTypes = destinationTemplate.find(".productTypes");
			
			// Accommodation
			if (destination.ProductTypes.accommodation && destination.ProductTypes.accommodation.length > 0) {
				this.AddProductType(containerProductTypes, destination.ProductTypes.accommodation, "Accommodation")

			}
			// Experiences
			if (destination.ProductTypes.experiences && destination.ProductTypes.experiences.length > 0) {
				this.AddProductType(containerProductTypes, destination.ProductTypes.experiences, "Experiences")
			}
			
			var object = this;
			// Set date picker
			// Datepicker
			destinationTemplate.find('.datepicker').each(function(){
				
				var selectedDateElement = jQuery(this).find("#date1 span");
				selectedDateElement.html(object.Options.SelectedDate.toString("dd MMM yyyy"));
				
				var a = jQuery('.trigger', this);
				jQuery(this).append('<div class="datepopup"></div>');
				jQuery('.datepopup', this).datepicker({
					inline: true,
					dateFormat: 'dd MM yy',
					onSelect: function(date, inst){
						a.find('span').html(date.toUpperCase()).end().
							parents('.datepicker').
								removeClass('datepicker-active').
								find('input[type="hidden"]').val(date).end();
						object.SetDate(inst.selectedYear, inst.selectedMonth + 1, inst.selectedDay);
						object.SetDatePickers();
						//object.RefreshRates();
						
					}
				});
				jQuery('.trigger', this).click(function(){
					jQuery(this.parentNode).toggleClass('datepicker-active');
					return false;
				});
			});

			
		},
		
		
		AddProductType: function(container, data, name) {
			var productType = jQuery(this.Templates.ProductType);
			productType.find(".type-name").html(name);
			
			var providers = productType.find(".providers");
			
			container.append(productType);
			
			if (this.UseCustomFilters()) {
			base2.Array2.forEach(data, jQuery.proxy(function(provider) {
					if (provider.ProviderID == this.Options.FilterProvider && provider.Products.length > 0) {
					this.AddProvider(providers, provider);
				}
				}, this));
			}
			else {
				base2.Array2.forEach(data, jQuery.proxy(function(provider){
					if (provider.Products.length > 0) {
						this.AddProvider(providers, provider);
					}
				}, this));
			}
			


			
		},
		
		
		
		AddProvider: function(container, data) {
			
			var providerTemplate = jQuery(this.Templates.Provider);
			providerTemplate.find(".provider-name a").html(data.Name.Media[0].Label.Text);
			providerTemplate.find(".provider-name").attr({
				id: data.ProviderID
			});
			
			var containerProduct = providerTemplate.find(".products");
			
			container.append(providerTemplate);
			
			var productCount = 0;
			
			base2.Array2.forEach(data.Products, jQuery.proxy(function(product){
				var showDates = productCount++ == 0;
				
				this.AddProduct(containerProduct, product, showDates)
			}, this));
			


			
		},
		
		
		AddProduct: function(container, data, showDates) {
			
			var productTemplate = jQuery(this.Templates.Product);
			
			if (!showDates) {
				//productTemplate.find(".thead .tr").empty();
				productTemplate.find(".thead").remove();
				productTemplate.find(".product-name").html('');
			}
			else {
				//productTemplate.find(".product-name").html(data.ProductName);
			}

			productTemplate.data("product", data);
			container.append(productTemplate);

			// Set SalesConfigurations
			base2.Array2.forEach(data.SalesConfigurations, jQuery.proxy(function(salesConfiguration) {
				this.AddSalesConfiguration(productTemplate, salesConfiguration, data);
			}, this));

			this.Products.push(data);


		},

		AddSalesConfiguration: function(container, salesConfigData, productData) {
			var salesConfigurationTemplate = jQuery(this.Templates.SalesConfiguration);
			//salesConfigurationTemplate.find(".col1").html(salesConfigData.Name);
			salesConfigurationTemplate.find(".col1").html(productData.ProductName);
			salesConfigurationTemplate.find(".col2 a").attr({ href: productData.ProductUrl});
			salesConfigurationTemplate.data("salesConfiguration", salesConfigData);
			salesConfigurationTemplate.attr({ rel: "sc" + salesConfigData.SalesConfigurationID});

			container.append(salesConfigurationTemplate);

			var salesConfigArray = new base2.Array2();
			salesConfigArray.push(salesConfigData);

			this.UpdateRatesMatrix(salesConfigArray);

			this.SalesConfigurations.push(salesConfigData);

		},

		/**
		 * Updates the product rates based on supplied array of SalesConfigurations
		 * @param {Object} data (Array of Sales Configurations)
		 */
		UpdateRatesMatrix: function(data) {
			var container = this.Container;
			base2.Array2.forEach(data, function(salesConfiguration) {

				// Get salesConfigID
				var salesConfigurationID = salesConfiguration.SalesConfigurationID;

				// Find the sales config row
				var row = container.find("[rel='sc" + salesConfigurationID + "']");

				// Locate the dates heading row
				//var dates = row.parent().prev().find(".th.day");
				var dates = row.parent().find(".th.day");

				// Get row days
				var days = row.find(".day").removeClass("weekend");

				var index = 0;
				base2.Array2.forEach(salesConfiguration.DailyDetails, function(dailyDetail) {

					var day = days.eq(index);
					var date = dates.eq(index);
					day.data("dailyDetail", dailyDetail);
					day.html(dailyDetail.DisplayAmount);

					// Date
					var rateDate = Date.parse(dailyDetail.Date);
					date.html(rateDate.toString("ddd<br>dd MMM"));

					// Determine Weekend
					var dayOfWeek = rateDate.toString("ddd");
					if (dayOfWeek == "Sat" || dayOfWeek == "Sun") {
						date.addClass("weekend");
					} else {
						date.removeClass("weekend");
					}

					if (dailyDetail.Inactive) {
						day.addClass("inactive");
					} else {
						day.removeClass("inactive");
					}
					index ++ ;
				});
			})
		}
	});
