/* Map loader */

function MapLoader(conf) {
	$.extend(this, {
		// properties
		conf: {
			init_scale: 5
		},
		pos: null,
		map: null,
		wmap: null,
		init_scale: null,
		mapOpts: null,

		// methods
		init: function () {
			$.extend(this.conf, conf);

			var that = this;

			that.pos = new google.maps.LatLng(52.219503, 14.270063);
			that.init_scale = that.conf.init_scale;
			that.mapOpts = {
				zoom: that.init_scale,
				center: that.pos,
				mapTypeId: google.maps.MapTypeId.ROADMAP,
				scrollwheel: false,
				disableDefaultUI: true,
				zoomControl: true,
				zoomControlOptions: {
					position: google.maps.ControlPosition.LEFT_CENTER
				}
			};

			that.map = new google.maps.Map(document.getElementById("map"), that.mapOpts);

/*$.get('http://wheely-geo.herokuapp.com/nowjs/now.js', function(responseText, textStatus, XMLHttpRequest) {
                console.log(responseText);
            });*/
			that.wmap = new WheelyMap(that.map);
		}
	});

	this.init();
	return this;
}

(function () {

	"use strict"

	// var g = new google.maps.Geocoder()
	// 
	// g.geocode({
	//     // address : 'st. Gallen'
	//     location : new google.maps.LatLng(47.4241, 9.370879999999943)
	// }, function(data) {
	//     console.log(data)
	// })
	window.WheelyMap = function (map, opts) {
		var self = this,
			
			// All cities
			citiesView = new Cities(),
			
			// Map legend
			mapLegend = new MapLegend(),
			
			options = $.extend({}, this.defaults, opts),
			cities = [],
			active = -1,
			tpl = {
				main: '<div class="cityinfo">' + '<div class="cityinfo-content">' + '<div class="cityinfo-info">' + '<div class="cityinfo-vendors-wrapper">' + '<div class="cityinfo-vendors">{vendors}</div>' + '</div>' + '<div class="cityinfo-zoom"><a href="#">zoom in city</a></div>' + '</div>' + '<div class="cityinfo-name">{city}</div>' + '</div>' + '<div class="cityinfo-tail"></div>' + '</div>',
				vendor: '<div class="cityinfo-vendor"><div class="cityinfo-vendor-name">{logo}</div><div class="cityinfo-vendor-phone">{phone}</div>{url}</div>'
			},
			ibOptions = {
				disableAutoPan: true,
				pixelOffset: new google.maps.Size(-100, -205),
				closeBoxURL: '',
				isHidden: true,
				// pane: "mapPane",
				// pane: "floatPane",
				enableEventPropagation: true
			},
			load = function () {
				$.ajax('http://dev.wheely.com/cities', {
					success: function(data, textStatus, jqXHR) {
						cities = $.map(data, function (city, ndx) {
							var vendors = [],
								node;
	
							city.cars = {};
	
							city.bounds = new google.maps.LatLngBounds(new google.maps.LatLng(city.sw[0], city.sw[1]), new google.maps.LatLng(city.ne[0], city.ne[1]));
	
							city.marker = new google.maps.Marker({
								title: city.city,
								position: new google.maps.LatLng(city.center[0] , city.center[1]),
								icon: options.icon,
								map: map
							});
							console.log(city);
							$.each(city.vendors || [], function (i, vendor) {
								var html = tpl.vendor.replace(/\{([a-z]+)\}/g, function (a, m) {
									if (m == 'logo') {
										return vendor.logo ? '<img src="' + options.stdImgDir + 'map/' + vendor.logo + '" title="' + vendor.name + '"/>' : vendor.name;
									} else if (m == 'url') {
										return vendor.url ? '<a href="' + vendor.url + '" target="_blank">' + vendor.url + '</a>' : '';
									} else {
										return vendor[m] || '';
									}								
								});
								vendors.push(html);
							})
	
							node = $(tpl.main.replace(/\{vendors\}/, vendors.join('')).replace(/\{ndx\}/, ndx).replace(/\{city\}/, city.city));
	
							node.find('.cityinfo-zoom a').click(function (e) {
								e.preventDefault();
								self.showCity(ndx);
							}).end().find('.cityinfo-content').click(function (e) {
								e.stopPropagation()
							});
	
							if (city.zoom === false) {
								node.find('.cityinfo-zoom').hide()
							}
	
							city.infobox = new InfoBox($.extend({}, ibOptions, {
								content: node[0]
							}))
							city.infobox.open(map, city.marker)
	
							google.maps.event.addListener(city.marker, 'click', function () {
								var h = node.parent().css('visibility') == 'hidden';
	
								$.each(cities, function (i, c) {
									c.infobox.hide();
								});
	
								h && city.infobox.show()
							})
	
							return city;
						});
	
						google.maps.event.addListener(map, 'dragend', onMapChange);
						google.maps.event.addListener(map, 'zoom_changed', onMapChange);
						google.maps.event.addListener(map, 'click', closeInfoboxes);
	
						//window.now.update = update;
	
						//load = function () {};
	
						//options.onload(cities);
	
						//onMapChange();
					}
				});
					
			},

			closeInfoboxes = function () {
				$.each(cities, function (i, c) {
					c.infobox.hide();
				});
			},

			update = function (data) {
				var city = cities[data.city_ndx];

				if (city) {
					self.log('update ' + city.city)
					$.each(data.cars, function (id, car) {
						// var id = car.id;
						if (!city.cars[id]) {
							self.log('new car: ' + id)
							city.cars[id] = new google.maps.Marker({
								icon: options.icon,
								animation: google.maps.Animation.DROP
							})

						}
						city.cars[id].setPosition(new google.maps.LatLng(car.lat, car.lng));
						city.cars[id].setTitle(id + ' ' + car.text);
					})
					updateMap();
				}

			},

			updateMap = function () {
				var cityZoom = map.getZoom() >= options.cityZoom;

				$.each(cities, function (ndx, city) {
					var carsMap = cityZoom && ndx == active ? map : null;

					city.marker.setMap(cityZoom ? null : map);
					cityZoom && city.infobox.hide();

					$.each(city.cars, function (id, car) { !! carsMap != !! car.getMap() && car.setMap(carsMap);
					});
				});
			},


			onMapChange = function () {
				/*var bounds = map.getBounds(),
					ndxs = [-1],
					ndx;

				if (!bounds) {
					return setTimeout(onMapChange, 500);
				}

				$.each(cities, function (ndx, city) {
					bounds.intersects(city.bounds) && ndxs.unshift(ndx);
				});

				active = ndxs.shift()
				updateMap();
				window.now.get(active, update);*/
			}

			;


		this.showCity = function (ndx) {
			var city = cities[ndx];

			if (city) {
				// city.marker.setMap(null)
				map.setCenter(new google.maps.LatLng(city.lat, city.lng));
				map.setZoom(options.streetZoom);
				onMapChange();
			}
		};
		
		this.zoomTo = function(aLatLng, id) {
			var latLng = new google.maps.LatLng(aLatLng[0], aLatLng[1]);
			map.setZoom(9);
			map.setCenter(latLng);
			
			citiesView.switchView();
			
			for (var i = 0; i < cities.length; i++) {
				cities[i].infobox.hide();
				
				if (cities[i].city == id) {
					cities[i].infobox.show();				
				}
			}
		};

		//window.now && window.now.ready(load);
		load();


	}

	window.WheelyMap.prototype.defaults = {
		// cities      : [],             // cities info list
		//countryZoom : 5,              // zoom to hide/show cities markers
		cityZoom: 12,
		// min zoom to show cars
		streetZoom: 13,
		icon: 'http://static.wheely.com/i/car.png',
		// car icon
		cache: true,
		onload: function () {},
		stdImgDir: 'http://static.wheely.com/i/'
	}

	window.WheelyMap.prototype.log = function (m) {
		// window.console && window.console.log && window.console.log(m);
	}



})(jQuery)

/* 
    Map legend
*/

function MapLegend(conf) {
	$.extend(this, {
		// properties
		conf: {
			selector: '#legend',
			cityTitleSelector: 'h1',
			citySelector: '.city',
			moreSelector: '.more'
		},
		el: null,
		cityTitle: null,
		geo: null,
		flagInited: null,

		// methods
		init: function () {
			$.extend(this.conf, conf);

			var that = this;
			that.flagInited = false;

			that.el = $(that.conf.selector);
			that.cityTitle = that.el.find(that.conf.cityTitleSelector);
			that.city = that.el.find(that.conf.citySelector);

/*that.geo = new WheelyCityDetector({
                complete: function(city) {
                    that.updateLegend.call(that, city)
                }
            });*/

			that.listenToKey();
		},

		setText: function (str) {
			this.textElement.html(str);
		},

		initGeolocation: function (func) {
			this.geo = new WheelyCityDetector({
				complete: function (city) {
					func.call(this, city);
				}
			});

			this.flagInited = true;
		},

		listenToKey: function () {
			var that = this;

			$(document).keydown(function (e) {
				if (e.keyCode == 76) {
					that.el.is(':visible') ? that.el.hide() : that.el.show();

					if (!that.flagInited) {
						that.initGeolocation(function (city) {
							console.log('USER LOCATION: ' + city);
						});
					}
				}
			});
		}
	});

	this.init();
	return this;
}

/* 
    City detector based on Google Geocoder
*/

function WheelyCityDetector(conf) {
	$.extend(this, {
		// properties
		conf: {
			complete: function (city) {}
		},

		geo: null,
		latLng: null,
		city: null,

		// methods
		init: function () {
			$.extend(this.conf, conf);

			var that = this;

			that.geo = new google.maps.Geocoder();
			that.sendPositionRequest();
		},

		sendPositionRequest: function () {
			var that = this;

			// First, check that the browser is capable
			if ( !! navigator.geolocation) {
				var wpid = navigator.geolocation.watchPosition(

				function (position) {
					that.geoSuccess.call(that, position);
				}, function (error) {
					that.geoError.call(that, error)
				}, {
					enableHighAccuracy: true,
					maximumAge: 30000,
					timeout: 27000
				});

			} else {
				that.error('ERROR: Your Browser doesn\'t support the Geo Location API');
			}
		},

		geoSuccess: function (position) {
			var that = this;

			that.latLng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);

			that.geo.geocode({
				location: that.latLng
			}, function (geocoderResult, status) {
				//console.log(geocoderResult);
				that.city = geocoderResult[3].address_components[0].short_name;

				if (that.city) {
					that.success();
				} else that.error('ERROR: Google geocoder returned bad address.');
			});
		},

		geoError: function (error) {
			var that = this;

			switch (error.code) {
			case error.TIMEOUT:
				that.error('ERROR: Timeout!');
				break;
			default:
				that.error('ERROR: Can\'t detect user position.');
				break;
			};
		},

		success: function () {
			this.conf.complete(this.city);
		},

		error: function (str) {
			console.log(str);
		}

	});

	this.init();
	return this;
}


/*
	Show all cities
*/
function Cities(conf) {
	$.extend(this, {
		conf: {
			wrapSelector: '#cities',
			linkSelector: '#cities-link'
		},
		
		// Properties
		el: $(),
		link: $(),
		
		// Methods
		init: function() {
			$.extend(this.conf, conf);

			var that = this;
			
			that.el = $(that.conf.wrapSelector);
			that.link = $(that.conf.linkSelector);
			
			that.link.click(function() {
				that.switchView();
			});
		},
		
		switchView: function() {
			var that = this;
			
			if (that.link.hasClass('active')) {
				that.link.removeClass('active');
				that.el.fadeIn();
			} else {
				that.link.addClass('active');
				that.el.fadeOut();
			}
		}
	});

	this.init();
	return this;
}

