cora = cora || {};
cora.gmap = cora.gmap || {};

/**
 * Object constructor
 * Merge options and defines DOM objects
 */
cora.gmap = function(obj, options) {
	defaults = {
		markerDefault: false,
		markers: false, // default markers to show, i.e. no GET query
		mode: "full",
		zoom: 4,
		forceCenter: true, // forces center to default coords, not to first marker
		latitude: 48.019324,
		longitude: -81.826172,
		controls: ["GSmallMapControl", "GMapTypeControl"]
	};
	this.options = jQuery.extend({}, defaults, options);

	/* defines objects */
	this.target = $(obj);

	// js enable 
	this.target.parent().addClass('js-enabled');
	
	// if dom elements not defined, don't proceed
	if (typeof(this.options.elem) == 'undefined') return false;
	
	return this.init();
};

/**
 * function init()
 */
cora.gmap.prototype = {
	init: function() {

		this.gmapOptions = {
		  	zoom:         this.options.zoom,
		    controls:     this.options.controls,
		    scrollwheel:  false,
		    maptype:      G_NORMAL_MAP,
		    html_prepend: '<div class="gmap-marker">',
		    html_append:  '</div>',
		    forceCenter:  false
		};

		var $this = this;
		
		// bind onchange handler on drop down, search field and pager
		$($this.options.elem.select).change(function() {
			return $this.filter({name: $(this).attr('name'), input: ($(this).children('option:selected').val())});
		});
		
		$($this.options.elem.form).submit(function(e) {
			e.preventDefault();
			var elem = $(this).children('input[type=text]');
			if (elem.val() == "") return false;
			return $this.filter({name: elem.attr('name'), input: (elem.val())});
		});
	
		$($this.options.elem.page).children('a').click(function(e) {
			e.preventDefault();
			return $this.browsePage($(this));
		});
	
		$($this.options.elem.locate).live('click', function(e) {
			e.preventDefault();
			return $this.locateMarker($(this));
		});
	
		this.refreshPager();
	
		// we have all markers we need to show
		// show map rightaway
		this.populate({results: this.options.markers});

	},
	
	/**
	 * function getIcon()
	 */
	getIcon: function(params) {
		var path = { markers: heap.urlmap['static']+"/images/markers/" };
		
		if (params.defaultm !== undefined && params.defaultm) {
			filename = "default-small.png";
			iconsize = [21, 27];
			iconanchor = [4, 25];
		} else {
			// numbered bullets
			filename = "marker-small-"+params.number+".png";
			iconsize = [29, 39];
			iconanchor = [4, 37];
		}

		var icon = {
			image:       path.markers + filename,
			iconsize:    iconsize,
			iconanchor:  iconanchor,
			infowindowanchor:   [17, 1]
		};
		return icon;
	},
	
	/**
	 * function displayPopup()
	 */
	formatPopup: function(o) {
		var lang = heap.config.current_language;
		html = '<div class="title">' + o.title + '</div>';
		html += '<p>';
		if (o._meta['address_'+lang]) html += o._meta['address_'+lang] + ', ';
		if (o._meta['city_'+lang]) html += o._meta['city_'+lang] + ', ';
		if (o._meta['province_'+lang]) html += o._meta['province_'+lang] + ', ';
		if (o._meta['postal_code']) html += o._meta['postal_code'];
		if (o._meta['phone']) html += '<br />' + o._meta['phone'];
		html += '</p>';
		if (o._meta['hours_'+lang]) html += '<p>'+o._meta['hours_'+lang] + '</p>';
		html += '<p class="bottom"><a href="'+o.url+'">'+cora.labels['more_information']+'</a> | <a target="_blank" href="http://maps.google.ca/maps?hl='+lang+'&saddr=&daddr='+escape(o._meta['address_'+lang]+', '+o._meta['city_'+lang])+'">'+cora.labels['directions']+'</a></p>';
		return html;
	},
	
	/**
	 * function filter()
	 * filter search results
	 */
	filter: function(params) {
		
		var params = params || {};
		
		var url = $(this.options.elem.form).attr('action');
		var data = { 'ajax' : 'true' };
		if (params.input !== "") data[params.name] = params.input;
		var status = gup('status');
		if (status !== "") data.status = status;
		
		//url += params.name + '=' + params.input;
		//url += "&ajax=true"
		
		// load html in target div, repopulate gMap
		$('html, body').animate({scrollTop:0}, 'slow');
		var $this = this;
		$.ajax({
		  'type' : 'GET', 
		  'url' : url, 
		  'data' : data, 
		  'dataType' : 'html', 
		  'success' : function(response)
		  {
		    $($this.options.elem.resultsAll).html(response);
		    
  			$($this.options.elem.page).children('a').click(function(e) {
  				e.preventDefault();
  				return $this.browsePage($(this));
  			});
  		
  			var title = (params.input);
  			if (title == "") title = cora.labels['canada'];
  			if (params.name == 'q') title =  cora.labels['search_label_result'] + ' ' + title;
  			$($this.options.elem.title).html(title); // change title
  
  			$this.refreshMap(markers.filter);
  			
  			cora.ui.refresh($($this.options.elem.parent));
		  }
		});
/*
		$(this.options.elem.resultsAll).load(url, function(){
		

		});
*/
		return false;
	},
	
	/**
	 * function browsePage()
	 * bind click function on page links
	 */
	browsePage: function(elem) {
		
		$('html, body').animate({scrollTop:0}, 'slow');
		var $this = this;
		$(this.options.elem.resultsContent).load(elem.attr('href')+'&ajax=true', function(){
			$this.refreshMap(markers.filter);
		});
		
		// mark all pages as inactive
		$(this.options.elem.page)
			.removeClass('active')
			.children('a').filter('[href='+elem.attr('href')+']').parent(':not(.link)').addClass('active');
		
		return false;
	},
	
	refreshMap: function(markers) {
		
		if (typeof(markers) == 'undefined') return false;
		
		// first, remove from map all active markers (stored in $gmap.markers.current)
		// recreate them with default icon
		// create new numeral markers on map
			

		var pendingmarkers = {};
		var $this = this;
		$.each($gmap.markers.current, function(id, v) {

			// create with default icon
			var marker = cora.gmap.markers[id];
			var gicon = $.fn.gMap.createIcon({}, {icon: cora.gmap.prototype.getIcon({defaultm: true})});
			var gmarker = new GMarker(new GLatLng(marker.latitude, marker.longitude), gicon);
			gmarker.bindInfoWindowHtml($this.gmapOptions.html_prepend + marker.html + $this.gmapOptions.html_append);

			// remove marker from map, store new created one in array
			v.remove();
			
			pendingmarkers[id] = gmarker;
		});
		
		// parse new icons
		$gmap.markers.current = {};
		var i = 1;
		$.each(markers.resultset, function() {

			// create with default icon
			var marker = cora.gmap.markers[this.id];
			var gicon = $.fn.gMap.createIcon({}, {icon: cora.gmap.prototype.getIcon({number: i})});
			var gmarker = new GMarker(new GLatLng(marker.latitude, marker.longitude), gicon);
			gmarker.bindInfoWindowHtml($this.gmapOptions.html_prepend + marker.html + $this.gmapOptions.html_append);

			// remove marker from map, quickly add newly created one
			$gmap.markers.def[this.id].remove();
			$gmap.addOverlay(gmarker);
			$gmap.markers.current[this.id] = gmarker;
			$gmap.markers.def[this.id] = gmarker;			
			i++;
			
			// if new marker is also waiting in pending array, be sure to remove it, or else we'll have duplication
			if (this.id in pendingmarkers) pendingmarkers[this.id] = false;
		});

		// add each pending markers with default icon
		$.each(pendingmarkers, function(id, v) {
			if (typeof(v) == 'object') {
				$gmap.addOverlay(v);
			}
		});
		
		this.refreshPager();

		// zoom map and center accordingly
		this.fitBound($gmap.markers.current);

	},
	
	/**
	 * function refreshPager()
	 * hides pager buttons when not needed (prev and next)
	 * highlight first page if none active
	 * replace prev/next buttons with according destination href
	*/
	refreshPager: function() {
	
		var pageo = $(this.options.elem.page);
	
		var prev = pageo.filter('.prev');
		var next = pageo.filter('.next');
		var pages = pageo.children('a').filter('[rel]');
		var active = pageo.filter('.active').children('a');

		// if no href, hide link
		pageo.children('a').filter('[href=""]').parent().addClass('hidden');		
		
		prev.add(next).removeClass('hidden');
		
		if (!active.length) {
			active = pageo.children('a').filter('[rel=1]');
			active.parent().addClass('active');
		}
		var urltemp = active.attr('href');

		var page = {active: parseFloat(active.attr('rel')), total: pages.length};
		page.next = page.active+1 <= page.total ? page.active+1 : 0;
		page.prev = page.active-1 > 0 ? page.active-1 : 0;
		
		
		if (page.prev) {
			prev.children('a').attr('href', urltemp.replace(/page=[0-9]+/g, "page="+ page.prev));
		} else {
			prev.addClass('hidden');
		}
		
		if (page.next) {
			next.children('a').attr('href', urltemp.replace(/page=[0-9]+/g, "page="+ page.next));
		} else {
			next.addClass('hidden');
		}
	},
	
	/**
	 * function locateMarker()
	 * locate marker on map
	 */
	locateMarker: function(elem) {
		
		$('html, body').animate({scrollTop:0}, 'slow');
		var id = parseFloat(elem.attr('rel'));
		GEvent.trigger($gmap.markers.current[id], 'click');
		
		return false;
	},
	
	/**
	 * function prepareMarkers()
	 * prepare markers and their icons
	 * called only on first instance
	*/
	prepareMarkers: function(m) {
	
		if (m.raw == '' || m.rawpage == '') return false;
		
		// build markers clean object
		markersPageTemp = {};
		var i = 1;
		$.each(m.rawpage.resultset, function() { markersPageTemp[this.id] = i; i++; });
	
		cora.gmap.markers = {};
		markersSearch = new Array();
		$.each(m.raw, function() {
			marker = {
				latitude: this.latitude,
				longitude: this.longitude,
				id: this.id,
				html: cora.gmap.prototype.formatPopup(this)
			};
			// assign numeric icon or default icon
			if(this.id in markersPageTemp) {
				icon = cora.gmap.prototype.getIcon({number: markersPageTemp[this.id]});
				marker.type = 'current';
			} else {
				icon = cora.gmap.prototype.getIcon({defaultm: true})
			}
			marker.icon = icon;
			markersSearch.push(marker);
			
			// store marker for global use
			cora.gmap.markers[marker.id] = marker;
		});
		return markersSearch;
	},
	
	/**
	 * function populate()
	 * populate results, refresh googleMap
	 */
	populate: function(data) {

		var $this = this;
		
		// populate gmap markers
		this.gmapOptions.markers = data.results || [];
		
		// we unshift defaultMarker, populate googleMap
		if (this.options.markerDefault) this.gmapOptions.markers.unshift(this.options.markerDefault); // show marker in gmap

		// if no markers, center to default point
		if (!this.gmapOptions.markers.length || this.options.forceCenter) {
			this.gmapOptions.latitude = this.options.latitude;
			this.gmapOptions.longitude = this.options.longitude;
		}

		this.gmapOptions.forceCenter = this.options.forceCenter;

		// show the magic!
		this.target.gMap(this.gmapOptions);
	},
	
	/**
	 * function fitBound()
	 */
	fitBound: function(markers) {
		var bounds = new google.maps.LatLngBounds;
		var length = 0;
		$.each(markers, function() {
			length++;
			bounds.extend(this.getLatLng());
		});
		var newzoom = $gmap.getBoundsZoomLevel(bounds);
		var newcenter = bounds.getCenter();
		
		if (length == 0) {
			newcenter = new GLatLng(this.options.latitude, this.options.longitude);
			newzoom = this.options.zoom;
		} else if (length == 1) {
			newzoom = 11;
		}
		$gmap.setCenter(newcenter, newzoom);
	}

};
