'use strict';

define(['GeoLocator'],
	function (GeoLocator) {
		var App = function() {
			// Start position for the map (hardcoded here for simplicity)
			var lat=45.8070;
			var lon=9.0850;
			var zoom=1;

			var map; //complex object of type OpenLayers.Map
			var markers; // markers layer
			var direction; // compass and dot layer
			
			var icon;
			var compass;
			
			var fromProjection  = new OpenLayers.Projection("EPSG:4326"); // transform from WGS 1984
			var toProjection = new OpenLayers.Projection("EPSG:900913"); // to Spherical Mercator Projection

			var extent = new OpenLayers.Bounds(9.04323,45.7807,9.1282,45.8309).transform(fromProjection,toProjection);
			var position   = new OpenLayers.LonLat(lon, lat).transform( fromProjection, toProjection);
			var resolutions = OpenLayers.Layer.Bing.prototype.serverResolutions.slice(15, 19);

			var geoloc;

			var update_by_gps = false;
			
			var dom_btn_gps; // elemento dom del bottone gps
			
			// START!
			init();
			
			/* non credo che serva...
			// Get rid of address bar on iphone/ipod
			var fixSize = function() {
			    window.scrollTo(0,0);
			    document.body.style.height = '100%';
			    if (!(/(iphone|ipod)/.test(navigator.userAgent.toLowerCase()))) {
				if (document.body.parentNode) {
				    document.body.parentNode.style.height = '100%';
				}
			    }
			};
			setTimeout(fixSize, 700);
			setTimeout(fixSize, 1500);
			**/
			
			function init() {
				// elementi dom
				dom_btn_gps = document.getElementById("geolocate");
				dom_btn_gps.addEventListener('click', on_btn_gps_click);

				// create map
				map = new OpenLayers.Map({
					div: "map",
					theme: null,
					controls: [
					    new OpenLayers.Control.Attribution(),
					    new OpenLayers.Control.TouchNavigation({
						    dragPanOptions: { enableKinetic: true }
					    }),
					    new OpenLayers.Control.Zoom()
					],
					projection: toProjection,
					displayProjection: fromProjection,
					restrictedExtent : extent,
					eventListeners: {
					    move: onMapMove
					}
				});
				
				// livello mappa. carica tile da disco. limita lo zoom
				var mapLayer = new OpenLayers.Layer.OSM(
					"Como", 
					"tiles/${z}/${x}/${y}.png", 
					{zoomOffset:15, resolutions:resolutions}
				);
				map.addLayer(mapLayer);
				
				markers = new OpenLayers.Layer.Vector(
				    "Markers",
				    {
					styleMap: new OpenLayers.StyleMap({
						"default": {
						externalGraphic: "img/icon.png",
						graphicWidth: 40,
						graphicHeight: 42,
						graphicXOffset: -8,
						graphicYOffset: -34,
						rotation: "${angle}"
					    }
					})
				    }
				);		
				map.addLayer(markers);

				// livello bussola
				direction = new OpenLayers.Layer.Vector(
				    "Direction",
				    {
					styleMap: new OpenLayers.StyleMap({
					    "default": {
						externalGraphic: "img/${image}.png",
						graphicWidth: 120,
						graphicHeight: 120,
						graphicXOffset: -60,
						graphicYOffset: -60,
						rotation: "${angle}",
						//label : "${dist}",
						/*
						fontColor: "${favColor}",
						fontSize: "12px",
						fontFamily: "Courier New, monospace",
						fontWeight: "bold",
						labelAlign: "${align}",
						labelXOffset: "${xOffset}",
						labelYOffset: "${yOffset}",
						labelOutlineColor: "white",
						labelOutlineWidth: 3*/
					    }
					})
				    }
				);
				map.addLayer(direction);

				// crea la bussola e la aggiunge al livello
				compass = new OpenLayers.Feature.Vector(
					new OpenLayers.Geometry.Point(position.lon,position.lat) ,
					{angle: 180, image:"compass"}
				);
				direction.addFeatures([compass]);
				
				// carica le coordinate dagli stalli
				updatepoints();
				
				// start geoloc
				geoloc = new GeoLocator(geolocUpdate, geolocError);
				
				
				// centra la mappa
				if( ! map.getCenter() ){
					map.setCenter (position, zoom);
				}
				
			}
			
			function geolocUpdate(event){
				// accendo il bottone, avviso il sistema che sto muovendo la mappa
				// per via del gps..
				update_by_gps = true;
				dom_btn_gps.classList.remove('wait');
				dom_btn_gps.classList.add('on');
				// muovo la mappa
				var crd = event.coords;
				var point = new OpenLayers.LonLat(crd.longitude, crd.latitude).transform( fromProjection, toProjection);
				map.setCenter(point, map.getZoom(), true);
				//markers.refresh({force:true,params: { 'key': Math.random()} });
				markers.redraw(true);
				//direction.refresh({force:true,params: { 'key': Math.random()} });
				direction.redraw(true);
			}

			function geolocError(event){
				//console.log(event);
			}

			
			function updateCompass(point){
				// ricentra il compasso
				compass.move(point);
			
				// trova lo stallo più vicino
				var closest = markers.features[0];
				if (closest == undefined){ return -1; }
				var closest_dist = closest.geometry.distanceTo(compass.geometry);
				var k; var dist;
				for (k in markers.features) {
					dist = markers.features[k].geometry.distanceTo(compass.geometry);
					if (dist<closest_dist){
						closest = markers.features[k];
						closest_dist = dist;
					}
				}
				// calcola l'angolo e gira il compasso
				dist = compass.geometry.distanceTo(closest.geometry, {details:true});
				var a = ( Math.atan2( (dist.y1-dist.y0) , (dist.x1-dist.x0) ) / (2*Math.PI) ) * 360;
				compass.attributes.angle = -a;
				if (dist.distance<(120/map.zoom)) {
					compass.attributes.image = "compass2";
				} else {
					compass.attributes.image = "compass";
				}
				
				markers.refresh({force:true});
				direction.refresh({force:true});
				return 0;
			}
			
			
			function onMapMove(event) {
				if (!update_by_gps) {
					// il movimento non è stato avviato dal gps.
					// spengo il bottone e blocco il gps
					dom_btn_gps.classList.remove('on');
					geoloc.disable();
				}
				update_by_gps = false;
				updateCompass(map.getCenter());
			}

			function on_btn_gps_click(event) {
				dom_btn_gps.classList.add('wait');
				// avvio il gps
				geoloc.enable();
			}
			
		    
			function reqListener () {
				var points = JSON.parse(this.responseText);
				var features = [];
				var k; var pos;
				for (k in points.elements) {
					var p = points.elements[k];
					pos =  new OpenLayers.LonLat(p.lon, p.lat).transform( fromProjection, toProjection);
					//markers.addMarker(new OpenLayers.Marker(pos, icon.clone()));
					features.push(
					    new OpenLayers.Feature.Vector(
						new OpenLayers.Geometry.Point(pos.lon,pos.lat)
					    )
					);
				}
				markers.addFeatures(features);
			}

			function updatepoints() {
				var oReq = new XMLHttpRequest();
				oReq.onload = reqListener;
				//oReq.open("get", "http://overpass.osm.rambler.ru/cgi/interpreter?data=[out:json];node[amenity=bicycle_rental]%2845.78812,9.05823,45.82162,9.11144%29;out;", true);
				oReq.open("get", "data.json", true);
				oReq.send();
			}
		};
		
		return App;
	
	}
);