var EventLocationList = Class.create({
	/** デフォルト オプション */
	defaultOptions : {
		useWrap:true,
		containerId : 'fcmMapTabBoxL',
		descriptionUrl : 'hotSpot/hotSpot.php?hotSpotId=',
		unitTpl : 'event-item-unit',
		type : 'event'
	},
	/** 初期化 */
	initialize : function(mngObj, options) {
		this.mngObj = mngObj;

		options = Object.extend(Object.extend(this.defaultOptions, EventLocationList.options), options);
		this.options = {};
		for(var i in options) { this.options[i] = options[i]; }

		this.container = $(this.options.containerId);
		this.unitTpl = Conf.getApplicationParts(this.options.unitTpl);
	},
	createUnit : function(item) {
		// イベント表示の雛形を取得
		var unit = this.unitTpl.cloneNode(true);
		var descriptionUrl = this.options.descriptionUrl;
		var type = this.options.type;
		for(var key in item) {
			var value = item[key];
			$(unit).select('.' + key).each(function(node) {
				if(value == null) {
					$(node).hide(); // null のばあいは非表示
				}
				else {
					switch(node.tagName) {
						case 'IMG': node.src  = value; break;
						case 'A':   node.href = descriptionUrl + value; break;
						default:
							if(node.className.match(/@@@/)) {
								node.className = node.className.replace(/@@@/, value);
							}
							else {
								node.update(value);
							}
					}
				}
			});
		}
		// バックグラウンド画像を設定
		var a = unit.select('a')[0];
		a.style.backgroundImage = 'url(' + item.THUMBNAIL_URL + ')';
		// 場所の場合に消す要素
		if(type == 'hotspot') {
			unit.select('.OPENING_NOW', '.OPENING_STILL').each(function(node) {
				node.hide();
			})
		}


		unit.setStyle({cursor:'default'});
		unit.observe('mouseover', (function() {
			this.mngObj.onListMouseover(item.LOCATION_ID);
			if(!unit.defaultBgColor) {
				unit.defaultBgColor = unit.style.backgroundColor;
			}
			unit.setStyle({backgroundColor:'#FFF0D9'});
		}).bind(this));
		unit.observe('mouseout', (function() {
			this.mngObj.onListMouseover();
			unit.setStyle({backgroundColor:unit.defaultBgColor/*'#ffffff'*/});
		}).bind(this));
		return unit;
	},
	reflesh: function(items) {
		this.items = items;
		while(this.container.firstChild) {
			this.container.removeChild(this.container.firstChild);
		}
		this.units = [];
		this.highlighted = null;

		if(items.length) {
			for(var i = 0; i < items.length; i++) {
				var item = items[i];
				var unit = this.createUnit(item);
				this.container.appendChild(unit);
				this.units.push(unit);
			}
			$(this.options.noData).style.display = 'none';
		}
		else {
			$(this.options.noData).style.display = '';
		}
	},
	highlight : function(locationId) {
		if(this.highlighted) {
			this.highlighted.removeClassName('itemOn');
			this.highlighted.setStyle({backgroundColor:this.highlighted.defaultBgColor});
			this.highlighted = null;
		}
		for(var i=0,flg=0; i < this.items.length; i++) {
			var item = this.items[i];
			if(item.LOCATION_ID == locationId) {
				var unit = this.units[i];
				var bgcolor = unit.defaultBgColor;

				if(!bgcolor) {
					bgcolor = unit.style.backgroundColor;
					if(!bgcolor || bgcolor) {
						bgcolor = '#E9F4FE';
					}
					unit.defaultBgColor = bgcolor;
				}
				unit.addClassName('itemOn');
				new Effect.Highlight(unit, {
					startcolor: '#ffb544',
					endcolor: '#E9F4FE',
					restorecolor: bgcolor
				});

				this.highlighted = unit;

				if(!flg) {
					if (typeof document.documentElement.style.maxHeight != "undefined") {
						var jspPane = j$(this.container.parentNode.parentNode.parentNode).data('jsp');
						var scrollTop = this.highlighted.offsetTop;
						jspPane.scrollTo(0, scrollTop);
					}
					else {
						this.container.parentNode.scrollTop = this.highlighted.offsetTop -this.container.parentNode.offsetTop;
					}
				}
				flg = 1;
				break;
			}
		}
	},
	show : function() {
		this.container.show();
	},
	hide : function() {
		this.container.hide();
	},
	showWrap : function(msg) {
		if(!this.options.useWrap) return;
		if(!this.wrap) {
			this.wrap = new Wrap(this.container.parentNode.parentNode, {opacity:0.8});
			this.wrap.setImage(Conf._p(Conf.images.loading.url));
		}
		if(this.container.display != 'none') {
			this.wrap.setMessage(msg);
			this.wrap.show();
		}
	},
	hideWrap : function() {
		if(!this.options.useWrap) return;
		this.wrap.hide();
	}
});







/* MapPointerのコンストラクタ。緯度、軽度をメンバ変数に設定する。 */
function MapPointer(map, latlng) {
	this.latlng = latlng;
	this.setMap(map);
	this.icon = Conf.gmapMarkerIcons['pointer']['icon'];
}
/** google.maps.OverlayViewを継承 */
MapPointer.prototype = new google.maps.OverlayView();

/** 緯度経度を設定 */
MapPointer.prototype.setPosition = function(latlng) {
	this.latlng = latlng;
	var point = this.getProjection().fromLatLngToDivPixel(this.latlng);
	if(!point)return;
	this.element.style.left = point.x - this.icon.anchor.x + 'px';
	this.element.style.top  = point.y - this.icon.anchor.y + 'px';
}
/** 要素を作成 */
MapPointer.prototype.createElement = function() {
	if (this.element) return;
	this.element = new Element('img', {src:Conf._p(this.icon.url)});
	this.element.setStyle({
		width : this.icon.size.width + 'px',
		height: this.icon.size.height + 'px',
		position : 'absolute',
		display : 'none'
	});
	this.element.setOpacity(1.0);
	var panes = this.getPanes();
	if((typeof document.body.style.maxHeight != "undefined")) {
		panes.overlayImage.appendChild( this.element );// マーカーと同じオーバーレイに追加
	}
	else {
		panes.floatPane.appendChild( this.element );// IE6バグ回避
	}
}
/** 描画処理の実装 */
MapPointer.prototype.draw = function() {
	this.createElement();
	this.setPosition(this.latlng);
}
MapPointer.prototype.show = function(zindex) {
	if(this.element) {
		if(zindex)
			this.element.style.zIndex = zindex;
		this.element.style.display = 'block';
	}
}
MapPointer.prototype.hide = function() {
	if(this.element) this.element.style.display = 'none';
}
/* 削除処理の実装 */
MapPointer.prototype.remove = function() {
	if(this.element)
		this.element.parentNode.removeChild(this.element);
	this.element = null;
	this.icon = null;
}


var EventLocationMap = Class.create({
	/** デフォルト オプション */
	defaultOptions : {
		mapElementId       : 'map',
		defaultLat         : 39.7200079,
		defaultLng         : 140.102564,
		draggable          : true,
		scrollwheel        : false,
		zoom               : 14,
		eventListUri       : './EventLocation.php',// 問い合わせ先
		useWrap:true,
		infoWindowContentId: 'event-location-infowin'
	},
	/** 初期化 */
	initialize : function(eventLocation) {
		this.eventLocation = eventLocation;
		this.highlightZetIndex = 1000;
		this.options = Object.extend(this.defaultOptions, EventLocationMap.options || {});
		this.markers = null;
		this.mapElement = $(this.options.mapElementId);
		this.loadCenter();
	},
	initMap : function() {
		//this.showWrap();
		// マップ作成
		var map = new google.maps.Map(this.mapElement, {
			zoom        : this.options.zoom,
			center      : new google.maps.LatLng(
							this.options.defaultLat,
							this.options.defaultLng),
			mapTypeId   : google.maps.MapTypeId.ROADMAP,
			scaleControl: true,
			draggable   : this.options.draggable,
			scrollwheel : this.options.scrollwheel
		});
		this.map = map;
		
		// 地図上のクリックイベントハンドラ設定
		google.maps.event.addListener(map, 'click', this.closeAllInfoWindow.bind(this));
		
		// リサイズイベントのトリがを地図表示要素に設定
		this.mapElement.gmapTriggerReseize = function() {
			google.maps.event.trigger(map, 'resize') ;
		};
		
		// 地図状態の変更イベントのハンドラを設定
		var onChengeMapState = this.onChengeMapState.bind(this);
		var setOnBoundsChanged = function() {
			var listener = google.maps.event.addListener(map, 'bounds_changed', function() {
				google.maps.event.removeListener(listener);
				onChengeMapState();
			});
		};
		setOnBoundsChanged(); // 地図表示の初回の範囲変更イベントのため

		this.mapElement.gmapRedraw = (function() {
			var center = this.currentLatlng;
			this.mapElement.hide();
			setTimeout((function() {
				this.mapElement.show();
				this.mapElement.setStyle({visibility:'hidden'});
				map.setCenter(center);
				this.mapElement.gmapTriggerReseize();
			}).bind(this), 500);
		}).bind(this);

		
		google.maps.event.addListener(map, 'dragend',      onChengeMapState);
		google.maps.event.addListener(map, 'zoom_changed', setOnBoundsChanged);
		google.maps.event.addListener(map, 'resize', (function(){
			// 現在の中心を保存
			var center = this.map.getCenter();
			// 表示範囲変更イベントハンドラを設定
			var listener = google.maps.event.addListener(map, 'bounds_changed', function() {
				google.maps.event.removeListener(listener);
				// 中心位置を設定
				map.setCenter(center);
				// 表示範囲変更イベントハンドラを設定(中心位置が変わるのでイベントが発生するため)
				setOnBoundsChanged();
			});
		}).bind(this));

		// ポインタを作成
		this.pointer = new MapPointer(map);
	},
	activate : function(flg) {
		if(flg) {
			this.mapElement.show();
			if(!this.map) {
				setTimeout(this.initMap.bind(this), 200);
			}
		}
		else {
			this.mapElement.hide();
		}
	},
	loadCenter : function() {
		var lat = getCookie('eventLocationLat');
		var lng = getCookie('eventLocationLng');
		var zoom= getCookie('eventLocationZoom');
		if(!lat || !lng || zoom == null) return;
		this.options.defaultLat = lat;
		this.options.defaultLng = lng;
		this.options.zoom = parseInt(zoom);
	},
	saveCenter : function(lat, lng) {
		setTimeout((function() {
		var center = this.map.getCenter();
		setCookie('eventLocationLat', center.lat().toString());
		setCookie('eventLocationLng', center.lng().toString());
		setCookie('eventLocationZoom',this.map.getZoom().toString());
		}).bind(this), 0);
	},
	/** 地図状態の変更イベントのハンドラ */
	onChengeMapState : function() {
		var bounds = this.map.getBounds();
		var ne = bounds.getNorthEast();//北西
		var sw = bounds.getSouthWest();//南東
		// イベント情報を読み込み
		this.eventLocation.loadMapEvent(ne, sw); 
		// 中央の緯度経度を保存
		this.saveCenter();
		this.currentLatlng = this.map.getCenter();
		// 情報ウインドウの表示/非表示設定
		if(this.infowindow) {
			var p  = this.infowindow.getPosition();
			if(ne.lat() < p.lat() || ne.lng() < p.lng() || sw.lat() > p.lat() || sw.lng() > p.lng()) {
				this.infowindow.close();
				this.infowindow = null;
			}
		}
	},
	/** マーカー表示をリフレッシュ */
	reflesh : function(locations) {
		this.clearAllMarker();
		// 得られた位置情報のリストからマーカを作成
		this.markers = {};//new google.maps.MVCArray();

		// locations = this.sortLocations(locations);

		for(var i=0; i < locations.length; i++) {
			var marker = this.createMarker(locations[i], i);
			this.markers[locations[i].ID] = marker;// 作成したマーカーを保存
		}
		this.mapElement.setStyle({visibility:'visible'});
	},
	sortLocations : function(locations) {
		var result = [];
		for(var i in locations) {
			result.push(locations[i]);
		}
		result.sort(function(a,b) {
			return a.LNG < b.LNG;
		});
		return result;
	},
	highlight : function(locationId) {
		if(!locationId) {
			this.pointer.hide();
		}
		else {
			var marker = this.markers[locationId];
			if(!marker) {
				this.pointer.hide();
			}
			else {
				this.highlightZetIndex++
				this.pointer.setPosition(marker.getPosition());
				this.pointer.show(marker.getZIndex()+1);
			}
		}
	},
	clearAllMarker : function() {
		// すべてのマーカーを削除
		if(this.markers) {
			for(var i in this.markers) {
				this.markers[i].setMap(null);
			}
		}
		this.markers = null;
	},
	/** マーカ作成 */
	createMarker : function(location, z) {
		// マーカーを作成
		var marker = new google.maps.Marker({
			position: new google.maps.LatLng(location.LAT, location.LNG),
			map: this.map,
			icon  : createHotspotMarker(location.TERM, 'icon'),
			shadow: createHotspotMarker(location.TERM, 'shadow'),
			zIndex: z*10
		});
		// 情報ウィンドウを作成
		var infowindow = this.createInfoWindow(location, marker);
		// マーカーのイベントハンドラを設定
		google.maps.event.addListener(marker, 'click', (function() {
			this.closeAllInfoWindow();
			infowindow.open(this.map, marker);
			this.infowindow = infowindow;
		}).bind(this));
		google.maps.event.addListener(marker, 'mouseover', (function() {
			this.eventLocation.onMarkerMouseover(location.ID);
		}).bind(this));
		google.maps.event.addListener(marker, 'mouseout', (function() {
			this.eventLocation.onMarkerMouseover();
		}).bind(this));
		return marker;
	},
	/** 情報ウインドウの内容を作成 */
	createInfoWindow : function(location, marker) {
		// 情報ウィンドウを作成
		var infowindow = new google.maps.InfoWindow({position: marker.getPosition()});
		// 情報ウインドウの内容を設定
		var infoWindowContent = Conf.getApplicationParts(this.options.infoWindowContentId);

		var match_IF = /^IF\s+(.+)$/;
		$(infoWindowContent).select('.IF').each(function(node) {
			var cnames =node.classNames();
			if(cnames.toString().match(match_IF)) {
				var cname = RegExp.$1;
				node.removeClassName(cname);
				if(location[cname]) {
					$(node).show();
				}
				else {
					$(node).hide();
				}
			}
		});
		
		for(var key in location) {
			var value = location[key];
			$(infoWindowContent).select('.' + key).each(function(node) {
				if(value == null) {
					$(node).hide(); // null のばあいは非表示
				}
				else {
					switch(node.tagName) {
						case 'IMG': node.src  = value; break;
						case 'A':
							if(node.href.match(/@@@/)) {
								node.href = node.href.replace(/@@@/, value);
							}
							else {
								node.href = value;
							}
							break;
						default:
							if(node.className.match(/@@@/)) {
								node.className = node.className.replace(/@@@/, value);
							}
							else {
								node.update(value);
							}
					}
				}
			});
		}
		infowindow.setContent(infoWindowContent);
		// 情報ウィンドウのイベントハンドラを設定
		google.maps.event.addListener(infowindow, 'closeclick', function() {
			marker.infowindow = null;
		});
		return infowindow;
	},
	closeAllInfoWindow : function() {
		if(this.infowindow) {
			this.infowindow.close();
			this.infowindow = null;
		}
	},
	showWrap : function(msg) {
		if(!this.options.useWrap) return;
		if(!this.wrap) {
			this.wrap = new Wrap(this.mapElement.parentNode, {opacity:0.01});
			this.wrap.setImage(Conf._p(Conf.images.loading.url));
		}
		this.wrap.setMessage(msg);
		this.wrap.show();
	},
	hideWrap : function() {
		if(!this.options.useWrap) return;
		this.wrap.hide();
	}
});
var EventLocation = Class.create({
		/** デフォルト オプション */
	defaultOptions : {
		mapElementId       : 'map',
		accordionId        : 'fcmMap',
		defaultLat         : 35.689506,
		defaultLng         : 139.691701,
		draggable          : true,
		scrollwheel        : false,
		zoom               : 14,
		eventListUri       : './EventLocation.php',// 問い合わせ先
		useWrap:false,
		infoWindowContentId: 'event-location-infowin'
	},

	/** 初期化 */
	initialize : function() {
		var $this = this;
		this.options = Object.extend(this.defaultOptions, EventLocationMap.options || {});
		this.eventMap  = new EventLocationMap(this);
		this.eventList = new EventLocationList(this, {
			containerId : 'mapEventList',
			noData : 'mapEventListNoData',
			descriptionUrl : 'event/event.php?eventId=',
			unitTpl : 'event-item-unit',
			type : 'event'
		});
		this.productList = new EventLocationList(this, {
			containerId : 'mapProductList',
			noData : 'mapProductListNoData',
			descriptionUrl : 'product/product.php?productId=',
			unitTpl : 'event-item-unit',
			type : 'product'
		});
		this.hotspotList = new EventLocationList(this, {
			containerId : 'mapHotspotList',
			noData : 'mapHotspotListNoData',
			//descriptionUrl : 'hotSpot/hotSpot.php?hotSpotId=',
			descriptionUrl : 'hotSpot/hotSpot.php?hotSpotId=',
			unitTpl : 'event-item-unit',
			type : 'hotspot'
		});
		this.accordion = new Accordion(this.options.accordionId, {cookieName : 'TOP_ACCORDION_INDEX'});
		this.iikamoSelect = new IikamoSelect({
			change : function() { $this.loadMapEvent() }
		});
	},
	showWrap : function(msg) {
		setTimeout((function() {
			this.eventMap.showWrap(msg);
			this.eventList.showWrap(msg);
			this.productList.showWrap(msg);
			this.hotspotList.showWrap(msg);
		}).bind(this), 10);
	},
	hideWrap : function() {
		setTimeout((function() {
			this.eventMap.hideWrap();
			this.eventList.hideWrap();
			this.productList.hideWrap();
			this.hotspotList.hideWrap();
		}).bind(this), 10);
	},
	/** イベント情報を読み込み */
	loadMapEvent : function(ne, sw) {
		this.showWrap('読み込み中');

		if(!ne || !sw) {
			ne = this.ne;
			sw = this.sw;
		}
		else {
			this.ne = ne;
			this.sw = sw;
		}

		var p = {
			'sw[lat]': sw.lat(), 'sw[lng]':sw.lng(),
			'ne[lat]': ne.lat(), 'ne[lng]':ne.lng()
		};
		if(this.ne && this.sw) {
			p['sw2[lat]'] = this.sw.lat(); p['sw2[lng]'] = this.sw.lng();
			p['ne2[lat]'] = this.ne.lat(); p['ne2[lng]'] = this.ne.lng();
		}
		// いいかも
		var vote = this.iikamoSelect.getValue();
		if(vote > 0) {
			p.vote = vote;
		}
		// 表示範囲のイベント位置情報をサーバに問い合わせる
		new Ajax.Request(this.options.eventListUri, {
			parameters: p,
			//asynchronous: false,
			onSuccess: (function(res/*, data*/) {
				try {
					//this.debugOut(res.responseText.replace(/}/, "}\n"));
					var data = res.responseJSON;
					if (!data){
						this.hideWrap();
						// 2011/09退避
						//alert("1:"+res.responseText);
						return;
					}
					if(!data.unchanged) {
						var locationList = this.sortLocations(data.locationList);
						this.eventMap.reflesh(locationList);
						this.eventList.reflesh(data.eventList);
						this.productList.reflesh(data.productList);
						this.hotspotList.reflesh(data.hotspotList);

						// 範囲を保存
						this.ne = ne;
						this.sw = sw;
					}
				}catch (e){
					this.hideWrap();
					//this.debugOut(res.responseText.replace(/}/, "}\n"));
					// 2011/09退避
					//alert("2:"+e.message);
					return;
				}
				this.hideWrap();
			}).bind(this),
			onFailure: (function(res)    {
				this.hideWrap();
				alert('読み込みに失敗しました');
			}).bind(this),
			onException: (function (res) {
				this.hideWrap();
				alert('読み込み中にエラーが発生しました');
			}).bind(this)
		});
	},
	sortLocations : function(locations) {
		var result = [];
		if(Object.isArray(locations)) {
			for(var i=0; i<locations.length; i++) {
				result.push(locations[i]);
			}
		}
		else {
			for(var i in locations) {
				result.push(locations[i]);
			}
		}

		result.sort(function(a,b) {
			return a.LNG < b.LNG;
		});

		return result;
	},
	onListMouseover : function(locationId) {
		this.eventMap.highlight(locationId);
	},
	onMarkerMouseover : function(locationId) {
		this.eventList.highlight(locationId);
		this.productList.highlight(locationId);
		this.hotspotList.highlight(locationId);
	},
	activate : function(flg) {
		this.eventMap.activate(flg);
		this.accordion.activate(flg);
		this.iikamoSelect.activate(flg);
	},
	debugOut : function(text) {
		var w = window.open('', 'debugconsole',
			'width=400, height=300, menubar=no, toolbar=no, scrollbars=yes,resizable=yes');
		w.document.open();
		w.document.write('<html><head><title>debug console</title></head><body><pre>');
		w.document.write(text);
		w.document.write('</pre></body></html>');
		w.document.close();
		w.focus();
	}
});
//google.maps.event.addDomListener(window, 'load', function() {new EventLocation()} );


