var YMapWrapper = new Class( {

	Implements: [Options],

	options: {
		'defaultLat': 48.61391,
		'defaultLng': 22.298027,
		'defaultZoom': 13,
		'freeBalloonWidth': 100,
		'premiumBalloonWidth': 300
	},

	initialize: function( mapBlockID, objects, currentObjectID, currentSubcategoryIDs, bannerObjects, options ) {
		this.setOptions( options );

		this.mapBlock              = $( mapBlockID );
		this.objects               = objects;
		this.currentObjectID       = currentObjectID;
		this.currentSubcategoryIDs = currentSubcategoryIDs;
		this.bannerObjects         = bannerObjects;
		this.categoryCheckboxes    = $$( '.category-checkbox' );
		this.subcategoryCheckboxes = $$( '.subcategory-checkbox' );

		this.needsClear        = true;
		this.balloonMouseEnter = false;

		this.buildMap();
		this.installPlacemarks();
		this.installEvents();
	},

	setMapBlockSizes: function() {
		var parent = this.mapBlock.getParent();
		this.mapBlock.setStyles( {
			'width': ( parent.getStyle( 'width' ).toInt() ) + 'px',
			'height': ( parent.getStyle( 'height' ).toInt() ) + 'px'
		} );
	},

	buildMap: function() {
		this.map = new YMaps.Map( this.mapBlock );
		this.map.addControl( new YMaps.SmallZoom(), new YMaps.ControlPosition( YMaps.ControlPosition.TOP_RIGHT, new YMaps.Point( 40, 60 ) ) );
		this.map.enableScrollZoom();
		this.map.addControl( new YMaps.SearchControl( {width: 200}), new YMaps.ControlPosition( YMaps.ControlPosition.TOP_RIGHT, new YMaps.Point( 18, 18 ) ) );
		this.centerMap( this.options.defaultZoom );
	},

	installPlacemarks: function() {
		this.objects.each( function( object ) {
			var s = new YMaps.Style();
			s.iconStyle = new YMaps.IconStyle();

			s.iconStyle.offset = new YMaps.Point(
				( -1 * object.get( 'iconWidth' ) ) / 2,
				( -1 * object.get( 'iconHeight' ) ) / 2
			);
			s.iconStyle.href   = object.get( 'icon' );
			s.iconStyle.size   = new YMaps.Point( object.get( 'iconWidth' ), object.get( 'iconHeight' ) );
			YMaps.Styles.add( 'icon' + object.get( 'id' ), s );

			var marker = new YMaps.Placemark(
				new YMaps.GeoPoint( object.get( 'lat' ), object.get( 'lng' ) ),
				{
					style       : 'icon' + object.get( 'id' ),
					hasHint     : 1,
					hintOptions : {
						style: new YMaps.HintContentStyle(
							new YMaps.Template(
								'<div class="tip-container">' +
									'<div class="tip-top"></div>' +
									'<div class="tip">' +
										'<div class="tip-title">$[metaDataProperty.hint.title|Заголовок подсказки]</div>' +
										'<div class="tip-text">$[metaDataProperty.hint.text|Текст подсказки]</div>' +
									'<div class="tip-bottom"></div>' +
								'</div>'
							)
						)
					}
				}
			);
			marker.description                  = object.get( 'description' );
			marker.premium                      = object.get( 'premium' );
			marker.metaDataProperty.hint        = {};
			marker.metaDataProperty.hint.title  = object.get( 'tooltipTitle' );
			marker.metaDataProperty.hint.text   = object.get( 'tooltipText' );

			marker.setBalloonOptions( {
				maxWidth   : ( marker.premium == 1 ) ? this.options.premiumBalloonWidth : this.options.freeBalloonWidth,
				mapAutoPan : 1
			} );
			object.set( 'placemark', marker );

			if( this.currentObjectID != 0 ) {
				if( object.get( 'id' ) == this.currentObjectID ) {
					this.showPlacemark( object, true );
					this.map.openBalloon( marker.getGeoPoint(), marker.description, {
						maxWidth    : ( marker.premium == 1 ) ? this.options.premiumBalloonWidth : this.options.freeBalloonWidth,
						mapAutoPan : 1
					} );
				}
			} else {
				if( object.get( 'displayed' ) ) {
					this.showPlacemark( object, false );
				}
			}
		}.bind( this ) );
	},

	installEvents: function() {
		$( 'centerMap' ).addEvent( 'click', this.centerMap.bind( this, this.options.defaultZoom ) );
		$( 'clearMap' ).addEvent( 'click', function() { this.clearMap( true ) }.bind( this ) );
		$( 'centerMapNoZoom' ).addEvent( 'click', this.centerMap.bind( this, false ) );
		$( 'showOnlyRecommendObjects' ).addEvent( 'click', this.showRecommendObjects.bind( this, 2 ) );
		$( 'showOnlyVeryRecommendObjects' ).addEvent( 'click', this.showRecommendObjects.bind( this, 3 ) );
		$( 'showOnlyNewObjects' ).addEvent( 'click', this.showNewObjects.bind( this ) );

		this.installCategoryEvents();
		this.installBannerEvents();
	},

	installCategoryEvents: function() {
		this.currentSubcategoryIDs.each( function( subcategoryID ) {
			$( 'map-subcategory' + subcategoryID ).set( 'checked', true );
		} );
		//categories
		this.categoryCheckboxes.each( function( el ) {
			el.addEvent( 'click', function() {
				if( this.needsClear == true ) {
					this.clearMap( false );
					this.needsClear = false;
				}

				var categoryID            = el.get( 'id' ).replace( 'map-category', '' );
				var subcategoryBlock      = $( 'subcategories' + categoryID );
				var subcategoryCheckboxes = subcategoryBlock.getChildren( 'input' );
				subcategoryCheckboxes.each( function( subEl ) {
					subEl.set( 'checked', el.get( 'checked' ) );
					if( el.get( 'checked' ) == true ) {
						this.showSubCategoryPlacemarks( subEl.get( 'id' ).replace( 'map-subcategory', '' ) );
					} else {
						this.hideSubCategoryPlacemarks( subEl.get( 'id' ).replace( 'map-subcategory', '' ) );
					}
				}.bind( this ) )
			}.bind( this ) );
		}.bind( this ) );

		//subcategories
		this.subcategoryCheckboxes.each( function( el ) {
			el.addEvent( 'click', function() {
				if( this.needsClear == true ) {
					this.clearMap( false );
					this.needsClear = false;
				}

				if( el.get( 'checked' ) == true ) {
					this.showSubCategoryPlacemarks( el.get( 'id' ).replace( 'map-subcategory', '' ) );
				} else {
					this.hideSubCategoryPlacemarks( el.get( 'id' ).replace( 'map-subcategory', '' ) );
				}
			}.bind( this ) );
		}.bind( this ) );
	},

	showSubCategoryPlacemarks: function( subcategoryID ) {
		this.objects.each( function( object ) {
			if( object.get( 'subcategoryID' ) == subcategoryID ) {
				this.showPlacemark( object, false );
			}
		}.bind( this ) );
	},

	hideSubCategoryPlacemarks: function( subcategoryID ) {
		this.objects.each( function( object ) {
			if( object.get( 'subcategoryID' ) == subcategoryID ) {
				this.hidePlacemark( object );
			}
		}.bind( this ) );
	},

	installBannerEvents: function() {
		this.bannerObjects.each( function( relatedObjects, bannerID ) {
			$( 'banner' + bannerID ).addEvent( 'click', function() {
				this.clearMap( true );

				if( relatedObjects.length == 1 ) {
					if( this.objects.has( relatedObjects[0] ) ) {
						this.showPlacemark( this.objects.get( relatedObjects[0] ), true );
					}
				} else {
					relatedObjects.each( function( objectID ) {
						if( this.objects.has( relatedObjects[0] ) ) {
							this.showPlacemark( this.objects.get( objectID ), false );
						}
					}.bind( this ) );
					this.centerMap( this.options.defaultZoom );
				}
			}.bind( this ) );
		}.bind( this ) );
	},

	clearMap: function( clearCategories ) {
		this.objects.each( function( object ) {
			if( object.get( 'displayed', true ) ) {
				object.set( 'displayed', false )
				this.hidePlacemark( object );
			}
		}.bind( this ) );

		if( clearCategories == true ) {
				this.categoryCheckboxes.combine( this.subcategoryCheckboxes ).each( function( el ) {
				el.set( 'checked', false );
			} );
		}
	},

	centerMap: function( zoom ) {
		if( zoom == false ) {
			zoom = this.map.getZoom();
		}
		this.map.setCenter( new YMaps.GeoPoint( this.options.defaultLng, this.options.defaultLat ), zoom );
	},

	centerMapByObjectID: function( objectID, zoom ) {
		var object = this.objects.get( objectID );
		this.map.setZoom( 16 );
		this.map.panTo( new YMaps.GeoPoint( object.get( 'lat' ), object.get( 'lng' ) ) );
	},

	showRecommendObjects: function( recommend ) {
		this.clearMap( true );
		this.objects.each( function( object ) {
			if( object.get( 'recommend' ) == recommend ) {
				this.showPlacemark( object, false );
			}
		}.bind( this ) );
	},

	showNewObjects: function() {
		this.clearMap( true );
		this.objects.each( function( object ) {
			if( object.get( 'new' ) ) {
				this.showPlacemark( object, false );
			}
		}.bind( this ) );
	},

	showPlacemark: function( object, zoom ) {
		if( ( object.get( 'lat' ).toFloat() == 0 ) && ( object.get( 'lng' ).toFloat() == 0 ) ) {
			return false;
		}
		this.map.addOverlay( object.get( 'placemark' ) );
		object.set( 'displayed', true );

		if( zoom == true ) {
			if ( object.get( 'zoomOnView' ) == true ) {
				this.map.setZoom( 16 );
			} else {
				this.map.setZoom( this.options.defaultZoom );
			}
			this.map.panTo( new YMaps.GeoPoint( object.get( 'lat' ), object.get( 'lng' ) ) );
		}
	},

	hidePlacemark: function( object ) {
		object.set( 'displayed', false );
		this.map.removeOverlay( object.get( 'placemark' ) );
	}
} );

