function Marker(map, object) {
	this.self = Marker;
	this.map  = map;
	this.type   = object.type;
	this.teaser = object.teaser;
	this.placemark = null;
	this.hint = object.name;
	this.url = object.url;
}

Marker.prototype = {
	getStyle: function() {
		if (this.self.style.icon) {
			var icon = this.self.style.icon, s = new YMaps.Style();
			s.iconStyle = new YMaps.IconStyle();
			s.iconStyle.offset = this.pointFromArray(icon.offset, [-22, -46]);
			s.iconStyle.href   = icon.href.imageUrl(this.type);
			s.iconStyle.size   = this.pointFromArray(icon.size, [26, 46]);
			s.hasHint = true;
			this.style = this.implementBalloonStyle(s);
		} else {
			this.style = 'default#greenPoint';
		}
		return this.style;
	},
	implementBalloonStyle: function(style) {
		if (this.self.style.balloon) style.balloonStyle = this.self.style.balloon;
		return style;
	},
	pointFromArray: function (origin, Default) {
		if (!origin) origin = Default;
		return new YMaps.Point(origin[0], origin[1]);
	},
	createPlacemark: function (x, y) {
		this.placemark = new YMaps.Placemark(
			new YMaps.GeoPoint(x,y), {style: this.getStyle(), hintOptions:{showTimeout: 200, offset: new YMaps.Point(-20,20)},  balloonOptions: {hasCloseButton: false, maxWidth:270}}
		);
		this.placemark.description = this.teaser;
		this.placemark.name = "<a href='"+this.url+"'>"+this.hint+"</a>";
		this.coord = this.placemark.getCoordPoint();
        YMaps.Events.observe(this.placemark, this.placemark.Events.MouseLeave, function () {
            	this.map.hint.hide(0);
        }, this);				
		return this;
	},
	move: function (x, y) {
		this.placemark ?
			this.coord.setX(x).setY(y) :
			this.createPlacemark(x, y);
		return this;
	},
	add: function () {
		this.map.addOverlay(this.placemark);
		return this;
	},
	remove: function () {
		this.map.removeOverlay(this.placemark);
		return this;
	},
	show: function () {
		if (this.placemark._$iconContainer) { // dirty hacking...
			this.placemark._$iconContainer.css('display', '');
		}
		return this;
	},
	hide: function (marker) {
		if (this.placemark._$iconContainer) { // dirty hacking...
			this.placemark._$iconContainer.css('display', 'none');
		}
		return this;
	}
};

Marker.style = {};

Marker.factory = {
	cache: {},
	produce: function (map, object) {
		if (!this.exists(object)) {
			var marker = new Marker( map, object );
			this.cache[object.pk] = marker.move(object.lon, object.lat);
		}
		return marker || this.cache[object.pk];
	},
	exists: function (object) {
		return object.pk in this.cache;
	}
};

