function RaphaelOverlay(options) {

	/**
	 * autor: CTAPbIu_MABP
	 * email: ctapbiumabp@gmail.com
	 * site: http://mabp.kiev.ua/2010/09/10/raphael-overlay/
	 * license: GPL
	 * last update: 10.09.2010
	 * version: 0.5
	 */

	this.shapes = options.shapes;
	this.position = options.position;
	this.setMap(options.map);
	
	//this.zoom;
	//this.set;
	//this.fig;
	//this.dim;
}

RaphaelOverlay.prototype = new google.maps.OverlayView();

RaphaelOverlay.prototype.onAdd = function() {
	
	var center = this.getProjection().fromLatLngToDivPixel(new google.maps.LatLng(0,0)),
		worldWidth = this.getProjection().getWorldWidth();
			
	this.div = document.createElement('div');
	this.div.style.border = 'none';
	this.div.style.position = 'absolute';
	this.div.style.overflow = 'visible'; //?
	
	this.div.style.left = center.x - worldWidth / 2 + 'px';
	this.div.style.top = center.y - worldWidth / 2 + 'px';
	this.div.style.width = worldWidth+'px';
	this.div.style.height = worldWidth+'px';
	
	this.getPanes().overlayImage.appendChild(this.div);
	this.canvas = Raphael(this.div);
	
};

RaphaelOverlay.prototype.draw = function() {

	//console.group("draw");
	/*
	var zoom = this.getMap().getZoom();
	
	if (this.zoom == zoom){
		return;
	}else{
		this.zoom = zoom; 
	}*/

	var center = this.getProjection().fromLatLngToDivPixel(new google.maps.LatLng(0,0)),
		worldWidth = this.getProjection().getWorldWidth(),
		left = center.x - worldWidth / 2,
		top = center.y - worldWidth / 2,
		zoom = this.getMap().getZoom(),
		figure = null;
	
	this.canvas.clear();
	this.set = this.canvas.set();
	
	this.figures = [];
	this.dim = {
		left : [0],
		top : [0],
		right : [0],
		bottom : [0]
	};
	
	
	for (var i in this.shapes){
		this.dimensions(this.shapes[i], {
			worldWidth : worldWidth,
			zoom : zoom,
			left : left, 
			top : top
		});
	}
	
	var offsetLeft = Math.max.apply(null,this.dim.left),
		offsetTop = Math.max.apply(null,this.dim.top),
		offsetRight = Math.max.apply(null,this.dim.right),
		offsetBottom = Math.max.apply(null,this.dim.bottom),
		fullWorkdWidth = offsetLeft + worldWidth + offsetRight,
		fullWorkdHeight = offsetTop + worldWidth + offsetBottom;
		
	//console.log("offsets", offsetLeft, offsetTop, offsetRight, offsetBottom)
		
	this.div.style.left = left - offsetLeft + 'px';
	this.div.style.top = top - offsetTop + 'px';
	this.div.style.width = fullWorkdWidth + 'px';
	this.div.style.height = fullWorkdHeight + 'px';
	this.canvas.setSize(fullWorkdWidth, fullWorkdHeight);
	
	for (var i in this.figures){
		//console.log(this.figures[i].data)
		figure = this[this.figures[i].type](this.figures[i].data,{
			zoom : zoom,
			left : offsetLeft, 
			top : offsetTop
		});
		if (figure && this.figures[i].attr){
			figure.attr(this.figures[i].attr)
		}
		this.set.push(figure);
	}
	
	//console.groupEnd("draw");
};

RaphaelOverlay.prototype.dimensions = function(data, param){
	var projection = this.getProjection(), line = [], zoom = param.zoom,
		x, y, height, width, rx, ry, ne, sw, r, point, center, scale, fixed;
	
	//console.group("dimensions");
	//console.log("data.type")
	
	if ("zoom" in data){
		//console.log("zoom", data.zoom.min, "<", param.zoom, "<", data.zoom.max);
		if ("min" in data.zoom && data.zoom.min > param.zoom){
			return;
		} else 
		if ("max" in data.zoom && param.zoom > data.zoom.max){
			return;
		}
		if ("adjusted" in data.zoom){
			zoom -= data.zoom.adjusted;
		} else 
		if ("min" in data.zoom) {
			zoom -= data.zoom.min;
		}
	}
	
	scale = 1 << zoom;
	//console.log("scale", scale);
	
	switch (data.type){
		case "circle":
		case "ellipse":
			if (data.center instanceof google.maps.LatLng || data.position instanceof google.maps.LatLng){
				point = projection.fromLatLngToDivPixel(data.center || data.position);
			} else if (data.center instanceof google.maps.Point || data.position instanceof google.maps.Point){
				point = data.center || data.position;
			}
			rx = scale * data.rx;
			ry = scale * data.ry;
			r = scale * data.radius;
			x = point.x - param.left;
			y = point.y - param.top;
			this.dim.left.push(rx||r - x);
			this.dim.top.push(ry||r - y);
			this.dim.right.push(rx||r + x - param.worldWidth);
			this.dim.bottom.push(ry||r + y - param.worldWidth);
			
				console.log(rx||r - x, ry||r - y, rx||r + x - param.worldWidth, ry||r + y - param.worldWidth)
			this.figures.push({
				type:data.type,
				attr:data.attr,
				data:data.type=="circle" ?
					{x:x,y:y,r:r} : 
					{x:x,y:y,rx:rx,ry:ry}
			});
			break;
			
		case "rect":
		case "image":
			if (data.position instanceof google.maps.LatLngBounds) {
				ne = projection.fromLatLngToDivPixel(data.position.getNorthEast());
				sw = projection.fromLatLngToDivPixel(data.position.getSouthWest());
				width = ne.x - sw.x;
				height = ne.y - sw.y;
				x = sw.x - param.left;
				y = sw.y - param.top;
				r = scale * data.radius;
				fixed = 1;
			} else {
				if (data.position instanceof google.maps.LatLng){
					point = projection.fromLatLngToDivPixel(data.position);
					center = 0;
					fixed = 1;
				} else if (data.position instanceof google.maps.Point){
					point = data.position;
					center = 0;
					fixed = -1;
				} else if (data.center instanceof google.maps.LatLng){
					point = projection.fromLatLngToDivPixel(data.center);
					center = 1 / 2;
					fixed = 1;
				} else if (data.center instanceof google.maps.Point){
					point = data.center;
					center = 1 / 2;
					fixed = -1;
				}
				
				width = data.size.width * scale;
				height = data.size.height * scale;
				x = point.x - width * center - param.left;
				y = point.y - height * center - param.top;
				r = scale * data.radius;
			}

			this.dim.left.push(-x);
			this.dim.top.push(-y);
			this.dim.bottom.push(width + x - param.worldWidth * fixed);
			this.dim.right.push(height + y - param.worldWidth * fixed);
			this.figures.push({
				type:data.type,
				attr:data.attr,
				data:data.type=="rect" ?
					{x:x,y:y,width:width,height:height,r:r} :
					{src:data.src,x:x,y:y,width:width,height:height}
			});
			break;
			
		case "text" :
			point = projection.fromLatLngToDivPixel(data.position);	
			x = point.x - param.left;
			y = point.y - param.top;
			
			this.figures.push({
				type:data.type,
				attr:data.attr,
				data:{x:x,y:y,text:data.text}
			});
			break;
			
		case "path":
			point = projection.fromLatLngToDivPixel(data.position);
			path = Raphael.pathToRelative(Raphael.parsePathString(data.path));
			
			for (var i in path) {
				for (var j in path[i]) {
					if (j == 0) {
						line[i] = [path[i][j]];
					} else if (i==0 && j==1) {
						line[i].push(point.x - param.left + path[i][j]);
					} else if (i==0 && j==2) {
						line[i].push(point.y - param.top + path[i][j]);
					} else {
						line[i].push(path[i][j] * scale);
					}
				}
			}
			
			this.figures.push({
				type:data.type,
				attr:data.attr,
				data:{
					path:line
				}
			});
			break;
			
		case "polygon":
			
			for (var i in data.position){
				point = projection.fromLatLngToDivPixel(data.position[i]);
				line.push([
					i == 0 ? "M" : "L", 
					point.x - param.left, 
					point.y - param.top
				]);
			}
			line.push(["z"]);
			
			this.figures.push({
				type:data.type,
				attr:data.attr,
				data:{
					path:Raphael.pathToRelative(line)
				}
			});
			break;
			
		default:
			break;
	}
	//console.log("figures", this.figures[this.figures.length-1].toSource())
	//console.groupEnd("dimensions");
}



RaphaelOverlay.prototype.path = function(data, param) {
	data.path[0][1] += param.left;
	data.path[0][2] += param.top;
	return this.canvas.path(data.path);
};

RaphaelOverlay.prototype.polygon = function(data, param) {
	data.path[0][1] += param.left;
	data.path[0][2] += param.top;
	return this.canvas.path(data.path);
};

RaphaelOverlay.prototype.text = function(data, param) {
	return this.canvas.text(data.x, data.y, data.text);
};

RaphaelOverlay.prototype.image = function(data, param) {
	return this.canvas.image(
		data.src,
		data.x + param.left,
		data.y + param.top,
		data.width,
		data.height
	);
};

RaphaelOverlay.prototype.rect = function(data, param) {
	return this.canvas.rect(
		data.x + param.left,
		data.y + param.top,
		data.width,
		data.height,
		data.r
	);
};

RaphaelOverlay.prototype.circle = function(data, param) {
	return this.canvas.circle(
		data.x + param.left,
		data.y + param.top,
		data.r
	);
};

RaphaelOverlay.prototype.ellipse = function(data, param) {
	return this.canvas.ellipse(
		data.x + param.left,
		data.y + param.top,
		data.rx,
		data.ry
	);
};

RaphaelOverlay.prototype.onRemove = function() {
	this.canvas.clear();
	this.div.parentNode.removeChild(this.div);
};

