/* 建立 Namespace - StoreMap */
StoreMap = {};

/* 建立 Namespace - StoreMap.utils - 包含常用的 utilities */
StoreMap.utils = {};

/* 處理 DOM element 的滾輪事件 */
$.extend (StoreMap.utils, {
	preventScrolling: function (expr) {
		function cancelWheel (e) {
			e = e || window.event;
			if (e.preventDefault) {
				e.preventDefault ();
			}
			e.returnValue = false;
		}

		$(expr).each (function () {
			if (this.addEventListener) {
				this.addEventListener ('DOMMouseScroll', cancelWheel, false);
			}
			this.onmousewheel = cancelWheel;
		});
	},

	customScrolling: function (expr, scale) {
		function customScroll (e) {
			e = e || window.event;
			this.scrollTop += e.detail * scale;
			if (e.preventDefault) {
				e.preventDefault ();
			}
			e.returnValue = false;
		}

		$(expr).each (function () {
			if (this.addEventListener) {
				this.addEventListener ('DOMMouseScroll', customScroll, false);
			}
			// Doesn't work on IE
			// this.onmousewheel = customScroll;
		});
	}
} );

/* 處理表單欄位內容 */
$.extend (StoreMap.utils, {
	emptyForm: function (form) {
		$ (form).clearForm ();
	},

	updateFormValues: function (form, values) {
		if (! $ (form).filter ('form').length) {
			return;
		}
		var elements = $(form)[0].elements;
		$.each (values, function (name, value) {
			var element = elements[name];
			if (element) {
				switch (element.type) {
				case 'submit':
				case 'button':
					break;
				case 'checkbox':
					element.checked = value;
					break;
				default:
					element.value = value;
				}
			}
		} )
	},

	getFormValues: function (form) {
		var result = {}
		var fieldArray = $ (form).formToArray();
		if (fieldArray) {
			$.each (fieldArray, function (index, field) {
				result[field.name] = field.value;
			});
		}
		return result;
	}
});

/* 雜項 */
$.extend (StoreMap.utils, {
	readQuery: function (name) {
		var prefix = name + '=';
		return $.map (
			$.grep (document.location.search.substring (1).split('&'),
				function (str) {
					return str.indexOf (prefix) == 0;
				}
			),
			function (str) {
				return decodeURIComponent (str.substring (prefix.length) );
			}
		)[0];
	},

	findObjectInArray: function (ar, key, value) {
		if (!key) {
			return null;
		}
		return ($.grep (ar, function (obj) {
			return (obj && obj[key] == value);
		} ) [0]) || null;
	}
});

/* 建立 Namespace - StoreMap.bases - 一些 base classes */
StoreMap.bases = {};

StoreMap.bases.Observable = {
	getListeners: function (event_name) {
		var lm = this.listenerMap = this.listenerMap || {};
		return (lm[event_name] = lm[event_name] || []);
	},

	addListener: function (event_name, listener) {
		this.getListeners (event_name).push (listener);
	},

	clearListeners: function () {
		this.listenerMap = {};
	},

	fireEvent: function (event_name) {
		var ls = this.getListeners (event_name);

		for (var i = 0; i < ls.length; ++i) {
			ls[i] (this);
		}
	}
};

StoreMap.bases.Configurable = $.extend ( {}, {
	config: function (name, value) {
		this.configuration = this.configuration || {};
		if ( (typeof value) != "undefined") {
			this.configuration[name] = value;
		}
		return this.configuration[name];
	}
} );

/* 地圖的基本操作 */
StoreMap.MapController = $.extend ( {}, StoreMap.bases.Observable, StoreMap.bases.Configurable, {
	ensureDefaultViewpoint: function () {
		if (! this.config ('default_viewpoint') ) {
			this.config ('default_viewpoint', {
				longitude: 121.53728485107422,
				latitude: 25.04299284814388,
				zoom: 15
			} );
		}
	},

	showMapIn: function (container) {
		this.ensureDefaultViewpoint ();

		container = container ? $(container)[0] : null;
		if ( (! container) || this.map) {
			return;
		}

		if (! GBrowserIsCompatible () ) {
			alert ('您的瀏覽器不支援 Google Map');
			return;
		}

		/* 縮放地圖時，視窗不會捲動 */
		StoreMap.utils.preventScrolling (container, true);

		this.map = new GMap2 (container);
		this.geocoder = new GClientGeocoder ();

		(function (mc) {
			(function (map) {
				map.addControl (new GLargeMapControl () );
				map.addControl (new GMapTypeControl () );
				map.enableScrollWheelZoom ();
				map.enableDoubleClickZoom ();
				map.enableContinuousZoom ();

				var centerIcon = new GIcon();
				centerIcon.image = "http://labs.google.com/ridefinder/images/mm_20_blue.png";
				centerIcon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";
				centerIcon.iconSize = new GSize(12, 20);
				centerIcon.shadowSize = new GSize(22, 20);
				centerIcon.iconAnchor = new GPoint(6, 20);
				centerIcon.infoWindowAnchor = new GPoint(5, 1);

				GEvent.addListener (map, 'moveend', function () {
					mc.saveViewpoint ();
					if (mc.config ('show_center_marker') ) {
						if (!mc.centerPointer) {
							mc.centerPointer = new GMarker (map.getCenter (), centerIcon);
							map.addOverlay (mc.centerPointer);
						}
						mc.centerPointer.setPoint (map.getCenter () );
					}
					mc.fireEvent ('after_map_move');
				});

				GEvent.addListener (map, 'singlerightclick', function (p) {
					mc.showPopupMenu (p.x, p.y);
				});

			}) (mc.map);

			mc.restoreViewpoint ();
			mc.fireEvent ('after_load');
		}) (this);

		$ (window).unload (function () { GUnload (); });
	},

	isMapLoaded: function () {
		return (this.map && this.map.isLoaded () );
	},

	afterLoadMap: function (fn) {
		if (this.isMapLoaded () ) {
			fn (this);
		} else {
			this.addListener ('after_load', fn);
		}
	}
});

/* 記錄、還原視點 (viewpoint) */
$.extend (StoreMap.MapController, {
	getViewpoint: function () {
		if (! this.map) {
			return null;
		}

		var c = this.map.getCenter ();
		var z = this.map.getZoom ();

		return {longitude: c.lng (), latitude: c.lat (), zoom: z};
	},

	setViewpoint: function (vp) {
		vp = $.extend ({}, this.config ('default_viewpoint'), vp);
		this.map.setCenter (new GLatLng (vp.latitude, vp.longitude), vp.zoom);
	},

	resetViewpoint: function () {
		this.setViewpoint (this.config ('default_viewpoint') );
	},

	saveViewpoint: function () {
		var vp = this.getViewpoint ();
		$.cookie ('storemap.vp.lng', vp.longitude);
		$.cookie ('storemap.vp.lat', vp.latitude);
		$.cookie ('storemap.vp.z', vp.zoom);
	},

	restoreViewpoint: function () {
		var vp = $.extend ({}, this.config ('default_viewpoint'), {
			longitude: Number ($.cookie ('storemap.vp.lng') ) || undefined,
			latitude: Number ($.cookie ('storemap.vp.lat') ) || undefined,
			zoom: Number ($.cookie ('storemap.vp.z') ) || undefined
		}, {
			longitude: Number (StoreMap.utils.readQuery ('lng') ) || undefined,
			latitude: Number (StoreMap.utils.readQuery ('lat') ) || undefined,
			zoom: Number (StoreMap.utils.readQuery ('z') ) || undefined
		} );
		this.setViewpoint (vp);
	}
});

/* 地圖的 context manu (pop-up menu) */
$.extend (StoreMap.MapController, {
	popupMenu: {
		inited: false,
		entries: []
	},

	getPopupMenu: function () {
		if ( (! this.config ('popup_menu') ) || (this.popupMenu.entries.length <= 0) ) {
			return null;
		}

		if (! this.popupMenu.inited) {
			$ (this.config ('popup_menu') )
				.css ({position: 'absolute'})
				.appendTo (this.map.getContainer() )
				.hide ();

			(function (mc) {
				GEvent.addListener (mc.map, 'click', function () {
					mc.hidePopupMenu ();
				});
				GEvent.addListener (mc.map, 'mouseout', function () {
					mc.hidePopupMenu ();
				});
			}) (this);

			this.popupMenu.inited = true;
		}

		return this.popupMenu;
	},

	showPopupMenu: function (x, y) {
		var popupMenu = this.getPopupMenu ();
		if (popupMenu) {
			var pos = new GControlPosition (G_ANCHOR_TOP_LEFT, new GSize (x, y) );
			$ (this.config ('popup_menu') ).show ();
			pos.apply ($ (this.config ('popup_menu') )[0] );
			popupMenu.lastPoint = new GPoint (x, y);
		}
	},

	hidePopupMenu: function (x, y) {
		var popupMenu = this.getPopupMenu ();
		if (popupMenu) {
			$ (this.config ('popup_menu') ).hide ();
		}
	},

	isPopupMenuVisible: function () {
		if (! this.getPopupMenu () ) {
			return false;
		}
		return $ (this.config ('popup_menu') ).css ('display') != 'none';
	},

	getPopupMenuLocation: function () {
		if (! this.isPopupMenuVisible () ) {
			return;
		}
		return (function (latlng) {
			return {
				latitude: latlng.lat(),
				longitude: latlng.lng()
			};
		} ) (this.map.fromContainerPixelToLatLng (this.getPopupMenu ().lastPoint) );
	},

	addPopupMenuEntry: function (id, title, fn) {
		var existEntry = StoreMap.utils.findObjectInArray (this.popupMenu.entries, 'id', id);
		if (! existEntry) {
			(function (mc, entry) {
				mc.popupMenu.entries.push (entry);
				$ (document.createElement ('div') )
					.text (title)
					.appendTo (mc.config ('popup_menu') )
					.addClass (mc.config ('popup_menu.entry_class') )
					.click (function () {
						if (entry.handler) {
							entry.handler (mc);
						}
						mc.hidePopupMenu ();
					} );
			}) (this, {id: id, title: title, handler: fn});
		}
	},

	addPopupMenuSeparator: function () {
		$ (document.createElement ('hr') ).appendTo (this.config ('popup_menu') );

	}
});

/* 地圖上標記的相關 functions */
$.extend (StoreMap.MapController, {
	createMarker: function (point, options) {
		this.markers = this.markers || [];
		var m = new GMarker (new GLatLng (point.latitude, point.longitude), options);
		this.map.addOverlay (m);
		this.markers.push (m);
		return m;
	},

	getMarkerPoint: function (marker) {
		return marker ? {
			latitude: marker.getPoint ().lat (),
			longitude: marker.getPoint ().lng ()
		} : undefined;
	},

	removeMarker: function (marker) {
		StoreMap.MapController.map.removeOverlay (marker);
	},

	clearMarkers: function () {
		var markers = this.markers || [];
		for (var i = 0; i < markers.length; ++i) {
			this.removeMarker (markers[i]);
		}
		this.markers = [];
	},

	showMarker: function (marker) {
		if (marker && marker.getPoint) {
			this.map.panTo (marker.getPoint () );
		}
	},

	addMarkerListener: function (marker, event_name, handler) {
		GEvent.addListener (marker, event_name, handler);
	},

	showMarkerInformation: function (marker, html) {
		marker.openInfoWindowHtml (html);
	},

	hideInformation: function () {
		this.map.closeInfoWindow ();
	},

	isMarkerVisible: function (marker) {
		if (marker) {
			return this.map.getBounds ().contains (marker.getPoint () );
		}
		return false;
	}
});

/* 快速移動 */
$.extend (StoreMap.MapController, {
	quickMoveTo: function (name) {
		switch (name.replace (' ', '') ) {
		case '台北':
			this.setViewpoint ( {longitude: 121.56852722167969, latitude: 25.077825175989293, zoom: 12} );
			break;
		case '高雄':
			this.setViewpoint ( {longitude: 120.34423828125, latitude: 22.62034926433951, zoom: 12} );
			break;
		case '基隆':
			this.setViewpoint ( {longitude: 121.73503875732422, latitude: 25.121040804823515, zoom: 12} );
			break;
		case '桃園':
			this.setViewpoint ( {longitude: 121.27120971679688, latitude: 24.910726659859982, zoom: 12} );
			break;
		case '新竹':
			this.setViewpoint ( {longitude: 121.01646423339844, latitude: 24.760861243818784, zoom: 12} );
			break;
		case '苗栗':
			this.setViewpoint ( {longitude: 120.84514617919922, latitude: 24.566171618760233, zoom: 12} );
			break;
		case '台中':
			this.setViewpoint ( {longitude: 120.70026397705078, latitude: 24.148946551598858, zoom: 12} );
			break;
		case '彰化':
			this.setViewpoint ( {longitude: 120.52207946777344, latitude: 23.986879947190896, zoom: 12} );
			break;
		case '南投':
			this.setViewpoint ( {longitude: 120.71674346923828, latitude: 23.903729820074282, zoom: 12} );
			break;
		case '雲林':
			this.setViewpoint ( {longitude: 120.4046630859375, latitude: 23.685402974297677, zoom: 12} );
			break;
		case '嘉義':
			this.setViewpoint ( {longitude: 120.4489517211914, latitude: 23.47993684921374, zoom: 12} );
			break;
		case '台南':
			this.setViewpoint ( {longitude: 120.25634765625, latitude: 23.091733271320724, zoom: 11} );
			break;
		case '屏東':
			this.setViewpoint ( {longitude: 120.59967041015625, latitude: 22.575974402876476, zoom: 11} );
			break;
		case '宜蘭':
			this.setViewpoint ( {longitude: 121.78516387939453, latitude: 24.715959844709335, zoom: 12} );
			break;
		case '花蓮':
			this.setViewpoint ( {longitude: 121.60560607910156, latitude: 23.97605777710017, zoom: 13} );
			break;
		case '台東':
			this.setViewpoint ( {longitude: 121.13164901733398, latitude: 22.750380089147967, zoom: 13} );
			break;
		case '澎湖':
			this.setViewpoint ( {longitude: 119.59785461425781, latitude: 23.572798279092712, zoom: 12} );
			break;
		case '恆春':
			this.setViewpoint ( {longitude: 120.76086044311523, latitude: 21.998763532629045, zoom: 13} );
			break;
		case '金門':
		case '馬祖':
		default:
			alert (['系統尚無 "', name, '" 的資料。'].join ('') );
			break;
		}
	}
} );


StoreMap.StaticLinkManager = $.extend ({}, StoreMap.bases.Observable, StoreMap.bases.Configurable, {
	configuration: {
		registered_class: 'registered_static_link'
	},

	register: function (expr) {
		var elements = $ (expr).filter ('a'). not ('.' + this.config ('registered_class') );
		if (! elements || ! elements.length) {
			return;
		}

		if (! this.staticLinks) {
			this.staticLinks = [];
			StoreMap.Stores.addListener ('after_update', function () { StoreMap.StaticLinkManager.refresh (); } );
		}

		this.staticLinks = $ (this.staticLinks).add (elements);
		$ (elements).addClass (this.config ('registered_class') )

		this.refresh ();

		return elements;
	},

	setURL: function (url) {
		this.staticLinks = this.staticLinks || [];
		return $ (this.staticLinks).attr ('href', url);
	},

	refresh: function () {
		var parameters = [];

		(function (keyword) {
			if (keyword) {
				parameters.push (['q', keyword].join ('=') );
			}
		}) (StoreMap.Stores.extraInformation ('keyword') );

		(function (type) {
			if (type) {
				parameters.push (['st', type].join ('=') );
			}
		}) (StoreMap.Stores.extraInformation ('type') );

		(function (center) {
			if (center) {
				parameters.push (['lng', center.longitude].join ('=') );
				parameters.push (['lat', center.latitude].join ('=') );
			}
		} ) (StoreMap.Stores.getSearchCenter () );

		this.setURL (encodeURI (['?', parameters.join ('&')].join ('') ) );
	}

});

StoreMap.SearchMessage = $.extend ({}, StoreMap.bases.Observable, StoreMap.bases.Configurable, {
	setMessage: function (message) {
		this.lastMessage = message;
		this.fireEvent ('after_update');
	},

	getMessage: function () {
		return this.lastMessage;
	}
});

StoreMap.Stores = $.extend ({}, StoreMap.bases.Observable, StoreMap.bases.Configurable, {
	clear: function () {
		/* 清除 list items */
		if (this.config ('list_item.enable') ) {
			$ (this.config ('list_item.filter') )
				.not (this.config ('list_item.template') )
				.remove ();
		}

		/* 清除 map markers */
		if (this.config ('map_marker.enable') ) {
			$.each (this.stores || {}, function (id, store) {
				StoreMap.MapController.removeMarker (store.marker);
			});
		}

		this.select (null);
		this.stores = {};
		this.extras = {};
		this.extraInformation ('valid', false);

		this.hideSearchCenterPointer ();

		this.fireEvent ('after_update');
	},

	getSearchCenterIcon: function () {
		if (! this.searchCenterIcon) {
			this.searchCenterIcon = new GIcon();
			this.searchCenterIcon.image = "http://labs.google.com/ridefinder/images/mm_20_green.png";
			this.searchCenterIcon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";
			this.searchCenterIcon.iconSize = new GSize(12, 20);
			this.searchCenterIcon.shadowSize = new GSize(22, 20);
			this.searchCenterIcon.iconAnchor = new GPoint(6, 20);
			this.searchCenterIcon.infoWindowAnchor = new GPoint(5, 1);
		}
		return this.searchCenterIcon;
	},

	showSearchCenter: function () {
		if (this.searchCenterPointer) {
			StoreMap.MapController.showMarker (this.searchCenterPointer);
		}
	},

	getSearchCenter: function () {
		if (this.searchCenterPointer) {
			var p = this.searchCenterPointer.getPoint();
			return {longitude: p.lng(), latitude: p.lat()};
		}
	},

	showSearchCenterPointer: function (point) {
		this.hideSearchCenterPointer ();
		this.searchCenterPointer = StoreMap.MapController.createMarker (point, this.getSearchCenterIcon () );
	},

	hideSearchCenterPointer: function () {
		if (this.searchCenterPointer) {
			StoreMap.MapController.removeMarker (this.searchCenterPointer);
		}
		this.searchCenterPointer = undefined;
	},

	update: function (updateInformation) {
		(function (ss) {
			if (! ss.config ('stores.registered_map_listener') ) {
				StoreMap.MapController.addListener ('after_map_move', function (mc) {
					ss.refreshListItems ();
				});
				StoreMap.Stores.addListener ('after_update', function (ss) {
					ss.updateSearchMessage ();
				});
				ss.config ('stores.registered_map_listener', true);
			}

			ss.clear ();

			$.each (updateInformation, function (name, value) {
				if (name != 'stores') {
					ss.extraInformation (name, value);
				}
			} );

			( function (stores, center) {
				if (stores) {
					if (center && ! ss.config ('plain_result') ) {
						ss.showSearchCenterPointer (center);

						var cp = new GLatLng (center.latitude, center.longitude);

						stores = $.grep (stores, function (s) {
							var sp = new GLatLng (s.point.latitude, s.point.longitude);
							return cp.distanceFrom(sp) < 30000;
						} );

						stores.sort (function (a, b) {
							var ap = new GLatLng (a.point.latitude, a.point.longitude);
							var bp = new GLatLng (b.point.latitude, b.point.longitude);
							return cp.distanceFrom(ap) - cp.distanceFrom(bp);
						} );
					}
					$.each (stores, function (i, store) {
						ss.add (store);
					} );
				}
			} ) (updateInformation.stores, updateInformation.queryCenter);

			ss.refreshListItems ();
			ss.extraInformation ('valid', true);
			ss.fireEvent ('after_update');
		}) (this);
	},

	add: function (store) {
		var stores = this.stores = this.stores || {};

		/* 顯示列表項目 */
		if (this.config ('list_item.enable') ) {
			store.listItem = this.createListItem (store);
		}

		/* 顯示地圖標記 */
		if (this.config ('map_marker.enable') ) {
			store.marker = this.createMapMarker (store);
		}

		/* 新增成功, 加入清單中 */
		stores[store.id] = store;
	},

	createListItem: function (store) {
		return $ (this.config ('list_item.template') )
			.clone ()
			.attr ('id', '')
			.show ()
			.text (store.name)
			.appendTo (this.config ('list_item.container') )
			.click (function () { StoreMap.Stores.select (store.id) } ) [0];
	},

	createMapMarker: function (store) {
		var marker = StoreMap.MapController.createMarker (store.point, {title: store.name});
		if (marker) {
			StoreMap.MapController.addMarkerListener (marker, "click", function () {
				StoreMap.Stores.select (store.id);
			} );
		}
		return marker;
	},

	get: function (id) {
		var stores = this.stores = this.stores || {};
		return stores[id];
	},

	showDetails: function (id) {
		(function (ss, store) {
			if (! ss.detailWindowInited) {
				$ (ss.config ('details.container') ).jqm ({trigger: false});
				$ (document).keypress (function (e) {
					if (e.keyCode == 27)
						$ (ss.config ('details.container') ).jqmHide ();
				});

				ss.detailWindowInited = true;
			}
			if (store) {
				$ (ss.config ('details.container') )
					.find ('.sd_store_name').text (store.name).end ()
					.find ('.sd_store_address').text (store.address).end ()
					.find ('.sd_store_phone').text (store.phone).end ()
					.find ('.sd_store_type').text (store.type).end ()
					.find ('.sd_store_description').text (store.description).end ()
					.jqmShow ();
			}
		}) (this, this.get (id) );
	},

	select: function (id) {
		if (this.selected) {
			if (this.selected.listItem) {
				$ (this.selected.listItem)
					.removeClass (this.config ('list_item.selected_class') );
			}
		}

		this.selected = id ? this.get (id) : null;

		if (this.selected) {
			if (this.selected.listItem) {
				$ (this.selected.listItem)
					.addClass (this.config ('list_item.selected_class') );
			}

			if (this.selected.marker) {
				StoreMap.MapController.showMarkerInformation (this.selected.marker, [
					['<b>', this.selected.name, '</b>'].join (''),
					['地址: ', this.selected.address].join (''),
					['電話: ', this.selected.phone].join (''),
					'',
					[
						'<a href="#" onclick="StoreMap.Stores.showDetails(',
						this.selected.id,
						'); return false;">顯示詳細資料</a>',
						'&nbsp;',
						'<a href="#" onclick="StoreMap.ErrorReport.openFor(',
						this.selected.id,
						'); return false;">回報錯誤資料</a>'
					].join ('')
				].join ('<br/>') );
			}
		}

		this.fireEvent ('after_select');
	},

	refreshListItems: function () {
		if (this.config ('list_item.enable') && this.config ('map_marker.enable') ) {
			(function (ss, mc, ic) {
				$.each (ss.stores, function (id, store) {
					if (mc.isMarkerVisible (store.marker) ) {
						$ (store.listItem).removeClass (ic).show ();
					} else {
						$ (store.listItem).addClass (ic);
						if (ss.config ('list_item.show_invisible') ) {
							$ (store.listItem).show ();
						} else {
							$ (store.listItem).hide ();
						}
					}
				} );
			} ) (this, StoreMap.MapController, this.config ('list_item.invisible_class') );
		}

	},

	updateSearchMessage: function () {
		var keywordDescription = (function (keyword) {
			if (! keyword) { return ''; }
			return ['符合 <em class="keyword">', keyword, '</em> 的'].join ('');
		}) (this.extraInformation ('keyword') );

		var typeDescription = (function (type) {
			if (! type) { return '書店' };
			return ['<em class="type">', $ (['#store_type option[text=', type, ']'].join ('')).text(), '</em> '].join ('');
		}) (this.extraInformation ('type') );

		var resultCount = $ (this.config ('list_item.filter') ).not (this.config ('list_item.template') ).size ();

		var elapsedTimeInformation = (function (elapsed) {
			if (! elapsed) return '';
			return ['費時', elapsed, '秒。'].join (' ');
		}) (this.extraInformation ('elapsed') ); 

		StoreMap.SearchMessage.setMessage ([
			'<a title="顯示搜尋中心" href="#" onclick="StoreMap.Stores.showSearchCenter(); return false;">地圖中心</a> 30 公里內',
			( (this.extraInformation ('valid') && resultCount > 0) ?
				['共找到 ', resultCount, ' 間', keywordDescription, typeDescription, '。', elapsedTimeInformation].join ('') :
				['找不到', keywordDescription, typeDescription, '，或許您可以協助我們<a href="/map/submit">新增書店資料</a>。'].join ('')
			)
		].join ('') );
	},

	extras: {},

	extraInformation: function (name, value) {
		if (value) {
			this.extras[name] = value;
		}
		return this.extras[name];
	}
} );

StoreMap.Locator = $.extend ({}, StoreMap.bases.Observable, {
	showOnMapCenter: function () {
		var c = StoreMap.MapController.getViewpoint ();
		this.moveTo (c);
	},

	locate: function (address, country) {
		var realAddress = (country) ? [address, country].join(',') : address;
		StoreMap.MapController.geocoder.getLocations (
			realAddress,
			function (locations) {
				if (locations.Status.code != 200 || locations.Placemark.length == 0) {
					alert (['找不到 "', address, '"'].join (''));
				} else {
					var debug_messages = [];

					debug_messages.push (['您所查詢的地址:', address].join (' ') );

					var p = locations.Placemark[0];
					debug_messages.push (['最接近的地址:', p.address].join (' ') );

					var coords = p.Point.coordinates;
					var point = {latitude: coords[1], longitude: coords[0]};

					StoreMap.Locator.moveTo (point, debug_messages.join ('<br/>') );
				}
			}
		);
	},

	moveTo: function (point, information) {
		if (this.locator) {
			StoreMap.MapController.removeMarker (this.locator);
			this.locator = null;
		}

		var locator = this.locator = StoreMap.MapController.createMarker (point, {draggable: true} );

		if (information) {
			StoreMap.MapController.addMarkerListener (locator, 'click', function () {
				StoreMap.MapController.showMarkerInformation (locator, information);
			} );
			StoreMap.MapController.showMarkerInformation (locator, information);
		}

		StoreMap.MapController.addMarkerListener (locator, 'dragstart', function () {
			StoreMap.MapController.hideInformation ();
		} );

		StoreMap.MapController.addMarkerListener (locator, 'dragend', function () {
			StoreMap.Locator.fireEvent ('after_update');
		} );

		this.fireEvent ('after_update');
	},

	getPoint: function () {
		return StoreMap.MapController.getMarkerPoint (this.locator);
	},

	hide: function () {
		if (this.locator) {
			StoreMap.MapController.removeMarker (this.locator);
			this.locator = null;
		}
	}
} );

StoreMap.ErrorReport = $.extend ({}, StoreMap.bases.Observable, StoreMap.bases.Configurable, {
	init: function () {
		if (! this.inited) {
			$ (this.config ('container') ).jqm ({
				ajax: this.config ('form_url'),
				trigger: false,
				onHide: function(h) {
					h.w.hide ();
					if (h.o) {
						h.o.remove();
					}
					h.w.html ('表單讀取中...<br/><a href="#" onclick="StoreMap.ErrorReport.close(); return false;">取消</a>');
				}
			});

			$(document).keypress (function (e) {
				if (e.keyCode == 27)
					StoreMap.ErrorReport.close();
			});

			this.inited = true;
		}
		return true;
	},

	openFor: function (store_id) {
		if (StoreMap.Stores.get (store_id) ) {
			$.jqm.hash[$ (this.config ('container') )[0]._jqm].c.ajax = [this.config ('form_url'), '&id=', store_id].join ('');
			$ (this.config ('container') ).jqmShow();
		}
	},

	close: function () {
		$ (this.config ('container') ).jqmHide ();
	},

	doSubmit: function (form) {
		$ (this.config ('container') ).load (
			this.config ('form_url'),
			StoreMap.utils.getFormValues (form)
		);
	}
});

StoreMap.FormConnector = $.extend ( {}, {
	proxies: {},

	getFormProxy: function (name) {
		if (name) {
			return this.proxies[name] = this.proxies[name] || $.extend ( {},
				StoreMap.bases.Observable, StoreMap.bases.Configurable, {
					submit: function () {
						$ (this.form).submit ();
					},

					getFormValues: function () {
						return StoreMap.utils.getFormValues (this.form);
					}
				} );
		}
	},

	addForm: function (name, form) {
		var proxy = this.getFormProxy (name);

		if (proxy.form) {
			proxy.clearListeners ();
		}

		$ (form).unbind ('submit')
			.submit (function () {
				proxy.fireEvent ('submit');
				return false;
			} );

		proxy.form = form;
	},

	removeForm: function (name) {
		var proxy = this.getFormProxy (name);
		if (proxy.form) {
			$ (proxy.form).unbind ('submit');
			proxy.clearListeners ();
			proxy.form = null;
		}
	},

	addFormHandler: function (name, fn) {
		this.getFormProxy (name).addListener ('submit', fn);
	}
} );


