
Ext.namespace('GFactory.Map');

GFactory.Map =  Ext.extend(Object, {
        constructor: function(config){
			
			Ext.apply(this, config || {}, {
				map : null,
			    userpopup : null,
			    zoom : 4,
			    slideFactor : 50,
			    ajaxk : 0,
			    bounds : null,
			    ctimeout : null,
			    locations : {},
			    geocoder : new GClientGeocoder(),
				callbacks : {}
			});
			
			
			this.gphy = new OpenLayers.Layer.Google("Google Physical", {
		        type: G_PHYSICAL_MAP,
		        sphericalMercator: true
		    });
			
			var mapOptions = {
		        projection: new OpenLayers.Projection("EPSG:900913"),
		        units: "m",
		        maxResolution: 156543.0339,
		        maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34, 20037508.34, 20037508.34),
		        eventListeners: {
		            "scope": this,
		            "moveend": this.mapEvent,
		            "zoomend": this.zoomEvent,
		            "click": this.click,
		            "dblclick": this.click
		        }
		    };
			
			this.map = new OpenLayers.Map(config.div, mapOptions);    		

			
		    this.markers = new OpenLayers.Layer.Markers("Markers", mapOptions);
		    this.markersself = new OpenLayers.Layer.Markers("Markers", mapOptions);
		    
		    this.map.addLayers([this.gphy, this.markers, this.markersself]);
		    
		    
		    var size = new OpenLayers.Size(53, 53);
		    var offset = new OpenLayers.Pixel(-(size.w / 2), -size.h / 2);
		    this.icon10000 = new OpenLayers.Icon(document.STATIC_URL + 'css/openlayers/img/markers/2.png', size, offset);
		    
		    var size = new OpenLayers.Size(44, 44);
		    var offset = new OpenLayers.Pixel(-(size.w / 2), -size.h / 2);
		    this.icon1000 = new OpenLayers.Icon(document.STATIC_URL + 'css/openlayers/img/markers/3.png', size, offset);
		    
		    var size = new OpenLayers.Size(40, 40);
		    var offset = new OpenLayers.Pixel(-(size.w / 2), -size.h / 2);
		    this.icon100 = new OpenLayers.Icon(document.STATIC_URL + 'css/openlayers/img/markers/4.png', size, offset);
		    
		    var size = new OpenLayers.Size(35, 35);
		    var offset = new OpenLayers.Pixel(-(size.w / 2), -size.h / 2);
		    this.icon10 = new OpenLayers.Icon(document.STATIC_URL + 'css/openlayers/img/markers/5.png', size, offset);
		    
		    var size = new OpenLayers.Size(30, 34);
		    var offset = new OpenLayers.Pixel(-5, -size.h);
		    this.icon1H = new OpenLayers.Icon(document.STATIC_URL + 'css/openlayers/img/markers/user-blue.png', size, offset);
		    this.icon1F = new OpenLayers.Icon(document.STATIC_URL + 'css/openlayers/img/markers/user-pink.png', size, offset);
		    
		    var size = new OpenLayers.Size(30, 34);
		    var offset = new OpenLayers.Pixel(-5, -size.h);
		    this.icon = new OpenLayers.Icon(document.STATIC_URL + 'css/openlayers/img/markers/user-orange.png', size, offset);
		    
		    
		    document.viewProfile = function(id){
		        url = "/" + document.site_lang + '/profile/display/' + id + '/'
		        setTimeout("window.location.href = url", 0);
		    }
		    
		    controls = this.map.getControlsByClass('OpenLayers.Control.Navigation');
		    for (var i = 0; i < controls.length; ++i) {
		        controls[i].disableZoomWheel();
		    }
			
			var mapEl = Ext.get(this.map.div)
		    mapEl.wrap({
		        tag: 'div',
		        cls: 'GFmap'
		    });
		    mapEl.createChild({
		        tag: 'div',
		        cls: 'ox-openlayers-control',
		        children: [{
		            tag: 'div',
		            cls: 'ox-openlayers-control-pan',
		            children: [{
		                tag: 'span',
		                cls: 'ox-openlayers-control-pan-north',
		                html: 'north'
		            }, {
		                tag: 'span',
		                cls: 'ox-openlayers-control-pan-west',
		                html: 'west'
		            }, {
		                tag: 'span',
		                cls: 'ox-openlayers-control-pan-east',
		                html: 'east'
		            }, {
		                tag: 'span',
		                cls: 'ox-openlayers-control-pan-south',
		                html: 'south'
		            }]
		        }, {
		            tag: 'div',
		            cls: 'ox-openlayers-control-zoom',
		            children: [{
		                tag: 'span',
		                cls: 'ox-openlayers-control-zoom-in',
		                html: 'zoom in'
		            }, {
		                tag: 'span',
		                cls: 'ox-openlayers-control-zoom-reset',
		                html: 'zoom reset'
		            }, {
		                tag: 'span',
		                cls: 'ox-openlayers-control-zoom-out',
		                html: 'zoom out'
		            }]
		        }]
		    
		    })
		    
		    
		    this.map.setCenter(new OpenLayers.LonLat(0, 0), 1);
		    mapEl.child('.ox-openlayers-control-pan-north').on('mousedown', function(){
		        this.map.pan(0, -this.slideFactor)
		    }, this);
		    mapEl.child('.ox-openlayers-control-pan-east').on('mousedown', function(){
		        this.map.pan(this.slideFactor, 0)
		    }, this);
		    mapEl.child('.ox-openlayers-control-pan-west').on('mousedown', function(){
		        this.map.pan(-this.slideFactor, 0)
		    }, this);
		    mapEl.child('.ox-openlayers-control-pan-south').on('mousedown', function(){
		        this.map.pan(0, this.slideFactor)
		    }, this);
		    mapEl.child('.ox-openlayers-control-zoom-in').on('mousedown', function(){
		        this.map.zoomIn()
		    }, this);
		    mapEl.child('.ox-openlayers-control-zoom-reset').on('mousedown', function(){
		        this.map.zoomToMaxExtent()
		    }, this);
		    mapEl.child('.ox-openlayers-control-zoom-out').on('mousedown', function(){
		        this.map.zoomOut()
		    }, this);
			
		},
		
	on : function(event, callback, scope){
    
        if (this.callbacks[event] == undefined) {
            this.callbacks[event] = []
        }
        this.callbacks[event].push({
            callback: callback,
            scope: scope
        });
    },
    
    _callback : function(event, args){
        if (this.callbacks[event] == undefined) 
            return;
        l = this.callbacks[event].length
        for (var i = 0; i < l; i++) {
            c = this.callbacks[event][i];
            c.callback.apply(c.scope || this, args)
            
        }
    },
	
	zoomEvent : function(event){
        try {
            if (this.userpopup != null) {
                this.userpopup.hide();
            }
        } 
        catch (e) {
        }
        this.zoom = event.object.zoom
        clearTimeout(this.ctimeout);
        var self = this;
        this.ctimeout = setTimeout(function(){
            self.loadCluster()
        }, 200);
        
    },
    searchLocation : function(searchString, callback, scope){
        var locations = []
        
        if (this.locations[searchString] == undefined) {
            var self = this;
            this.geocoder.getLocations(searchString, function(response){
                ;
                maxp = 0;
                p = null;
                locations = response.Placemark;
                for (var i = 0; i < locations.length; i++) {
                    place = locations[i];
                    if (place.AddressDetails.Accuracy > maxp) {
                        maxp = place.AddressDetails.Accuracy;
                        p = place;
                    }
                }
                
                conv = OpenLayers.Layer.SphericalMercator.forwardMercator(p.Point.coordinates[0], p.Point.coordinates[1]);
                
                p.Point.coordinates[0] = conv['lon'];
                p.Point.coordinates[1] = conv['lat'];
                
                self.locations[location] = p
                callback.apply(scope || self, [p])
            });
        }
        else {
            return this.locations[searchString]
            
        }
    },
    
    
    getZoomFromBox : function(lon1, lon2, lat1, lat2, convert){
        if (convert == true) {
            conv = OpenLayers.Layer.SphericalMercator.forwardMercator(lon1, lat1);
            lon1 = conv['lon'];
            lat1 = conv['lat'];
            conv = OpenLayers.Layer.SphericalMercator.forwardMercator(lon2, lat2);
            lon2 = conv['lon'];
            lat2 = conv['lat'];
        }
        z = this.gphy.getZoomForExtent(new OpenLayers.Bounds(lon2, lat2, lon1, lat1));
        return z;
    },
    
    setCenter : function(lon, lat, zoom, convert){
        if (convert == true) {
            conv = OpenLayers.Layer.SphericalMercator.forwardMercator(lon, lat);
            lon = conv['lon'];
            lat = conv['lat'];
        }
        this.map.setCenter(new OpenLayers.LonLat(lon, lat), zoom)
    },
    
    moveMeTo : function(lonlat){
        lonlat = lonlat.transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913"));
        marker = new OpenLayers.Marker(lonlat, this.icon.clone())
        this.markersself.clearMarkers()
        this.markersself.addMarker(marker);
        marker.events.register("click", marker, function(evt){
            return false;
        });
        marker.events.register("dblclick", marker, function(evt){
            return false;
        });
    },
    
    click : function(event){
        try {
            var lonlat = this.map.getLonLatFromViewPortPx(event.xy);
            lonlat.transform(new OpenLayers.Projection("EPSG:900913"), new OpenLayers.Projection("EPSG:4326"));
            this._callback('clickOnMap', [event, lonlat]);
        } catch(e) {
            
        }
        return false;
    },
    
    mapEvent : function(event){
        mapBounds = this.gphy.getExtent();
        this.bounds = mapBounds.transform(new OpenLayers.Projection("EPSG:900913"), new OpenLayers.Projection("EPSG:4326")).toArray();
        clearTimeout(this.ctimeout);
        var self = this;
        this.ctimeout = setTimeout(function(){
            self.loadCluster()
        }, 200);
    },
	
	loadCluster : function(){
		this.ajaxk++;
		DirectUser.geojson(this.bounds, this.zoom, this.ajaxk, function(response, provider){
			
				if (response.ajaxk != this.ajaxk) {
					return;
				}
				this.markers.clearMarkers()
				for (var i = 0; i < response.features.length; i++) {
					point = response.features[i];
					if (point.properties.count > 1000) {
						ico = this.icon10000.clone();
						cls = 'cls10000';
					}
					else 
						if (point.properties.count > 100) {
							ico = this.icon1000.clone();
							cls = 'cls1000';
						}
						else 
							if (point.properties.count > 10) {
								ico = this.icon100.clone();
								cls = 'cls100';
							}
							else 
								if (point.properties.count > 1) {
									ico = this.icon10.clone();
									cls = 'cls10';
								}
								else {
									if (point.properties.users.length == 1 && point.properties.users[0].sex == 'F') {
										ico = this.icon1F.clone();
									}
									else {
										ico = this.icon1H.clone();
									}
									cls = 'cls1';
								}
					var coordinates = OpenLayers.Layer.SphericalMercator.forwardMercator(point.geometry.coordinates[0], point.geometry.coordinates[1]);
					if (point.properties.count > 1) {
						var marker = new OpenLayers.Marker.Label(new OpenLayers.LonLat(coordinates['lon'], coordinates['lat']), ico, point.properties.count)
						Ext.get(marker.labelDiv).addClass(cls);
					}
					else {
						var marker = new OpenLayers.Marker(new OpenLayers.LonLat(coordinates['lon'], coordinates['lat']), ico)
					}
					marker.properties = point.properties;
					this.markers.addMarker(marker);
					var self = this;
					marker.events.register("mousedown", marker, function(evt){
						try {
							this.userpopup.hide();
						} 
						catch (e) {
						}
						if (this.properties.users.length > 0) {
							this.userpopup = new OpenLayers.Popup("", this.lonlat, new OpenLayers.Size(190, 145), "loading...");
							self.map.addPopup(this.userpopup);
							
							Ext.get(this.userpopup.div).load("/users/popup/" + this.properties.users[0].id + '/');
							Ext.get(this.userpopup.div).addClass('userPopup')
							Ext.get(this.userpopup.div).on('mousedown', function(){
								try {
									this.userpopup.hide();
								} 
								catch (e) {
								}
							}, this);
							this.userpopup.panIntoView()
						}
					});
					
				}
			
		
		}, this);
	}
		
});
