google.load("maps", "2.x");

var MapController = new Class({
	address_stack: [],
	location_hash: [],
	
	map: false,
	
	Implements: [Options, Events],
	
	options: {
	    /*onLookupComplete: $empty,*/
		'zoom' : 14,
		'address_lookup_order': [
			'address_1 address_2 city state zip',
			'zip',
			'city state',
			'state'	
		],
		'controls' : [
		]
	},
	
	initialize: function(container, addresses, options){
		this.container = $(container);

		if(!this.container) return;
		
		this.setOptions(options);
		
		this.location_links = $$('.location_link');
		
		this.location = new google.maps.ClientGeocoder();
		
		this.addAddress(addresses || {});		
	},
	
	addAddress: function(addresses){

		switch($type(addresses)){
			case 'object':
				this.address_stack.push($H(addresses));

				this._lookupAddress(0, (this.address_stack.length - 1));
				
				break;
				
			case 'array':
				$each(addresses, function(obj){
					this.addAddress(obj);
				}.bind(this));
				
				break;
		}
		
		return this;
	},
	
	_getLocationString: function(order_index, address_index){
		var add = [];
		
		this.options.address_lookup_order[order_index].split(' ').each(function(part){
			if(this.address_stack[address_index].has(part)){
				add.push(this.address_stack[address_index].get(part));
			}
		}.bind(this));
		
		return add.join(' ');
	},
	
	_lookupAddress: function(index, address_index){
		var that 	= this;
		var len		= this.address_stack.length;
		var start 	= address_index || 0;
		
		for(var x = start; x < len; x++){
			var lookup 	= this._getLocationString(index, x);
			
			that.location.getLatLng(lookup, function(latlng){
	   		  	if(latlng === null && ++index < len){
					that._lookupAddress(index, start);
				}else{
				    this.location_hash.push({
				        'latlng' : latlng,
				        'address' : lookup
				    });
				    
				    this.fireEvent('lookupComplete', [latlng]);
				    this.address_index = this.location_hash.length - 1;
				    
					that._addToMap()._createLinkEvent();
				}
			}.bind(this));
		}

		return this;
	},	
	
	_addToMap: function(){
	    var index = this.address_index;
	    var latlng = this.location_hash[index].latlng;
	    var address = this.location_hash[index].address;
	    
		if(!this.map){
			this._createMap();
		}
		
		var marker = new google.maps.Marker(latlng);
		
		this.location_hash[index]['marker'] = marker;
		google.maps.Event.addListener(marker, "click", function() { 
			marker.openInfoWindowHtml(address); 
		});
		
		this.map.addOverlay(marker);
		
		return this;
	},
	
	_createLinkEvent: function(){
	    var index = this.address_index;

	    if(this.location_links.length){
	        this.location_links[index].addEvent('click', function(e){
    	        e.stop();
    	        this.location_hash[index].marker.openInfoWindowHtml(this.location_hash[index].address); 
    	    }.bind(this));
    	}
	    
	    return this;
	},
	
	_createMap: function(){
		this.map = new google.maps.Map2(this.container);
		this.map.setCenter(this.location_hash[this.address_index].latlng, this.options.zoom);
		this.map.addControl(new GSmallMapControl());
		
		return this;
	}
});