///////////////////////////////////////
// HashMap Implementation            //
///////////////////////////////////////
(function($) {
	function hexToDec(hex) {
		switch (hex.toUpperCase()) {
			case '0': return 0;
			case '1': return 1;
			case '2': return 2;
			case '3': return 3;
			case '4': return 4;
			case '5': return 5;
			case '6': return 6;
			case '7': return 7;
			case '8': return 8;
			case '9': return 9;
			case 'A': return 10;
			case 'B': return 11;
			case 'C': return 12;
			case 'D': return 13;
			case 'E': return 14;
			case 'F': return 15;
		}
	}
	
	function getFontColor(bgColor) {
		var rgb = new Array();
		rgb.push(bgColor.substr(0, 2));
		rgb.push(bgColor.substr(2, 2));
		rgb.push(bgColor.substr(4, 2));
		
		for (var i=0; i < rgb.length; i++) {
			var first = hexToDec(rgb[i].substr(0, 1));
			var sec = hexToDec(rgb[i].substr(1, 1));
			rgb[i] = first*256 + sec;
		};
		
		var average = Math.round((rgb[0] + rgb[1] + rgb[2]) / 3);
		
		if (average <= 128) {
			return "FFFFFF";
		} else {
			return "000000";
		}
	}
	
	
	if (typeof $.Shfr == "undefined") {
		$.Shfr = {};
	}
	
	$.Shfr.Cookie = {};
	$.extend($.Shfr.Cookie, {
		set: function(c_name, value, expiredays) {
			if (typeof c_name == "undefined") {
				return;
			}
			var exdate = new Date();
			exdate.setDate(exdate.getDate() + expiredays);
			document.cookie = c_name+ "=" + escape(value) + ((expiredays==null) ? "" : ";expires=" + exdate.toGMTString());
		},
		
		get: function(c_name) {
			if (document.cookie.length > 0) {
				c_start=document.cookie.indexOf(c_name + "=");
				if (c_start != -1) {
					c_start = c_start + c_name.length + 1;
					c_end = document.cookie.indexOf(";", c_start);
					if (c_end == -1) {
						c_end = document.cookie.length;
					}
					return unescape(document.cookie.substring(c_start, c_end));
				}
			}
			return null;
		}
	});
	
	/*
	 * Klasse um String-Keys auf Werte zu mappen.
	 */
	$.Shfr.HashMap = function() {
		this.data = {};
	}

	$.extend($.Shfr.HashMap.prototype, {
		put: function(key, value) {
			this.data[key] = value;
		},

		get: function(key) {
			return typeof this.data[key] == "undefined" ? null : this.data[key];
		},

		remove: function(key) {
			delete this.data[key];
		},
		
		/*
		 * Gibt ein Array mit allen Keys zurück.
		 */
		keySet: function() {
			var result = new Array();
			jQuery.each(this.data, function(key, value) {
				result.push(key);
			});
			return result;
		},
		
		/*
		 * Gibt ein Array mit allen Werten zurück.
		 */
		values: function() {
			var result = new Array();
			jQuery.each(this.data, function(key, value) {
				result.push(value);
			});
			return result;
		},
		
		/*
		 * Löscht alle Einträge in dieser Map
		 */
		clear: function() {
			this.data = {};
		},
		
		isEmpty: function() {
			var keys = this.keySet();
			return keys.length == 0
		},
		
		toJSON: function() {
			return $.toJSON(this.data);
		}
	});
	
	$.fn.mouseOutHide = function(options) {
		var defaults = {};
		$.extend(defaults, options);
		
		console.log(defaults);
		
		var mouseHandler = function(e) {
			console.log(e);
		}
		$("html").bind("mousemove", mouseHandler);
	}
	
	/**
	 * Class Datastore
	 *
	 */
	$.Shfr.Datastore = function(container_id) {
		this.id = container_id;
		this.data = new $.Shfr.HashMap();
		this.load();
	}
	
	$.extend($.Shfr.Datastore.prototype, {
		persist: function() {
			var s = new Array();
			var keys = this.data.keySet();
			for (var i=0; i < keys.length; i++) {
				var d = this.data.get(keys[i]);
				s.push(keys[i] + ":" + d.join("-"));
			};
			
			var result = s.join("_");
			
			$.Shfr.Cookie.set(this.id, result, 1);
		},
		
		load: function() {
			var json = $.Shfr.Cookie.get(this.id);
			if (json == null || json == "") {
				return;
			}
			this.data.clear();
			var t = json.split("_");
			for (var i=0; i < t.length; i++) {
				var d = t[i].split(":");
				this.data.put(d[0], d[1].split("-"));
			};
		},
		
		get: function(key) {
			return this.data.get(key);
		},
		
		put: function(key, value) {
			this.data.put(key, value);
			this.persist();
		},
		
		remove: function(key) {
			this.data.remove(key);
			this.persist();
		},
		
		clear: function() {
			this.data.clear();
			$.Shfr.Cookie.set(this.id, "", -3600);
		}
		
	});
	
	
	var activePin = null;
	/**
	 * Class Partner
	 *
	 */
	$.Shfr.Partner = function(data) {
		this.id = data.id;
		this.posid = data.posid;
		this.label = data.label;
		this.x = data.x;
		this.y = data.y;
		this.price = data.price;
		this.region = data.region;
		this.categories = data.categories;
		
		this.x = this.x - 77;
		this.y = this.y - 21;
		this.visible = true;
		
		var $this = this;
		
		this.infobox = $("<div class=\"map-infobox\"></div>")
			.hide()
			.css("position", "absolute")
			.css("left", this.x + "px")
			.css("top", this.y - 58 + "px")
			.css("z-index", "999")
			.appendTo("#map-main");
		this.infobox_main = $("<div class=\"map-infobox-main\"><strong>"+this.label+", "+this.posid+"</strong><br /></div>").appendTo(this.infobox);
		this.infobox_arrow = $("<div class=\"map-infobox-arrow\"></div>").appendTo(this.infobox);
		this.infobox.css("left", this.x - (this.infobox.width()/2));
		this.infobox.css("top", this.y - (this.infobox.height()+1));
		
		var navBox = $("<div></div>").css("margin-top", "5px").css("height", "20px").appendTo(this.infobox_main);
		var infolink = $("<a class=\"map_button\" href=\"attraktionen/details.php?id="+this.id+"\">info</a>").appendTo(navBox)
			.css("cursor", "pointer").colorbox({innerWidth:450, height:"75%"}).css("float", "right");
		var merken = $("<a class=\"map_button\" href=\"#\">merken</a>").click(function(e) {
				$.Shfr.MainInstance.watchList.add($this);
				return false;
			}).appendTo(navBox)
			.css("cursor", "pointer")
			.css("float", "left");
		
		
		this.pin = $("<div class=\"map-pin\"></div>");
		this.pin.hover(
			function(e) {
				if (activePin != null) {
					activePin.pin.css("background-position", "-"+((activePin.posid-1)*15)+"px 0px").css("z-index", activePin.posid);
					activePin.infobox.hide();
					activePin = null;
				}
				$this.pin.css("background-position", "-"+(($this.posid-1)*15)+"px -15px").css("z-index", "1000");
				$this.infobox.show();
				$this.infobox.css("left", $this.x - ($this.infobox.outerWidth()/2));
				$this.infobox.css("top", $this.y - ($this.infobox.outerHeight() + 8));
				activePin = $this;
				return false;
			}, function(e) {
				$this.pin.css("background-position", "-"+(($this.posid-1)*15)+"px 0px").css("z-index", $this.id);
			});
		this.pin.css("left", this.x - 8 + "px")
			.css("top", this.y - 8 + "px")
			.css("background-image", "url(attraktionen/numbers.png)")
			.css("background-repeat", "no-repeat")
			.css("background-position", "-"+(($this.posid-1)*15)+"px 0px");
		this.pin.appendTo("#map-main");
		
		var exitFunction = function(e) {
			if (activePin != null) {
				activePin.pin.css("background-position", "-"+((activePin.posid-1)*15)+"px 0px").css("z-index", $this.id);
				activePin.infobox.hide();
				activePin = null;
			}
		};
		$("#map-main").click(exitFunction);
	}
	
	$.extend($.Shfr.Partner.prototype, {
		applyFilter: function(regions, categories) {
			var hasRegion = regions.length == 0;
			var hasCat = categories.length == 0;
			for (var i = regions.length - 1; i >= 0; i--){
				if (this.region == regions[i]) {
					hasRegion = true;
					break;
				}
			};
			
			for (var i = categories.length - 1; i >= 0; i--){
				for (var j = this.categories.length - 1; j >= 0; j--){
					if (this.categories[j] == categories[i]) {
						hasCat = true;
						break;
					}
					if (hasCat) {
						break;
					}
				};
			};
			
			if (hasRegion && hasCat) {
				this.show();
			} else {
				this.hide();
			}
		},
		
		show: function() {
			if (!this.visible) {
				this.pin.fadeIn("normal");
				if (activePin == this) {
					this.infobox.fadeIn("normal");
				}
				this.visible = true;
			}
		},
		
		hide: function() {
			if (this.visible) {
				this.pin.fadeOut("normal");
				if (activePin == this) {
					this.infobox.fadeOut("normal");
				}
				this.visible = false;
			}
		}
	});
	
	/**
	 * Class RegionList
	 *
	 */
	$.Shfr.RegionList = function(regions) {
		this.data = new Array();
		this.selected = new $.Shfr.HashMap();
		this.elements = new $.Shfr.HashMap();
		var $this = this;
		$("#map-regList li:first").click(function(e) {
			$this.selected.clear();
			$this.update();
		});
		regions.each(function(e) {
			var element = $("<li>" +  e.label.replace(/\//g, "/") + "</li>");
			element.data("id", e.id).click(function(e) {
				$this.handleClick($(this).data("id"));
			});
			element.appendTo("#map-regList");
			$this.data.push(e);
			$this.elements.put(e.id, element);
		});
	}
	
	$.extend($.Shfr.RegionList.prototype, {
		handleClick: function(id) {
			if (this.selected.get(id) != null) {
				this.selected.remove(id);
			} else {
				this.selected.put(id, true);
			}
			this.update();
		},
		
		update: function() {
			var el = this.elements.keySet();
			var sel = this.selected.keySet();
			if (sel.length == 0) {
				$("#map-regList li").removeClass("active");
				$("#map-regList li:first").addClass("active");
			} else {
				$("#map-regList li:first").removeClass("active");
				for (var i=0; i < el.length; i++) {
					if (this.selected.get(el[i]) != null) {
						this.elements.get(el[i]).addClass("active");
					} else {
						this.elements.get(el[i]).removeClass("active");
					}
				};
			}
			$.Shfr.MainInstance.setRegFilter(sel);
			$.Shfr.MainInstance.applyFilter();
		}
	});
	
	/**
	 * Class CategoryList
	 *
	 */
	$.Shfr.CategoryList = function(categories) {
		this.data = new Array();
		this.selected = new $.Shfr.HashMap();
		this.elements = new $.Shfr.HashMap();
		var $this = this;
		$("#map-catList li:first").click(function(e) {
			$this.selected.clear();
			$this.update();
		});
		categories.each(function(e) {
			var element = $("<li>" + e.label.replace(/\//g, "/") + "</li>");
			if (e.highlight != null) {
				element
					.css("background-color", "#" + e.highlight)
					.css("color", "#" + e.highlight_text)
					.data("highlight", e.highlight)
					.data("highlight_text", e.highlight_text);
			}
			element.data("id", e.id).click(function(e) {
				$this.handleClick($(this).data("id"));
			});
			element.appendTo("#map-catList");
			$this.data.push(e);
			$this.elements.put(e.id, element);
		});
	}
	
	$.extend($.Shfr.CategoryList.prototype, {
		handleClick: function(id) {
			if (this.selected.get(id) != null) {
				this.selected.remove(id);
			} else {
				this.selected.put(id, true);
			}
			this.update();
		},
		
		update: function() {
			var el = this.elements.keySet();
			var sel = this.selected.keySet();
			if (sel.length == 0) {
				$("#map-catList li").removeClass("active");
				$("#map-catList li").each(function(e) {
					var data = $(this).data("highlight");
					var data2 = $(this).data("highlight_text");
					if (data != null) {
						$(this)
							.css("background-color", "#" + data)
							.css("color", "#" + data2);
					}
				});
				$("#map-catList li:first").addClass("active");
			} else {
				$("#map-catList li:first").removeClass("active");
				for (var i=0; i < el.length; i++) {
					var element = this.elements.get(el[i]);
					if (this.selected.get(el[i]) != null) {
						element.addClass("active");
						var data = element.data("highlight");
						if (data != null) {
							element
								.css("background-color", "")
								.css("color", "");
						}
					} else {
						element.removeClass("active");
						var data = element.data("highlight");
						var data2 = element.data("highlight_text");
						if (data != null) {
							element
								.css("background-color", "#" + data)
								.css("color", "#" + data2);
						}
					}
				};
			}
			$.Shfr.MainInstance.setCatFilter(sel);
			$.Shfr.MainInstance.applyFilter();
		}
	});
	
	/**
	 * Class WatchList
	 *
	 */
	$.Shfr.WatchList = function() {
		this.htmlList = $("<table></table>")
			.addClass("map-watchListTable");
		$("#map-watchlist-list").append(this.htmlList);
		$("#map-watchlist").hide();
		this.calculator = $("<div></div>")
			.css("position", "absolute")
			.css("top", "0px")
			.css("left", "0px")
			.css("width", "100%")
			.css("height", "100%")
			.css("overflow", "auto")
			.css("z-index", "100")
			.css("background-color", "#FFF");
		this.calculatorActive = false;
		this.isHidden = true;
		this.selected = new $.Shfr.HashMap();
		var $this = this;
		$('input[name="map-delete"]').click(function(e) {
			$this.clear();
		});
		
		$('input[name="map-print"]').click(function(e) {
			window.open("merkliste.php?cardtype=0&entries=" + $this.selected.keySet().join("-"));
		});
		
		$('input[name="map-route"]').click(function(e) {
			window.location.href = "attraktionen_routenplaner.php";
		});
		
		$('input[name="map-calc"]').click(function(e) {
			var link = $("<a href='dataHandler.php?mode=show&id=calculation&centries="+$this.selected.keySet().join("-")+"'></a>");
			link.colorbox({width:450, height:"75%"}).click();
			/*
			$this.calculator.empty();
			$this.calculator.remove();
			$this.calculatorActive = true;
			$this.calculator.appendTo("#map-main")
				.load("dataHandler.php", { 'mode': "show", 'id': "calculation", 'centries': $this.selected.keySet().join("-") }, function() {
					$("#map-calculator-close").click(function(e) {
						$this.calculatorActive = false;
						$this.calculator.empty();
						$this.calculator.remove();
					});
				});*/
		});
		
		var pData = $.Shfr.MainInstance.datastore.get("watchlist");
		if (pData != null) {
			for (var i=0; i < pData.length; i++) {
				var p = $.Shfr.MainInstance.partnerList.get(pData[i]);
				if (p != null) {
					this.add(p, false);
				}
			};
		}
	}
	
	$.extend($.Shfr.WatchList.prototype, {
		add: function(partner, save) {
			if (this.selected.get(partner.id) == null) {
				var price = new Number(partner.price.replace(/,/, "."));
				var html = $("<tr><td>" + partner.label + "</td><td class=\"map-priceLabel\" align=\"right\">" + price.toFixed(2).toString().replace(/\./g, ',') + " &euro;</td><td width=\"15\" align=\"right\"></td></tr>");
				var deleteButton = $("<img src=\"layoutpics/close.gif\" />")
					.data("partner", partner)
					.data("watchList", this)
					.click(function(e) {
						$(this).data("watchList").remove($(this).data("partner"));
					});
				html.children("td:last").append(deleteButton);
				this.selected.put(partner.id, {"partner": partner, "html": html});
				html.appendTo(this.htmlList);
				
				if (this.isHidden) {
					$("#map-watchlist").show();
					this.isHidden = false;
				}
				
				if (save == null || save) {
					this.save();
				}
			}
		},
		
		refreshCalculator: function() {
			if (this.calculatorActive) {
				var $this = this;
				this.calculator.empty().load("dataHandler.php", { 'mode': "show", 'id': "calculation", 'centries': $this.selected.keySet().join("-") }, function() {
					$("#map-calculator-close").click(function(e) {
						$this.calculatorActive = false;
						$this.calculator.empty();
						$this.calculator.remove();
					});
				});
			}
		},
		
		closeCalculator: function() {
			if (this.calculatorActive) {
				this.calculatorActive = false;
				this.calculator.empty();
				this.calculator.remove();
			}
		},
		
		save: function() {
			var keys = this.selected.keySet();
			$.Shfr.MainInstance.datastore.put("watchlist", keys);
		},
		
		remove: function(partner, save) {
			var p = this.selected.get(partner.id);
			if (p != null) {
				p.html.remove();
				this.selected.remove(partner.id);
			}
			
			if (!this.isHidden && this.selected.keySet().length == 0) {
				$("#map-watchlist").hide();
				this.isHidden = true;
			}
			if (save == null || save) {
				this.save();
			}
			this.refreshCalculator();
		},
		
		clear: function() {
			var keys = this.selected.keySet();
			for (var i = keys.length - 1; i >= 0; i--){
				this.remove({id:keys[i]}, false);
			};
			$.Shfr.MainInstance.datastore.remove("watchlist");
			this.closeCalculator();
		}
	});
	
	$.Shfr.ExtraPartner = function() {
		this.catData = [
			{
				id: "kd",
				label: "KD",
				pinImg: "kd-logo.png",
				href: "http://www.k-d.com/",
				detailId: -1,
				pinLocs: [
					{x: 242, y: 273}, // Cockem
					{x: 329, y: 200}, // Koblenz
					{x: 345, y: 286}, // St. Goar
					{x: 365, y: 327}  // Bingen
				]
			},
			{
				id: "dtm",
				label: "DTM",
				pinImg: "dtm-logo.png",
				href: "http://www.dtm.com/rennen.php?rennen=2010-08-08",
				detailId: -2,
				pinLocs: [
					{x: 202, y: 207} // Nürburgring
				]
			}
		];
		this.createPins();
		this.createMenuBox();
	}
	
	$.extend($.Shfr.ExtraPartner.prototype, {
		createPins: function() {
			this.pins = new $.Shfr.HashMap();
			for (var i=0; i < this.catData.length; i++) {
				var cat = this.catData[i];
				var pinList = new Array();

				for (var j=0; j < cat.pinLocs.length; j++) {
					var pinLoc = cat.pinLocs[j];
					var pin = $("<div></div>");
					pin.attr("id", cat.id + "-" + j)
						.css("background-image", "url(attraktionen/" + cat.pinImg + ")")
						.css("width", "15px")
						.css("height", "15px")
						.css("position", "absolute")
						.css("top", (pinLoc.y-7) + "px")
						.css("left", (pinLoc.x-7) + "px")
						.css("cursor", "pointer")
						.data("href", cat.href)
						.data("detailId", cat.detailId)
						.click(function(e) {
							//window.open($(this).data("href"), "_blank");
							$.fn.colorbox({innerWidth:450, height:"75%", href:"attraktionen/details.php?id=" + $(this).data("detailId")});
						});
					pin.appendTo("#map-main");
					pinList.push(pin);
				};

				this.pins.put(cat.id, pinList);
			};
		},
		
		createMenuBox: function() {
			var $this = this;
			for (var i=0; i < this.catData.length; i++) {
				var cat = this.catData[i];
				var but = $("<li>" + cat.label + "</li>");
				but.data("cat", cat.id).click(function(e) {
					$("#map-extraList li").removeClass("active");
					$(this).addClass("active");
					$this.showPins($(this).data("cat"));
				});
				but.appendTo("#map-extraList");
			}
			$("#map-extraList li:first").click(function(e) {
				$("#map-extraList li").removeClass("active");
				$(this).addClass("active");
				$this.showPins(null);
			});
		},
		
		showPins: function(catId) {
			var catIds = this.pins.keySet();
			
			for (var i=0; i < catIds.length; i++) {
				var pins = this.pins.get(catIds[i]);
				if (null == catId || catIds[i] == catId) {
					for (var j=0; j < pins.length; j++) {
						pins[j].fadeIn("normal")
					}
				} else {
					for (var j=0; j < pins.length; j++) {
						pins[j].fadeOut("normal")
					}
				}
			};
		}
	});
	
	/**
	 * Class Main
	 *
	 */
	$.Shfr.Main = function() {
		this.partnerList = new $.Shfr.HashMap();
		this.categoryList = null;
		this.regionList = null;
		this.watchList = null;
		
		this.regsFilter = new Array();
		this.catsFilter = new Array();
		
		this.datastore = new $.Shfr.Datastore("rlp-map");
		
		/*var startTop = $("#map-main").offset().top;
		$(window).scroll(function (e) {
			var top = $(window).scrollTop() - startTop + 30;
			if (top < 30) {
				top = 30;
			}
			if ($("body").height() - (710+startTop) < top) {
				top = $("body").height() - (710+startTop);
			}
			$("#map-main").css("top", top + "px");
		});*/
	}
	
	$.extend($.Shfr.Main.prototype, {
		init: function() {
			this.initPartners();
			this.initExtraPartners();
			this.initWatchList();
			this.initRegionList();
			this.initCategoryList();
			
			$("#map-help").colorbox({innerHeight:400, innerWidth: 400});
			$("#map-saarvv").colorbox({innerWidth:450, height:"75%"});
		},
		
		initWatchList: function() {
			this.watchList = new $.Shfr.WatchList();
		},
		
		initRegionList: function() {
			this.regionList = new $.Shfr.RegionList(mapStartData.regionen);
		},
		
		initCategoryList: function() {
			this.categoryList = new $.Shfr.CategoryList(mapStartData.arten);
		},
		
		initPartners: function() {
			var partners = mapStartData.partners;

			for (var i=0; i < partners.length; i++) {
				this.partnerList.put(partners[i].id, new $.Shfr.Partner(partners[i]));
			};
		},
		
		initExtraPartners: function() {
			this.extraPartners = new $.Shfr.ExtraPartner();
		},
		
		applyFilter: function() {
			var keys = this.partnerList.keySet();
			for (var i=0; i < keys.length; i++) {
				this.partnerList.get(keys[i]).applyFilter(this.regsFilter, this.catsFilter);
			};
		},
		
		setCatFilter: function(cats) {
			this.catsFilter = cats;
		},
		
		setRegFilter: function(regs) {
			this.regsFilter = regs;
		}
	});
	
	$(document).ready(function() {
		$.Shfr.MainInstance = new $.Shfr.Main();
		$.Shfr.MainInstance.init();
	});
})(jQuery);