fittipPopup = 
{
	show: function(html)
	{
		if ($("#fitTipPopup").length == 0)
		{
			$(document.body).append('<div id="fitTipPopup"><div class="wrapper"></div></div>');
		}
		var $popup = $("#fitTipPopup"), that = this;
		$popup.html(html).append('<p class="button"><button>Close</button></p>');
		if ($("#overlay").length == 0)
		{
			$(document.body).append('<div id="overlay"></div>');
		}
		var w = $(window).width(), h = $(window).height(), offsetTop = $(window).scrollTop(), oh = $(document).height(), ow = $(window).width();
		if ($.browser.msie)
		{
			ow = document.documentElement.scrollWidth;
			oh = document.documentElement.scrollHeight;
		}
		$("#overlay").css({width:ow, height:oh}).show();
		$popup.find("div.wrapper").show();
		$popup.css({display:'block',visibility:'hidden',width:$("#content").innerWidth() - 14, height:'auto'});
		var iw = $popup.outerWidth(), ih = $popup.innerHeight();
		var start = {left: Math.round(w / 2), top: (Math.round(h / 2) + offsetTop)};
		var end = {left:start.left - Math.ceil(iw / 2), top: start.top - Math.ceil(ih / 2)};
		iw = $popup.width();
		ih = $popup.height();
		$popup.css({width:0, height:0, left:start.left, top:start.top, visibility:'visible'}).show();
		$popup.find("div.wrapper").hide();
		$popup.animate({width:iw, height:ih, left:end.left, top:end.top}, 'fast', function()
		{
			$popup.find("div.wrapper").show();
		});
		function updatePosition()
		{
			var w = $(window).width(), h = $(window).height(), offsetTop = $(window).scrollTop();
			var iw = $popup.outerWidth(), ih = $popup.innerHeight();
			var center = {left: Math.round(w / 2), top: (Math.round(h / 2) + offsetTop)};
			var pos = {left:center.left - Math.ceil(iw / 2), top: center.top - Math.ceil(ih / 2)};
			$popup.css({left:pos.left, top:pos.top});
		};
		$(window).bind("scroll.fit-tip", function()
		{
			updatePosition();
		});
		$("#fitTipPopup button").unbind().click(function()
		{
			that.hide();
		});
	},
	hide: function()
	{
		var $popup = $("#fitTipPopup");
		var w = $(window).width(), h = $(window).height(), offsetTop = $(window).scrollTop();
		$popup.find("div.wrapper").hide();
		$popup.animate({width: 0, height: 0, left: Math.round(w / 2), top: (Math.round(h / 2) + offsetTop)}, 'fast', function()
		{
			$popup.hide();
		});
		$(window).unbind("scroll.fit-tip");
		$("#overlay").hide();
	}
};
dropdown =
{
	opts: null,
	items: [],
	active: function()
	{
		return ("#dropdown").is(":visible");
	},
	hide: function()
	{
		var w = $("#dropdown").width(), pos = $("#dropdown").position();
		//console.log(pos);
		$("#dropdown").css({left:0, top: pos.top, width: w, position:"absolute"}).animate({left:w}, 500, function()
		{
			$("#dropdown").hide().css({position:"static", width: "auto"});
		});
	},
	show: function()
	{
		var w = $("#content div.wrapper").outerWidth();
		$("#dropdown").css({left:w, top: 0, width: w, position: "absolute"}).show().animate({left:0}, 500, function()
		{
			$("#dropdown").css({position:"static", width: "auto"});
		});
	},
	render: function()
	{
		var h = ['<ul>'];
		for (var i = 0, len = dropdown.items.length; i < len; i++)
			h.push('<li><a href="#" vid="' + dropdown.items[i].id + '">' + dropdown.items[i].text + '</a></li>');
		h.push('</ul>');
		$("#dropdown div.options").html(h.join(''));
		$("#dropdown a").click(function()
		{
			dropdown.hide();
			dropdown.opts.onSelect($(this).attr("vid"));
			$("#dropdown").stop(true, true).css({position:"static", width: "auto"}).hide();
			return false;
		}).filter('a[vid=' + dropdown.opts.selected + ']').addClass("selected");
	},
	activate: function(opts)
	{
		var o = $.extend({title:'Choose an option', selected: null, items: [], getter: null, onCancel: function(){}, onSelect: function(){}}, opts);
		dropdown.opts = o;
		$("#dropdown div.title").text(o.title);
		$("#dropdown div.head button").unbind().click(function()
		{
			dropdown.hide();
			o.onCancel();
		});
		if (o.getter)
		{
			var loader = new dataloader($("#dropdown div.options"));
			o.getter(function(i)
			{
				dropdown.items = i;
				dropdown.render();
			}, loader);
		}
		dropdown.show();
	}
};
app = 
{
	config: {dataUrl: 'data.php', dataProviderType: "php"},
	carMake: {selected: null, items: []},
	carModel: {selected: null, items: []},
	carId: {selected: null, items: []},
	carYearRange: {selected: null, items: []},
	carVariation: {selected: null, items: []},
	carYearExact: {selected: null, items: []},
	fitType: {selected: null, items: [], name: ''},
	products: {selected: null, items: []},
	vehicleSummary: null,
	roofRack: null,
	barSpread: null,
	currentStep: 1,
	resetData: function(src)
	{
		src.selected = null;
		src.items = [];
	},
	getById: function(id, src)
	{
		for (var key in src.items)
			if (src.items[key].id == id)
				return src.items[key];
		return null;
	},
	stateChange: function(d)
	{
		var data = $.extend({step:0, src:'', action:''}, d);
		$("#wizardStep button").hide();
		$("#vehicleInformation div.results-preview button").hide();
		switch (data.step)
		{
			case 1:
				switch (data.src)
				{
					case "carMake":
					case "carModel":
					case "carId":
					case "carYearRange":
					case "carYearExact":
						break;
					case "carVariation":
						$("#vehicleInformation div.results-preview button").show();
						app.resetData(app.fitType);
						break;
					case "init":
					case "show":
						if (app.carVariation.selected)
							$("#vehicleInformation div.results-preview button").show();
						break;
					case "hide":
						break;
				};
				break;
			case 2:
				if (app.fitType.selected)
					$("#wizardStep button.next").show();
				$("#wizardStep button.back").show();
				break;
			case 3:
				$("#wizardStep button.back").show();
				break;
			case 4:
				$("#wizardStep button.back").show();
				break;
		};
	},
	init: function()
	{
	},
	show: function()
	{
		app.stateChange({step:app.currentStep, src:'show'});
		$("#wizard").fadeIn("fast", function()
		{
			$("#wizard").css({width: "auto"});
		});
	},
	hide: function()
	{
		app.stateChange({step:app.currentStep, src:'hide'});
		$("#wizard").fadeOut("fast", function()
		{
			$("#wizard").css({width: "auto"});
		});
	},
	setStatus: function(opts)
	{
	},
	setWizardStep: function(step)
	{
		app.currentStep = step;
		$("#wizardStep button").hide();
		$("#vehicleInformation, #fitType, #roofRack, #vehicleSummary").hide();
		switch (step)
		{
			case 1:
				$("#vehicleInformation").show();
				$("#wizardStep div.progress div").removeClass().addClass("step-1").parent().parent().find("p").html("Step 1: Your vehicle information");
				break;
			case 2:
				$("#fitType").show();
				$("#wizardStep div.progress div").removeClass().addClass("step-2").parent().parent().find("p").html("Step 2: Fit type");
				break;
			case 3:
				$("#roofRack").show();
				$("#wizardStep div.progress div").removeClass().addClass("step-3").parent().parent().find("p").html("Step 3: " + app.fitType.name);
				break;
			case 4:
				$("#vehicleSummary").show();
				$("#wizardStep div.progress div").removeClass().addClass("step-4").parent().parent().find("p").html("Step 4: Vehicle Summary");
				break;
			default:
		};
		$("#vehicleInformation div.results-preview button").unbind().click(function()
		{
			app.step2();
		});
		$("#wizardStep button.next").unbind().click(function()
		{
			switch (app.currentStep)
			{
				case 1:
					app.step2();
					break;
				case 2:
					app.step3();
					break;
			};
		});
		$("#wizardStep button.back").unbind().click(function()
		{
			switch (app.currentStep)
			{
				case 2:
					app.step1();
					app.stateChange({step:1, src:'init'});
					break;
				case 3:
					app.step2();
					break;
				case 4:
					app.step3();
			};
		});
	},
	step1: function()
	{
		app.setWizardStep(1);
		if (app.carMake.selected)
		{
			$("#vehicleInformation").hide().fadeIn("slow");
		}else
		{
			$("#liCarMake a").click(function()
			{
				app.chooseCarMake();
				return false;
			});
		}
	},
	step2: function()
	{
		app.setWizardStep(2);
		app.getFitType(app.carVariation.selected, app.carYearRange.selected, app.carYearExact.selected);
	},
	step3: function()
	{
		app.setWizardStep(3);
		app.getRoofRack(app.carVariation.selected, app.carYearRange.selected, app.fitType.selected, app.carYearExact.selected);
	},
	step4: function()
	{
		app.setWizardStep(4);
		app.getVehicleSummary(app.roofRack, app.carVariation.selected, app.carYearRange.selected, app.fitType.selected, app.barSpread, app.carYearExact.selected);
	},
	getFitType: function(carVariation, carYearRange, carYearExact)
	{
		if (app.fitType.items.length > 0)
		{
			app.stateChange({step:2});
			$("#fitType").hide().fadeIn("slow");
		}else
		{
			var loader = new dataloader($("#fitType"));
			app.dataManager.getFitType(carVariation, carYearRange, carYearExact, function(response)
			{
				if (response.status)
				{
					var rd = response.data;
					app.fitType.items = [];
					//show fit types
					$("#fitType").html('').hide();
					for (var i = 0, len = rd.length; i < len; i++)
					{
						if (rd[i].img != '')
							$("#fitType").append('<a href="#" ftid="' + rd[i].id + '"><img src="' + rd[i].img + '"/><span>' + rd[i].name + '</span></a>');
						else
							$("#fitType").append('<a href="#" ftid="' + rd[i].id + '" ftname="><span>' + rd[i].name + '</span></a>');
						$("#fitType a:last").data("name", rd[i].name);
						app.fitType.items.push(rd[i]);
					}
					$("#fitType a").click(function()
					{
						$("#fitType a").removeClass("selected");
						$(this).addClass("selected");
						app.fitType.selected = $(this).attr("ftid");
						app.fitType.name = $(this).data("name");
						app.vehicleSummary = null;
						app.roofRack = null;
						app.step3();
						return false;
					});
					$("#fitType").fadeIn("slow", function()
					{
						app.stateChange({step:2});
					});
				}
			}, loader);
		}
	},
	getRoofRack: function(carVariation, carYearRange, fitType, carYearExact)
	{
		if (app.roofRack)
		{
			$("#roofRack").hide().fadeIn("slow");
			app.stateChange({step:3, src:'init'});
		}else
		{
			var loader = new dataloader($("#roofRack"));
			$("#roofRack").show();
			app.dataManager.getRoofRacks(carVariation, carYearRange, fitType, carYearExact, function(response)
			{
				if (response.status)
				{
					var vh = response.data[0];
					$("#roofRack").hide().html('<p class="vehicle"><label>Vehicle:</label><span class="data"></span></p><p class="years"><label>Year Range:</label><span class="data"></span></p><p class="fit-type"><label>Fit Type:</label><span class="data"></span></p><p class="variant"><label>Variant:</label><span class="data"></span></p>');
					//render summary
					$("#roofRack")
						.find("p.vehicle span.data").html(vh.vehicle).end()
						.find("p.years span.data").html(vh.yearRange).end()
						.find("p.fit-type span.data").html(vh.fitType).end()
						.find("p.variant span.data").html(vh.variant);
					//render items
					var vsi_t = '<div class="vehicle-summary-item"><p class="footpack"><label>Footpack:</label><span class="data"></span></p><p class="kit"><label>Kit:</label><span class="data"></span></p><p class="load-bar"><label>Load bar:</label><span class="data"></span></p><p class="bar-spread"><label>Bar Spread:</label><span class="data"></span></p><p class="product"><label>Product:</label><span class="data"></span></p><p class="button"><button>Select</button></p><div class="clear"></div></div>'
					$("#roofRack").find("div.vehicle-summary-item").remove();
					for (var i = 0, len = vh.items.length; i < len; i++)
					{
						var id = vh.items[i].id, barSpread = vh.items[i].barSpread;
						$(vsi_t).appendTo($("#roofRack"))
							.find("p.footpack span.data").html(vh.items[i].footPack).end()
							.find("p.kit span.data").html(vh.items[i].kit).end()
							.find("p.load-bar span.data").html(vh.items[i].loadBar).end()
							.find("p.bar-spread span.data").html(vh.items[i].barSpread).end()
							.find("p.product span.data").html(vh.items[i].product).end()
							.find("p.button button").click(function(id, barSpread)
							{
								return function()
								{
									app.roofRack = id;
									app.barSpread = barSpread;
									app.step4();
								};
							}(id, barSpread));
						var rrItem = $("#roofRack div.vehicle-summary-item:last");
						(vh.items[i].footPack == '') ? rrItem.find("p.footpack").hide() : true;
						(vh.items[i].kit == '') ? rrItem.find("p.kit").hide() : true;
						(vh.items[i].loadBar == '') ? rrItem.find("p.load-bar").hide() : true;
						(vh.items[i].barSpread == '') ? rrItem.find("p.bar-spread").hide() : true;
						(vh.items[i].product == '') ? rrItem.find("p.product").hide() : true;
					}
					//render accessories
					if (vh.accessories.length > 0) {
					    for (var i = 0, len = vh.accessories.length; i < len; i++) {
					        var category = $('<div class="roofRack-accessory"><h3>' + vh.accessories[i].name + '</h3></div>').appendTo($("#roofRack"));
					        var p_h = ['<ul>'];
					        for (var j = 0, len1 = vh.accessories[i].products.length; j < len1; j++)
					        {
								var fittips = [], fthtml = [];
								for (var k = 0, len2 = vh.accessories[i].products[j].fitTips.length; k < len2; k++)
								{
									fthtml.push('<p class="id">' + vh.accessories[i].products[j].fitTips[k].id + '</p><p class="description">' + vh.accessories[i].products[j].fitTips[k].description + '</p>');
								}
								fittips.push(vh.accessories[i].products[j].fitTips.length ? '<a href="#" class="fit-tip">i<div class="fittip-content">' + fthtml.join('') + '</div></a>' : '');
					            p_h.push('<li>' + vh.accessories[i].products[j].name + fittips.join('') + '</li>');
					        }
					        p_h.push('</ul>');
					        category.append(p_h.join(''));
					    }
					}
					$("#roofRack").fadeIn("slow").find("a.fit-tip").click(function()
					{
						fittipPopup.show($(this).find("div.fittip-content").html());
						return false;
					});
					app.stateChange({step:3, src:'init'});
				}
			}, loader);
		}
	},
	getVehicleSummary: function(roofRack, carVariation, carYearRange, fitType, barSpread, carYearExact)
	{
		var loader = new dataloader($("#vehicleSummary"));
		$("#vehicleSummary").show();
		app.dataManager.getVehicleSummary(roofRack, carVariation, carYearRange, fitType, barSpread, carYearExact, function(response)
		{
			if (response.status)
			{
				var vh = response.data[0];
				app.vehicleSummary = vh;
				$("#vehicleSummary").hide().html('<div class="vehicle-summary-item"><p class="vehicle"><label>Vehicle:</label><span class="data"></span></p><p class="years"><label>Year Range:</label><span class="data"></span></p><p class="fit-type"><label>Fit Type:</label><span class="data"></span></p><p class="variant"><label>Variant:</label><span class="data"></span></p><p class="footpack"><label>Footpack:</label><span class="data"></span></p><p class="kit"><label>Kit:</label><span class="data"></span></p><p class="load-bar"><label>Load bar:</label><span class="data"></span></p><p class="bar-spread"><label>Bar Spread:</label><span class="data"></span></p><p class="recommended-fairing"><label>Recommended Fairing:</label><span class="data"></span></p><p class="weight-limit"><label>Weight Limit:</label><span class="data"></span></p><p class="product"><label>Product:</label><span class="data"></span></p><p class="fit-kit-pdf"><label>Fit Kit PDF:</label><span class="data"><a href="#" class="pdf-icon" target="_new">Download</a></span></p><div class="clear"></div></div>');
				//render summary
				$("#vehicleSummary")
					.find("p.vehicle span.data").html(vh.vehicle).end()
					.find("p.years span.data").html(vh.yearRange).end()
					.find("p.fit-type span.data").html(vh.fitType).end()
					.find("p.variant span.data").html(vh.variant).end()
					.find("p.footpack span.data").html(vh.footPack).end()
					.find("p.kit span.data").html(vh.kit).end()
					.find("p.load-bar span.data").html(vh.loadBar).end()
					.find("p.bar-spread span.data").html(vh.barSpread).end()
					.find("p.recommended-fairing span.data").html(vh.fairingRecommendation).end()
					.find("p.weight-limit span.data").html(vh.weightLimit).end()
					.find("p.product span.data").html(vh.product).end()
					.find("p.fit-kit-pdf a").attr("href", vh.fitKitPDF);
				
				(vh.vehicle == '') ? $("#vehicleSummary").find("p.vehicle").hide() : true;
				(vh.yearRange == '') ? $("#vehicleSummary").find("p.years").hide() : true;
				(vh.fitType == '') ? $("#vehicleSummary").find("p.fit-type").hide() : true;
				(vh.variant == '') ? $("#vehicleSummary").find("p.variant").hide() : true;
				(vh.footPack == '') ? $("#vehicleSummary").find("p.footpack").hide() : true;
				(vh.kit == '') ? $("#vehicleSummary").find("p.kit").hide() : true;
				(vh.loadBar == '') ? $("#vehicleSummary").find("p.load-bar").hide() : true;
				(vh.barSpread == '') ? $("#vehicleSummary").find("p.bar-spread").hide() : true;
				(vh.fairingRecommendation == '') ? $("#vehicleSummary").find("p.recommended-fairing").hide() : true;
				(vh.weightLimit == '') ? $("#vehicleSummary").find("p.weight-limit").hide() : true;
				(vh.product == '') ? $("#vehicleSummary").find("p.product").hide() : true;
				(vh.fitKitPDF == '') ? $("#vehicleSummary").find("p.fit-kit-pdf").hide() : true;
				
				if (vh.fitTips.length > 0)
				{
					$("#vehicleSummary").append('<h2>Fit Tips</h2>');
					var vsft_t = '<div class="vehicle-summary-fit-tip"><p class="id"></p><p class="description"></p></div>';
					for (var i = 0, len = vh.fitTips.length; i < len; i++)
					{
						$(vsft_t).appendTo($("#vehicleSummary"))
							.find("p.id").html(vh.fitTips[i].id).end()
							.find("p.description").html(vh.fitTips[i].description);
					}
				}
				if (vh.fitImage != '')
				{
					$("#vehicleSummary").append('<h2>Fit Image</h2>');
					$('<img src="" class="fit-image" />').attr("src", vh.fitImage).appendTo($("#vehicleSummary"));
	            }
	            //render accessories
	            if (vh.accessories.length > 0)
	            {
	                $("#vehicleSummary").append('<h2>Compatible Carriers</h2>');
	                $("#vehicleSummary").append('Please review Fit Tips above to determine if adapters are required to fit the carriers listed');
					for (var i = 0, len = vh.accessories.length; i < len; i++)
					{
						var category = $('<div class="vehicle-summary-accessory"><h3>' + vh.accessories[i].name + '</h3></div>').appendTo($("#vehicleSummary"));
						var p_h = ['<ul>'];
						for (var j = 0, len1 = vh.accessories[i].products.length; j < len1; j++)
						{
							p_h.push('<li>' + vh.accessories[i].products[j].name + '</li>');
						}
						p_h.push('</ul>');
						category.append(p_h.join(''));
					}
	            }
	            /*if (vh.accessories.length > 0)
	            {
	                $("#vehicleSummary").append('<h2>Compatible Carriers</h2>');
	                var vsa_t = '<div class="vehicle-summary-accessory"><div class="image"><img src="" /></div><p class="sku"></p><p class="name"></p></div>';
	                for (var i = 0, len = vh.accessories.length; i < len; i++) {
	                    $(vsa_t).appendTo($("#vehicleSummary"))
								            .find("div.image img").attr("src", (vh.accessories[i].img == '') ? 'p-images/no-image.png' : vh.accessories[i].img).end()
								            .find("p.sku").html(vh.accessories[i].sku).end()
								            .find("p.name").html(vh.accessories[i].name);
	                }
	            }*/
				$("#vehicleSummary").fadeIn("slow");
				app.stateChange({step:4, src:'init'});
			}
		}, loader);
	},
	chooseCarMake: function()
	{
		app.hide();
		dropdown.activate({
			title:'Please choose car make',
			selected: app.carMake.selected,
			onCancel: function()
			{
				app.show();
			},
			onSelect: function(id)
			{
				app.carMake.selected = id;
				$("#liCarId, #liCarVariation, #liCarYearRange, #liCarYearExact").hide();
				app.resetData(app.carModel);
				app.resetData(app.carId);
				app.resetData(app.carVariation);
				app.resetData(app.carYearRange);
				app.resetData(app.carYearExact);
				var item = app.getById(id, app.carMake);
				$("#liCarMake").addClass("chosen").html('<div class="edit"><button>edit</button></div><div class="title">Car make</div><div class="value">' + item.text + '</div>');
				$("#liCarMake div.edit button").unbind().click(function()
				{
					app.chooseCarMake(app.carMake.selected);
				});
				app.show();
				//proceed to model
				$("#liCarModel")
					.removeClass()
					.html('<a href="#">Car model</a></li>')
					.show().
					find("a").click(function()
					{
						app.chooseCarModel();
						return false;
					});
				app.stateChange({step:1, src:'carMake'});
				app.setStatus({text:"car model"});
			},
			getter: function(callback, loader)
			{
				if (app.carMake.items.length > 0)
					callback(app.carMake.items);
				else
					app.dataManager.getCarMake(function(response)
					{
						if (response.status)
						{
							app.carMake.items = [];
							for (var i = 0, len = response.data.length; i < len; i++)
								app.carMake.items.push(response.data[i]);
							callback(response.data);
						}
					}, loader);
			}
		});
	},
	chooseCarModel: function()
	{
		app.hide();
		dropdown.activate({
			title:'Please choose car model', 
			selected: app.carModel.selected,
			onCancel: function()
			{
				app.show();
			},
			onSelect: function(id)
			{
				app.carModel.selected = id;
				$("#liCarVariation, #liCarYearRange, #liCarYearExact").hide();
				app.resetData(app.carId);
				app.resetData(app.carVariation);
				app.resetData(app.carYearRange);
				app.resetData(app.carYearExact);
				var item = app.getById(id, app.carModel);
				$("#liCarModel").addClass("chosen").html('<div class="edit"><button>edit</button></div><div class="title">Car model</div><div class="value">' + item.text + '</div>');
				$("#liCarModel div.edit button").unbind().click(function()
				{
					app.chooseCarModel(app.carModel.selected);
				});
				app.show();
				//proceed to id
				$("#liCarId")
					.removeClass()
					.html('<a href="#">Car id</a></li>')
					.show().
					find("a").click(function()
					{
						app.chooseCarId();
						return false;
					});
				app.stateChange({step:1, src:'carModel'});
				app.setStatus({text:"car id"});
			},
			getter: function(callback, loader)
			{
				if (app.carModel.items.length > 0)
					callback(app.carModel.items);
				else
					app.dataManager.getCarModel(app.carMake.selected, function(response)
					{
						if (response.status)
						{
							app.carModel.items = [];
							for (var i = 0, len = response.data.length; i < len; i++)
								app.carModel.items.push(response.data[i]);
							callback(response.data);
						}
					}, loader);
			}
		});
	},
	chooseCarId: function()
	{
		app.hide();
		dropdown.activate({
			title:'Please choose car id', 
			selected: app.carId.selected,
			onCancel: function()
			{
				app.show();
			},
			onSelect: function(id)
			{
				app.carId.selected = id;
				$("#liCarVariation, #liCarYearExact").hide();
				app.resetData(app.carVariation);
				app.resetData(app.carYearRange);
				app.resetData(app.carYearExact);
				var item = app.getById(id, app.carId);
				$("#liCarId").addClass("chosen").html('<div class="edit"><button>edit</button></div><div class="title">Car id</div><div class="value">' + item.text + '</div>');
				$("#liCarId div.edit button").unbind().click(function()
				{
					app.chooseCarId(app.carId.selected);
				});
				app.show();
				//proceed to year
				$("#liCarYearRange")
					.removeClass()
					.html('<a href="#">Car year range</a></li>')
					.show().
					find("a").click(function()
					{
						app.chooseCarYearRange();
						return false;
					});
				app.stateChange({step:1, src:'carId'});
				app.setStatus({text:"car variation"});
			},
			getter: function(callback, loader)
			{
				if (app.carId.items.length > 0)
					callback(app.carId.items);
				else
					app.dataManager.getCarId(app.carModel.selected, function(response)
					{
						if (response.status)
						{
							app.carId.items = [];
							for (var i = 0, len = response.data.length; i < len; i++)
								app.carId.items.push(response.data[i]);
							callback(response.data);
						}
					}, loader);
			}
		});
	},
	chooseCarVariation: function()
	{
		app.hide();
		dropdown.activate({
			title:'Please choose car variation', 
			selected: app.carVariation.selected,
			onCancel: function()
			{
				app.show();
			},
			onSelect: function(id)
			{
			    app.carVariation.selected = id;
				var item = app.getById(id, app.carVariation);
				$("#liCarVariation").addClass("chosen").html('<div class="edit"><button>edit</button></div><div class="title">Car variation</div><div class="value">' + item.text + '</div>');
				$("#liCarVariation div.edit button").unbind().click(function()
				{
					app.chooseCarVariation(app.carVariation.selected);
				});
				app.show();
				//proceed to 
				app.stateChange({step:1, src:'carVariation'});
			},
			getter: function(callback, loader)
			{
				if (app.carVariation.items.length > 0)
					callback(app.carVariation.items);
				else
					app.dataManager.getCarVariation(app.carYearRange.selected, function(response)
					{
						if (response.status)
						{
							app.carVariation.items = [];
							for (var i = 0, len = response.data.length; i < len; i++)
								app.carVariation.items.push(response.data[i]);
							callback(response.data);
						}
					}, loader);
			}
		});
	},
	chooseCarYearRange: function()
	{
		app.hide();
		dropdown.activate({
			title:'Please choose car year range',
			selected: app.carYearRange.selected,
			onCancel: function()
			{
				app.show();
			},
			onSelect: function(id)
			{
			    app.carYearRange.selected = id;
			    $("#liCarVariation").hide();
				app.resetData(app.carVariation);
				app.resetData(app.carYearExact);
				var item = app.getById(id, app.carYearRange);
				$("#liCarYearRange").addClass("chosen").html('<div class="edit"><button>edit</button></div><div class="title">Car year range</div><div class="value">' + item.text + '</div>');
				$("#liCarYearRange div.edit button").unbind().click(function()
				{
					app.chooseCarYearRange(app.carYearRange.selected);
				});
				app.show();
				$("#liCarYearExact")
					.removeClass()
					.html('<a href="#">Car year</a></li>')
					.show().
					find("a").click(function()
					{
						app.chooseCarYearExact();
						return false;
					});
				app.stateChange({step:1, src:'carYearRange'});
			},
			getter: function(callback, loader)
			{
				if (app.carYearRange.items.length > 0)
					callback(app.carYearRange.items);
				else
					app.dataManager.getCarYearRange(app.carId.selected, function(response)
					{
						if (response.status)
						{
							app.carYearRange.items = [];
							for (var i = 0, len = response.data.length; i < len; i++)
								app.carYearRange.items.push(response.data[i]);
							callback(response.data);
						}
					}, loader);
			}
		});
	},
	chooseCarYearExact: function()
	{
		app.hide();
		dropdown.activate({
			title:'Please choose car year', 
			selected: app.carYearExact.selected,
			onCancel: function()
			{
				app.show();
			},
			onSelect: function(id)
			{
				app.carYearExact.selected = id;
				var item = app.getById(id, app.carYearExact);
				$("#liCarYearExact").addClass("chosen").html('<div class="edit"><button>edit</button></div><div class="title">Car year</div><div class="value">' + item.text + '</div>');
				$("#liCarYearExact div.edit button").unbind().click(function()
				{
					app.chooseCarYearExact(app.carYearExact.selected);
				});
				app.show();
				app.stateChange({step:1, src:'carYearExact'});
				$("#liCarVariation")
					.removeClass()
					.html('<a href="#">Car variation</a></li>')
					.show().
					find("a").click(function()
					{
						app.chooseCarVariation();
						return false;
					});
			},
			getter: function(callback, loader)
			{
				if (app.carYearExact.items.length > 0)
					callback(app.carYearExact.items);
				else
					app.dataManager.getCarYearExact(app.carYearRange.selected, function(response)
					{
						if (response.status)
						{
							app.carYearExact.items = [];
							for (var i = 0, len = response.data.length; i < len; i++)
								app.carYearExact.items.push(response.data[i]);
							callback(response.data);
						}
					}, loader);
			}
		});
	},
	dataManager:
	{
		keys: {},
		xhrs: {},
		active: false,
		getCarMake: function(callback, loader)
		{
			this.processRequest("getCarMake", app.config.dataUrl, {action: "getCarMake"}, callback, loader);
		},
		getCarModel: function(carMake, callback, loader)
		{
			this.processRequest("getCarModel", app.config.dataUrl, {action: "getCarModel", carMake: carMake}, callback, loader);
		},
		getCarId: function(carModel, callback, loader)
		{
			this.processRequest("getCarId", app.config.dataUrl, {action: "getCarId", carModel: carModel}, callback, loader);
		},
		getCarYearRange: function(carId, callback, loader)
		{
			this.processRequest("getCarYearRange", app.config.dataUrl, {action: "getCarYear", carId: carId}, callback, loader);
		},
		getCarVariation: function(carYearRange, callback, loader)
		{
			this.processRequest("getCarVariation", app.config.dataUrl, {action: "getCarVariation", carYear: carYearRange}, callback, loader);
		},
		//getCarYearExact: function(carVariation, carYearRange, callback, loader)
		getCarYearExact: function(carYearRange, callback, loader)
		{
			this.processRequest("getCarYearExact", app.config.dataUrl, {action: "getCarYearExact", carVariation: '', carYear: carYearRange}, callback, loader);
		},
		getFitType: function(carVariation, carYearRange, carYearExact, callback, loader)
		{
			this.processRequest("getFitType", app.config.dataUrl, {action: "getFitType", carVariation: carVariation, carYear: carYearRange, carYearExact: carYearExact}, callback, loader);
		},
		getRoofRacks: function(carVariation, carYearRange, fitType, carYearExact, callback, loader)
		{
			this.processRequest("getRoofRacks", app.config.dataUrl, {action: "getRoofRacks", carVariation: carVariation, carYear: carYearRange, fitType: fitType, carYearExact: carYearExact}, callback, loader);
		},
		getVehicleSummary: function(roofRack, carVariation, carYearRange, fitType, barspread, carYearExact, callback, loader)
		{
			this.processRequest("getVehicleSummary", app.config.dataUrl, {action: "getVehicleSummary", roofRack: roofRack, carVariation: carVariation, carYear: carYearRange, fitType: fitType, barspread: barspread, carYearExact: carYearExact}, callback, loader);
		},
		processRequest: function(key, url, postData, callback, loader)
		{
			
			var that = this;
			if ((typeof(loader) != "undefined") && loader)
			{
				this.active = true;
				loader.activate();
			}
			var reqCallback = function(data)
			{
				this.active = false;
				callback(data);
				if (typeof(loader) != "undefined" && loader)
					loader.deactivate();
			};
			this.sendRequest(key, url, postData, reqCallback);
			return true;
		},
		registerRequest: function(key, reqCallback)
		{
			if (typeof(this.keys[key]) == "undefined")
				this.keys[key] = 1;
			else
				this.keys[key]++;
			reqCallback.id = key;
			reqCallback.index = this.keys[key];
		},
		unregisterRequest: function(key)
		{
			delete this.keys[key];
		},
		checkLatestRequest: function(callback)
		{
			return this.keys[callback.id] == callback.index;
		},
		sendRequest: function(key, url, postData, callback)
		{
			var that = this;
			this.registerRequest(key, callback);
			postData.hiddenSender = "ajax";
			if (key.indexOf("get") == 0)
			{
				if (typeof(this.xhrs[key]) != "undefined")
				{
					for (var item in this.xhrs)
						this.xhrs[item].abort();
					//this.xhrs[key].abort();
				}
			};
			if (app.config.dataProviderType == "php")
				this.xhrs[key] = $.ajax(
				{
					type: "POST",
					url: url,
					data: postData,
					dataType: "json",
					success: function(data)
					{
						if (that.checkLatestRequest(callback))
						{
							that.unregisterRequest(callback.id);
							callback(data);
						}
					}
				});
			else if (app.config.dataProviderType == "asp.net")
			{
				var url = url + "/" + postData.action;
				delete postData.action;
				this.xhrs[key] = $.ajax(
				{
					type: "POST",
					url: url,
					data: JSON.stringify(postData),
					contentType: "application/json; charset=utf-8",
					dataType: "json",
					success: function(data)
					{
						if (that.checkLatestRequest(callback))
						{
							that.unregisterRequest(callback.id);
							callback(JSON.parse(data.d));
						}
					}
				});
			}
		}
	}
};
dataloader = function(target)
{
	var that = this;
	this.target = target;
	this.active = false;
	this.activate = function(options)
	{
		this.target.html('<div class="loading"><p>loading data...</p></div>');
		this.active = true;
	};
	this.deactivate = function(options)
	{
		this.target.find("div.loading").remove();
		this.active = false;
	};
};
