var $htmlmap=(function($){

	$config={
		'hasVML':document.namespaces,
		'hasCanvas':!!document.createElement('canvas').getContext,
		'isSupported':document.namespaces||!!document.createElement('canvas').getContext,
		'canvasStyle':{
			'position':'absolute',
			'left':0,
			'top':0,
			'padding':0,
			'border':0
		}
	}

	if(!$config.isSupported){
		$.fn.htmlmap=function(){
			return this;
		};
		return;
	}

fader=function(element, opacity, interval) {
	if(opacity <= 1) {
		element.style.opacity = opacity;
		window.setTimeout(fader, 10, element, opacity + 0.1, 10);
	}
};

	var $cache={},
		$active=false,
		$lib={
			'addShape':function(canvas, shape, coords, options, name){
				if($config.hasCanvas){
					var i, context = canvas.getContext('2d');
					context.beginPath();
					if(shape == 'rect') {
						context.rect(coords[0], coords[1], coords[2] - coords[0], coords[3] - coords[1]);
					}else if(shape == 'poly') {
						for(i=0; i < coords.length; i+=2) {
							context.lineTo(coords[i], coords[i+1]);
						}
					}else if(shape == 'circ') {
						context.arc(coords[0], coords[1], coords[2], 0, Math.PI * 2, false);
					}
					context.closePath();
					if(options.fill){this.fillShape(context,options.fill.color,options.fill.opacity);}
					if(options.stroke){this.strokeShape(context,options.stroke.color,options.stroke.opacity,options.stroke.width);}
					if(options.fade){fader(canvas,0);}
				}else{
					name = 'highlighted';
					var fill, stroke, opacity, e;
					fill = '<v:fill color="#'+options.fill.color+'" opacity="'+(options.fill ? options.fill.opacity : 0)+'" />';
					stroke = (options.stroke ? 'strokeweight="'+options.stroke.width+'" stroked="t" strokecolor="#'+options.stroke.color+'"' : 'stroked="f"');
					opacity = '<v:stroke opacity="'+options.stroke.opacity+'"/>';
					if(shape == 'rect'){
						e = $('<v:rect name="'+name+'" 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>');
					}else if(shape == 'poly'){
						e = $('<v:shape name="'+name+'" 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>');
					} else if(shape == 'circ'){
						e = $('<v:oval name="'+name+'" 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>');
					}
					e.get(0).innerHTML = fill+opacity;
					$(canvas).append(e);
				}
			},
			'clearCanvas':function(canvas,e,options){
				var td=$.data(e.target);
				var group=options.group && td['htmlmap.group'].name && (options.group instanceof Array?$.inArray(td['htmlmap.group'].name,options.group)<0:true);
				if(group){
					if(e.relatedTarget && e.relatedTarget.nodeName=='AREA'){
						if($.data(e.relatedTarget,'htmlmap.group').name==td['htmlmap.group'].name){return false;}
					}
				}
				if($config.hasCanvas){
					canvas.getContext('2d').clearRect(0, 0, canvas.width,canvas.height);
				}else{
					$(canvas).empty();
				}
				return true;
			},
			'createCanvas':function(width,height){
				if($config.hasCanvas){
					var c = $('<canvas style="width:'+width+'px;height:'+height+'px;"></canvas>').get(0);
					c.getContext("2d").clearRect(0, 0, c.width, c.height);
				}else{
					c = $('<var style="zoom:1;overflow:hidden;display:block;width:'+Math.round(width)+'px;height:'+Math.round(height)+'px;"></var>').get(0);
				}
					c.width=width;
					c.height=height;
				return c;
			},
			'createMap':function(object,name,options){
				object.attr('usemap','#'+name);
				var scale={'width':object.innerWidth()/options.base.width,'height':object.innerHeight()/options.base.height};
				var map = '<map name="'+name+'">';
				$.each($cache[options.scheme].canvas,function(k,v){
					$.each(v.coords,function(i,c){
						var coords=[];
						$.each(c,function(n,p){coords[coords.length]=(n%2==0)?Math.round(p*scale.width):Math.round(p*scale.height);});
						map += '<area coords="' + coords.join(', ') + '" shape="poly" title="' + k + '" href="'+ (v['url']?v.url:'') +'" />'
					});
				});
				map += '</map>';

				return $(map).find('area').each(function(){
					var g=false;
					var obj=$(this);
					var k=obj.attr('title');
					$.each($cache[options.scheme].groups,function(i,v){
						if($.inArray(k,v.keys)>=0){g={'name':i,'url':v.url};return false;}
					});
					obj.data({'htmlmap.key':k,'htmlmap.group':g}).addClass([k,g.name].join(' '));

					var item=$cache[options.scheme].canvas[k];
					obj.attr('title',(item['title']?item.title:k));

					if(options.group){
						if(options.group instanceof Array){
							if($.inArray(g.name,options.group)>=0){
								if(!obj.attr('href')){
									obj.removeAttr('href');
								}
							}else{
								if(g['url'] && g.url){
									obj.attr('href',g.url);
								}else{
									obj.removeAttr('href');
								}
							}
						}else{
							if(g['url'] && g.url){
								obj.attr('href',g.url);
							}else{
								obj.removeAttr('href');
							}
						}
					}
				}).end();
			},
			'fillShape':function(shape,color,opacity){
				var hex_to_decimal=function(hex){return Math.max(0, Math.min(parseInt(hex, 16), 255));};
				shape.fillStyle='rgba('+hex_to_decimal(color.substr(0,2))+','+hex_to_decimal(color.substr(2,2))+','+hex_to_decimal(color.substr(4,2))+','+opacity+')';
				shape.fill();
			},
			'highlight':function(canvas,area,options,areaOnly){
					if(areaOnly){
						$lib.addShape(canvas,area.getAttribute('shape').toLowerCase(),area.getAttribute('coords').split(','),options);
					}else{
						var data=area.data();
						var group=options.group && data['htmlmap.group'].name && (options.group instanceof Array?$.inArray(data['htmlmap.group'].name,options.group)<0:true);
						area.parent().find('area.'+(group?data['htmlmap.group'].name:data['htmlmap.key'])).each(function(k,c){
							$lib.addShape(canvas,c.getAttribute('shape').toLowerCase(),c.getAttribute('coords').split(','),options);
						});
					}
			},
			'strokeShape':function(shape,color,opacity,width){
				var hex_to_decimal=function(hex){return Math.max(0, Math.min(parseInt(hex, 16), 255));};
				shape.strokeStyle='rgba('+hex_to_decimal(color.substr(0,2))+','+hex_to_decimal(color.substr(2,2))+','+hex_to_decimal(color.substr(4,2))+','+opacity+')';
				shape.lineWidth = width;
				shape.stroke();
			}
		},
		$o={
			'scheme':false,
			'group':false,
			'screen':false,
			'fill':false,
			'stroke':false,
			'fade':true,
			'base':{
				'width':1,
				'height':1
			}
		};


	$.fn.htmlmap=function(o){
		var o=$.extend($o,o);

		if(o['onBeforeLoad']){
			o.onBeforeLoad.call($cache[o.scheme]);
		}

		if(o.overlay){
			var overlayid='site-overlay';
			$('<div class="overlay" id="'+overlayid+'"></div>').prependTo('body');

			this.css({'cursor':'pointer'}).overlay({
				'target':'#'+overlayid,
				'expose':'#ffffff',
				'effect':'apple',
				'fixed':false,
				'top':'6px',
				'onBeforeLoad':function(e){
					var api=this;
					this.getOverlay().css({
						'width':o.base.width+'px',
						'height':o.base.height+'px'
					}).empty().append('<div class="close"></div><img class="'+o.scheme+'" alt="" src="/var/ezflow_site/storage/htmlmap/usamap/SARE-USA.png" width="960" height="660" />')
					.find('.close').click(function(){
						api.close();
					});
				},
				'onLoad':function(){
					o.overlay=false;
					o.screen=false;
					this.getOverlay().css({'zIndex':100000}).find('.'+o.scheme).htmlmap(o);
				},
				'onClose':function(){
					this.getOverlay().empty();
				}
			});
/*
			if(o.screen){
				this.each(function(i){
					var obj=$(this),
						screen=$lib.createCanvas(this.width,this.height);
					map = $lib.createMap(obj,'map'+i,o);
					obj.after(map);
					$('#map'+i+' area[coords]').each(function(){
						var area=$(this);
						if(o.screen && $.inArray(area.data('htmlmap.group').name,o.screen.group)>=0){
							$lib.highlight(screen,area.get(0),o.screen,true);
						}
					});
					obj.before(screen);
				});
			}
*/
			if(o['onLoad']){
				o.onLoad.call($cache[o.scheme]);
			}
			return this;
		}

		this.each(function(i){
			var obj=$(this);

			map = $lib.createMap(obj,'map'+i,o);
//alert('cache',$cache);

			var wrap = $('<div></div>').addClass('htmlmap-wrapper').css({
				display:'block',
				background:'url('+this.src+')',
				position:'relative',
				padding:'0 0 10px',
				width:this.width,
				height:this.height
				});
			if(o.wrapClass) {
				wrap.addClass(o.wrapClass===true?obj.attr('class'):o.wrapClass);
			}
			obj.before(wrap).css('opacity', 0).css($config.canvasStyle).remove();
			if($config.hasVML){obj.css('filter','Alpha(opacity=0)');}
			wrap.append(obj,map);
			
			var canvas = $lib.createCanvas(this.width,this.height);
			$(canvas).css($config.canvasStyle);

			if(o.screen){
				var screen=$lib.createCanvas(this.width,this.height);
			}

			obj.parent().find('area[coords]').each(function(){
				var area=$(this);
				if(o.screen && $.inArray(area.data('htmlmap.group').name,o.screen.group)>=0){
					$lib.highlight(screen,area.get(0),o.screen,true);
				}
				area.mouseover(function(e){
					if(!$active){
						$lib.highlight(canvas,area,o);
					}
				}).mouseout(function(e){
					$active=!$lib.clearCanvas(canvas,e,o);
				});
			});

			obj.before(canvas);

			if(o.screen){
				obj.before(screen);
			}

		});

		if(o['onLoad']){
			o.onLoad.call($cache[o.scheme]);
		}

		return this;
	};

	return {
		'config':$config,
		'extend':function(scheme,definition){
			$cache[scheme]={
				'canvas':{},
				'definition':definition,
				'groups':{},
				'load':function(obj){
					obj.scheme=scheme;
					this.definition=this.definition.call(obj);
					this.loaded=true;
				},
				'loaded':false,
				'name':scheme
			}
		},
		'initialize':function(options){
			if($config.hasVML && $.browser.msie){
				document.namespaces.add("v", "urn:schemas-microsoft-com:vml");
				var style = document.createStyleSheet();
				$.each(['shape','rect', 'oval', 'circ', 'fill', 'stroke', 'imagedata', 'group','textbox'], function() {
						style.addRule('v\\:' + this, "behavior: url(#default#VML); antialias:true");
					}
				);
			}
			if(options.scheme){
				if(options.scheme.constructor==String){
					options.scheme=options.scheme.split(',');
				}
				for(var p in options.scheme){
					$cache[options.scheme[p]].load(this);
				}
			}
			if(options.load){options.load.call();}
		},
		'load':function(settings){
			var obj=this,
				scheme=this.scheme;
			$.ajax({
				'async':false,
				'url':settings['url'],
				'dataType':'json',
				'success':function(){
					settings['success'].call(obj,arguments[0],$cache[scheme]);
				}
			});
		},
		'register':function(selector,options){
				if(!$cache[options.scheme].loaded){
					$cache[options.scheme].load(this);
				}
				$(function(){
					$(selector).htmlmap(options);
				});
		},
		'registerArea':function(scheme,name,o){
			$cache[scheme].canvas[name]=o;
		},
		'registerGroup':function(scheme,name,o){
			$cache[scheme].groups[name]=o;
		},
		'set':function(o){
			$.extend($o,o);
		}
	};

})(jQuery);


