/*!
* jQuery Area Navigation Plugin v1.0.3
* 
* Copyright 2011, Serge Melnikov
* Licensed under the GPL Version 2 license.
*
* Based on jQuery Map Hilight Plugin 
* http://plugins.jquery.com/project/maphilight
*
* Date: Mon Jun 13 22:33:48 2011 +0100
*/ 
(function(jq) {
	
	var tooltipTypes = Array("none", "dynamic", "static");
	var highlightTypes = Array("none", "dynamic", "static");
	var tooltipClass = "infoTooltip";
	var imageContainerClass = "imageContainer";
	
	var mouseoverHighlightOptions = {
		"highlightClass": "mouseoverHighlight",
		"fill": true,
		"fillColor": "396280",
		"fillOpacity": 0.8,
		"stroke": true,
		"strokeColor": "2e4f66",
		"strokeOpacity": 0.8,
		"strokeWidth": 2,
		"fade": true
	};
	
	var clickHighlightOptions = {
		"highlightClass": "clickHighlight",
		"fill": true,
		"fillColor": '003366',
		"fillOpacity": 1,
		"stroke": true,
		"strokeColor": '003366',
		"strokeOpacity": 1,
		"strokeWidth": 2,
		"fade": true
	};
	
	Array.max = function( array ){
		return Math.max.apply( Math, array );
	};

	Array.min = function( array ){
		return Math.min.apply( Math, array );
	};
	
	var hasVML = document.namespaces;
	var hasCanvas = document.createElement('canvas');
	hasCanvas = hasCanvas && hasCanvas.getContext;
	
	var getShapeFromArea = function(area) {
		var i, coords = area.getAttribute('coords').split(',');
		for (i=0; i < coords.length; i++) { coords[i] = parseFloat(coords[i]); }
		return [area.getAttribute('shape').toLowerCase().substr(0,4), coords];
	}
	
	if (hasCanvas && !jq.browser.msie) {
		var fader = function(element, opacity, interval) {
			if(opacity <= 1) {
				element.style.opacity = opacity;
				window.setTimeout(fader, 10, element, opacity + 0.1, 10);
			}
		};
		
		var hexToDecimal = function(hex) {
			return Math.max(0, Math.min(parseInt(hex, 16), 255));
		};
		var css3color = function(color, opacity) {
			return 'rgba('+ hexToDecimal(color.substr(0,2)) +','+ hexToDecimal(color.substr(2,2)) +','+ hexToDecimal(color.substr(4,2)) +','+ opacity +')';
		};
		
		var createCanvas = function(img, canvasClass) {
			var canvas = jq('<canvas class="'+ canvasClass +'" style="width:'+img.width+'px;height:'+img.height+'px;"></canvas>').get(0);
			canvas.getContext("2d").clearRect(0, 0, canvas.width, canvas.height);
			return canvas;
		};
		
		var addShape = function(canvas, shape, coords, options) {
			var i, context = canvas.getContext('2d');
			context.beginPath();
			switch (shape) {
				case "rect":
					context.rect(coords[0], coords[1], coords[2] - coords[0], coords[3] - coords[1]);
				break;
				case "poly":
					context.moveTo(coords[0], coords[1]);
					for(i=2; i < coords.length; i+=2) {
						context.lineTo(coords[i], coords[i+1]);
					}
				break;
				case "circ":
					context.arc(coords[0], coords[1], coords[2], 0, Math.PI * 2, false);
				break;
			}
			context.closePath();
			if(options.fill) {
				context.fillStyle = css3color(options.fillColor, options.fillOpacity);
				context.fill();
			}
			if(options.stroke) {
				context.strokeStyle = css3color(options.strokeColor, options.strokeOpacity);
				context.lineWidth = options.strokeWidth;
				context.stroke();
			}
			if(options.fade) {
				fader(canvas, 0);
			}
		};
		
		var clearCanvas = function(canvas) {
			canvas.getContext('2d').clearRect(0, 0, canvas.width,canvas.height);
		};
	} else {
		var ss = document.createStyleSheet();
		ss.addRule("v\\:shape", "behavior:url(#default#VML); display:inline-block; antialias:true");
		ss.addRule("v\\:shape", "behavior:url(#default#VML); display:inline-block; antialias:true");
		ss.addRule("v\\:group", "behavior:url(#default#VML); display:inline-block; antialias:true");
		ss.addRule("v\\:polyline", "behavior:url(#default#VML); display:inline-block; antialias:true");
		ss.addRule("v\\:stroke", "behavior:url(#default#VML); display:inline-block; antialias:true");
		ss.addRule("v\\:fill", "behavior:url(#default#VML);	display:inline-block; antialias:true");
		ss.addRule("v\\:rect", "behavior:url(#default#VML);	display:inline-block; antialias:true");
		ss.addRule("v\\:oval", "behavior:url(#default#VML);	display:inline-block; antialias:true");
		document.namespaces.add("v", "urn:schemas-microsoft-com:vml"); 
		
		var createCanvas = function(img, canvasClass) {
			return jq('<var class="'+ canvasClass +'" style="zoom:1;overflow:hidden;display:block;width:'+img.width+'px;height:'+img.height+'px;"></var>').get(0);
		};
		
		var addShape = function(canvas, shape, coords, options) {
			var fill, stroke, opacity, element;
			fill = '<v:fill color="#'+options.fillColor+'" opacity="'+(options.fill ? options.fillOpacity : 0)+'" />';
			stroke = (options.stroke ? 'strokeweight="'+options.strokeWidth+'" stroked="t" strokecolor="#'+options.strokeColor+'"' : 'stroked="f"');
			opacity = '<v:stroke opacity="'+options.strokeOpacity+'"/>';
			switch (shape) {
				case "rect":
					element = jq('<v:rect filled="t" '+stroke+' style="zoom:1;margin:0;padding:0;display:block;position:absolute;left:'+coords[0]+'px;top:'+coords[1]+'px;width:'+(coords[2] - coords[0])+'px;height:'+(coords[3] - coords[1])+'px;"></v:rect>');
				break;
				case "poly":
					element = jq('<v:shape filled="t" '+stroke+' coordorigin="0,0" coordsize="'+canvas.width+','+canvas.height+'" path="m '+coords[0]+','+coords[1]+' l '+coords.join(',')+' x e" style="zoom:1;margin:0;padding:0;display:block;position:absolute;top:0px;left:0px;width:'+canvas.width+'px;height:'+canvas.height+'px;"></v:shape>');
				break;
				case "circ":
					element = jq('<v:oval filled="t" '+stroke+' style="zoom:1;margin:0;padding:0;display:block;position:absolute;left:'+(coords[0] - coords[2])+'px;top:'+(coords[1] - coords[2])+'px;width:'+(coords[2]*2)+'px;height:'+(coords[2]*2)+'px;"></v:oval>');
				break;
			}			
			element.get(0).innerHTML = fill+opacity;
			jq(canvas).append(element);
			return element;
		};
		
		var clearCanvas = function(canvas) {
			jq(canvas).empty();
		};
	}
	
	var getTime = function() {
		var dateObj = new Date();
		return dateObj.getTime();
	}
	
	var createTooltip = function(area, text) {
		var calculateCoordinates = function(area) {
			var coords = area.attr("coords").split(",");
			var coordsX = Array();
			var coordsY = Array();
			for (var i = 0; i < coords.length; i += 2) {
				coordsX[i/2] = coords[i];
				coordsY[i/2] = coords[i+1]; 
			}
			/*var maxX = Array.max(coordsX);
			var maxY = Array.max(coordsY);
			var minX = Array.min(coordsX);
			var minY = Array.min(coordsY);
			var coords = Object();
			coords.posx = (minX + maxX)/2;
			coords.posy = (minY + maxY)/2;*/
			i = 0;
			var coords = Object();
			var sumX = 0,sumY = 0;
			for (i in coordsX) sumX += parseInt(coordsX[i]);
			coords.posx = sumX/(parseInt(i)+1);
			for (i in coordsY) sumY += parseInt(coordsY[i]);
			coords.posy = sumY/(parseInt(i)+1);
			return coords;
		};
		
		var coords = calculateCoordinates(area);
		var tooltip = jq('<div style="display:none;" class="'+ tooltipClass +'"></div>')
						.css({
							"top" : coords.posy,
							"left" : coords.posx,
							"position" : "absolute",
							"z-index" : "999",
							"display" : "none",
							"margin" : "0px"
						});
		tooltip.append('<div class="text">'+ text +'</text>');
		area.closest(".areaNavigation").append(tooltip);
		return tooltip;
	}
	
	var initAreaHighlight = function(area, canvas, data) {
		if (typeof(data.highlightType) != "string") data.highlightType = highlightTypes[1];
		var shape = getShapeFromArea(area[0]);
		switch (data.highlightType) {
			case highlightTypes[1]:
				area.bind("mouseenter.highlight", function() {
					var element = addShape(canvas, shape[0], shape[1], typeof(data.mouseoverHighlightOptions) == "object" ? jq.extend(mouseoverHighlightOptions, data.mouseoverHighlightOptions) : mouseoverHighlightOptions);
				});
				area.bind("mouseleave.highlight", function() {
					clearCanvas(canvas);
				});
			break;
			case highlightTypes[2]:
				addShape(canvas, shape[0], shape[1], typeof(data.mouseoverHighlightOptions) == "object" ? jq.extend(mouseoverHighlightOptions, data.mouseoverHighlightOptions) : mouseoverHighlightOptions);
			break;
		}
		area.bind("click.highlight", function(e) {
			jq(this).parents("div.areaNavigation").showHighlight(data);
			if (typeof(data.click) == "function") data.click(data);
			e.stopPropagation();
		});
	}
	
	var initAreaTooltip = function(area, data) {
		var tooltip = createTooltip(area, data.name);
		if (typeof(data.tooltip["class"]) != "undefined") tooltip.addClass(data.tooltip["class"]);  

		if (typeof(data.tooltip.type) != "string") var tooltipType = tooltipTypes[1];
		else var tooltipType = data.tooltip.type;
		
		switch (tooltipType) {
			case tooltipTypes[1]:
				area.bind("mouseenter.tooltip", function(e) {
					tooltip.fadeIn("fast");
				});
				area.bind("mouseleave.tooltip", function(e) {
					tooltip.fadeOut("fast");
				});
			break;
			case tooltipTypes[2]:
				tooltip.fadeIn("fast");
				area.bind("mouseenter", function(e) {
					tooltip.addClass("tooltip_highlight");
					
				});
				area.bind("mouseleave", function(e) {
					tooltip.removeClass("tooltip_highlight");
				});
			break;
		}
	}
	
	var transition = function(areaNavigation, data) {
		areaNavigation.destroyMapNode();
		areaNavigation.initMapNode(data);
	}	
	
	var initAreaEvents = function(area, data) {
		var parentTag = area.closest(".areaNavigation");
		
		// Ugly Hack.
		var temporaryHook = function(area) {
			var name = area.attr("title");
			jq("input[value="+name+"]").siblings("ul").css("display", "block");
			jq("input[value="+name+"]").parent("li").removeClass("expandable");
			jq("input[value="+name+"]").parent("li").addClass("collapsable");
			jq("input[value="+name+"]").parent("li").siblings("li.worldPart").children("ul").css("display","none");
			jq("input[value="+name+"]").parent("li").siblings("li.worldPart").removeClass("collapsable");
			jq("input[value="+name+"]").parent("li").siblings("li.worldPart").addClass("expandable");
		}
		
		if (typeof(data.areaList) != "undefined" && typeof(data.img) != "undefined") {
			area.click( function() {
				transition(parentTag, data);
				temporaryHook(jq(this));
			});
		}
	}
	
	var searchTree = function(name, data) {
		for (var areaIndex in data) {
			if (data[areaIndex].name == name) return data[areaIndex];
			if (typeof(data[areaIndex].areaList) == "object") {
				var result = searchTree(name, data[areaIndex].areaList);
				if (result) return result;
			};
		} return false;
	}
	
	jq.fn.deactivateHighlight = function() {
		jq(this).find("area").each(function() {
			jq(this).unbind("mouseenter.highlight");
			jq(this).unbind("mouseleave.highlight");
			jq(this).unbind("click.highlight");
			jq(this).unbind("mouseenter.tooltip");
			jq(this).unbind("mouseleave.tooltip");
		});
	}
	
	jq.fn.showHighlight = function(data) {
		if (hasCanvas || hasVML) {
			var opt = typeof(data.clickHighlightOptions) == "object" ? jq.extend(clickHighlightOptions, data.clickHighlightOptions) : clickHighlightOptions;
			if (jq("canvas."+opt.highlightClass).length != 0 || jq("var."+opt.highlightClass).length != 0) {
				jq("canvas."+opt.highlightClass+", var."+opt.highlightClass).remove();
			}
			var img = jq(this).children("img");
			var canvas = createCanvas(img[0], opt.highlightClass);
			jq(canvas).css({
				position : 'absolute',
				left: 0,
				top: 0,
				padding: 0,
				border: 0
			});
			canvas.height = img.height();
			canvas.width = img.width();
			
			var i, coords = new String(data.coords);
			coords = coords.split(',');
			for (i=0; i < coords.length; i++) { coords[i] = parseFloat(coords[i]); }
			addShape(canvas, data.shape, coords, opt);
			img.before(canvas);
		}
	}
	
	jq.fn.navigateTo = function(nodeName) {
		var data = jq.fn.areaNavigation.data;
		var result = searchTree(nodeName, data);
		if (result) transition(jq(this), result);
	}
	
	jq.fn.destroyMapNode = function() {
		jq(this).children().remove();
	}
	
	jq.fn.navigateToParent = function(nodeName) {
		var data = jq.fn.areaNavigation.data;
		var nodeData = searchTree(nodeName, data);
		var parentData = searchTree(nodeData.parent, data);		
		if (parentData) transition(jq(this), parentData);
		jq("div.areaNavigation").showHighlight(nodeData);
	}
	
	jq.fn.initMapNode = function(node) {
		if (typeof(node) != "undefined") {
			/*var areaNavigation = jq(this);
			var mapID = "areaNavigation-"+ node.name +"-map";
			var map = jq('<map name="'+ mapID +'"></map>').css("z-index", "1000");
			areaNavigation.append(map);*/
			/*Workaround for the Safari Bug*/
			var areaNavigation = jq(this);
			var date = new Date();
			var MapIDPostfix = date.getTime();
			var mapID = "areaNavigation-"+ node.name +"-map-"+ MapIDPostfix;
			var map = document.createElement('map'); map.setAttribute('name', mapID); map.setAttribute('id', mapID); areaNavigation[0].appendChild(map);
			map = jq(map);
			map.css("z-index", "1000");
			
			var imgLoader = jq('<img src="'+ node.img +'" usemap="#'+ mapID +'" class="'+ imageContainerClass +'"></img>');
			jq.browser.msie ? imgLoader.css("filter", "Alpha(opacity=0)") : imgLoader.css("opacity", "0");
			areaNavigation.append(imgLoader);
						
			imgLoader.load(function() {
				var img = jq(this);
				//areaNavigation.append(img);
				var wrap = jq('<div class="'+ imageContainerClass +'">').css({
					display : 'none',
					background : 'url(' + img.attr("src") + ')',
					position : 'absolute',
					padding : 0,
					width : img.width(),
					height : img.height()
				});
				areaNavigation.prepend(wrap);
				if(jq.browser.msie) img.css('filter', 'Alpha(opacity=0)');
				img.css({
					'z-index' : 1000,
					position : 'absolute',
					padding: 0,
					border: 0,
					opacity: 0
				});
				wrap.fadeIn("slow", function() {
					if (hasCanvas || hasVML) {
						var canvas = createCanvas(img[0], mouseoverHighlightOptions["highlightClass"]);
						jq(canvas).css({
							position : 'absolute',
							left: 0,
							top: 0,
							padding: 0,
							border: 0
						});
						jq.browser.msie ? jq(canvas).css("filter", "Alpha(opacity=0.3)") : jq(canvas).css("opacity", "0.3");
						canvas.height = img.height();
						canvas.width = img.width();
					}
					
					for (var areaIndex in node.areaList) {
						if (typeof(node.areaList[areaIndex].shape != "undefined")) var shape = node.areaList[areaIndex].shape;
						else var shape = "poly";
						/*var area = jq('<area shape="'+ node.areaList[areaIndex].shape +'" coords="'+ node.areaList[areaIndex].coords +'">').css("cursor", "pointer");*/
						/* One more ugly workaround for Safari bug */
						var area = document.createElement('area');
						area = jq(area)
						area.attr({'shape':node.areaList[areaIndex].shape, 'coords':node.areaList[areaIndex].coords, 'title':node.areaList[areaIndex].name});
						map.append(area);
						initAreaTooltip(area, node.areaList[areaIndex]);
						if (canvas) initAreaHighlight(area, canvas, node.areaList[areaIndex]);
						initAreaEvents(area, node.areaList[areaIndex]);
					}
					if (canvas) img.before(canvas);
					jq(canvas).fadeIn("slow");
					/* Ugly and unprofessional, but hopefully just temporary solution. No time to implement a post initialization hook for external functions =( */
					var backToWorld = function(){
						if (jq("div.map").find("map[name*=World]").length > 0) {
							var test = jq("div.map").find("map[name=areaNavigation-World-map]");
							jq('div.backToWorld').hide();
						}
						else jq('div.backToWorld').show();  
					};
					backToWorld();
					var product = jq("div.search").find("select[name=product]").val();
					var worldPart = jq("div.search").find("select[name=area]").val();
					/* The countries should not be highlighted, while searching */
					if (worldPart != "all" || product!= "all") jq("div.areaNavigation").deactivateHighlight();
				});
			});
		}
	}
	
	jq.fn.areaNavigation = function() {
		var data = jq.fn.areaNavigation.data;
		jq(this).each(function() {
			var parentContainer = jq('<div></div>');
			parentContainer.css({
				"position" : "absolute",
				"left" : 0,
				"top" : 0,
				"padding" : 0,
				"border" : 0
			});
			jq(this).append(parentContainer);
			parentContainer.initMapNode(data[0]);
			parentContainer.addClass("areaNavigation");
		});
	}
	
})(jQuery);
