﻿var Observer = new Class({
	options: {
		periodical: false,
		delay: 1000
	},
	initialize: function(el, onFired, options){
		this.setOptions(options);
		this.addEvent('onFired', onFired);
		this.element = $(el);
		this.listener = this.fired.bind(this);
		this.value = this.element.getValue();
		if (this.options.periodical) this.timer = this.listener.periodical(this.options.periodical);
		else this.element.addEvent('keyup', this.listener);
	},
	fired: function() {
		var value = this.element.getValue();
		if (this.value == value) return;
		this.clear();
		this.value = value;
		this.timeout = this.fireEvent.delay(this.options.delay, this, ['onFired', [value]]);
	},
	clear: function() {
		$clear(this.timeout);
		return this;
	}
});
Observer.implement(new Options);
Observer.implement(new Events);
/**
 * Autocompleter
 * @license		MIT-style license
 * @author		Harald Kirschner <mail [at] digitarald.de>
 * @copyright	Author
 */
var Autocompleter = {};

Autocompleter.Base = new Class({

	options: {
		minLength: 1,
		useSelection: true,
		markQuery: true,
		inheritWidth: true,
		maxChoices: 10,
		injectChoice: null,
		onSelect: Class.empty,
		onShow: Class.empty,
		onHide: Class.empty,
		customTarget: null,
		className: 'autocompleter-choices',
		zIndex: 42,
		observerOptions: {},
		fxOptions: {},
		overflown: []
	},
	initialize: function(el, options) {
		this.setOptions(options);
		this.element = $(el);
		this.build();
		this.observer = new Observer(this.element, this.prefetch.bind(this), $merge({
			delay: 400
		}, this.options.observerOptions));
		this.value = this.observer.value;
		this.queryValue = null;
	},	
	build: function() {
		if ($(this.options.customTarget)) this.choices = this.options.customTarget;
		else {
			this.choices = new Element('ul', {
				'class': this.options.className,
				styles: {zIndex: this.options.zIndex}
			}).injectInside(document.body);
			this.fix = new OverlayFix(this.choices);
		}
		this.fx = this.choices.effect('opacity', $merge({
			wait: false,
			duration: 200
		}, this.options.fxOptions))
			.addEvent('onStart', function() {
				if (this.fx.now) return;
				this.choices.setStyle('display', '');
				this.fix.show();
			}.bind(this))
			.addEvent('onComplete', function() {
				if (this.fx.now) return;
				this.choices.setStyle('display', 'none');
				this.fix.hide();
			}.bind(this)).set(0);
		this.element.setProperty('autocomplete', 'off')
			.addEvent(window.ie ? 'keydown' : 'keypress', this.onCommand.bindWithEvent(this))
			.addEvent('mousedown', this.onCommand.bindWithEvent(this, [true]))
			.addEvent('focus', this.toggleFocus.bind(this, [true]))
			.addEvent('blur', this.toggleFocus.bind(this, [false]))
			.addEvent('trash', this.destroy.bind(this));
	},
	destroy: function() {
		this.choices.remove();
	},
	toggleFocus: function(state) {
		this.focussed = state;
		if (!state) this.hideChoices();
	},
	onCommand: function(e, mouse) {
		if (mouse && this.focussed) this.prefetch();
		if (e.key && !e.shift) switch (e.key) {
			case 'enter':
				if (this.selected && this.visible) {
					this.choiceSelect(this.selected);
					e.stop();
				} return;
			case 'up': case 'down':
				if (this.observer.value != (this.value || this.queryValue)) this.prefetch();
				else if (this.queryValue === null) break;
				else if (!this.visible) this.showChoices();
				else {
					this.choiceOver((e.key == 'up')
						? this.selected.getPrevious() || this.choices.getLast()
						: this.selected.getNext() || this.choices.getFirst() );
					this.setSelection();
				}
				e.stop(); return;
			case 'esc': this.hideChoices(); return;
		}
		this.value = false;
	},
	setSelection: function() {
		if (!this.options.useSelection) return;
		var startLength = this.queryValue.length;
		if (this.element.value.indexOf(this.queryValue) != 0) return;
		var insert = this.selected.inputValue.substr(startLength);
		if (document.getSelection) {
			this.element.value = this.queryValue + insert;
			this.element.selectionStart = startLength;
			this.element.selectionEnd = this.element.value.length;
		} else if (document.selection) {
			var sel = document.selection.createRange();
			sel.text = insert;
			sel.move("character", - insert.length);
			sel.findText(insert);
			sel.select();
		}
		this.value = this.observer.value = this.element.value;
	},
	hideChoices: function() {
		if (!this.visible) return;
		this.visible = this.value = false;
		this.observer.clear();
		this.fx.start(0);
		this.fireEvent('onHide', [this.element, this.choices]);
	},
	showChoices: function() {
		if (this.visible || !this.choices.getFirst()) return;
		this.visible = true;
		var pos = this.element.getCoordinates(this.options.overflown);
		this.choices.setStyles({
			left: pos.left,
			top: pos.bottom
		});
		if (this.options.inheritWidth) this.choices.setStyle('width', pos.width);
		this.fx.start(1);
		this.choiceOver(this.choices.getFirst());
		this.fireEvent('onShow', [this.element, this.choices]);
	},
	prefetch: function() {
		if (this.element.value.length < this.options.minLength) this.hideChoices();
		else if (this.element.value == this.queryValue) this.showChoices();
		else this.query();
	},
	updateChoices: function(choices) {
		this.choices.empty();
		this.selected = null;
		if (!choices || !choices.length) return;
		if (this.options.maxChoices < choices.length) choices.length = this.options.maxChoices;
		choices.each(this.options.injectChoice || function(choice, i){
			var el = new Element('li').setHTML(this.markQueryValue(choice));
			el.inputValue = choice;
			this.addChoiceEvents(el).injectInside(this.choices);
		}, this);
		this.showChoices();
	},
	choiceOver: function(el) {
		if (this.selected) this.selected.removeClass('autocompleter-selected');
		this.selected = el.addClass('autocompleter-selected');
	},
	choiceSelect: function(el) {
		this.observer.value = this.element.value = el.inputValue;
		this.hideChoices();
		this.fireEvent('onSelect', [this.element], 20);
	},
	markQueryValue: function(txt) {
		return (this.options.markQuery && this.queryValue) ? txt.replace(new RegExp('^(' + this.queryValue.escapeRegExp() + ')', 'i'), '<span class="autocompleter-queried">$1</span>') : txt;
	},
	addChoiceEvents: function(el) {
		return el.addEvents({
			mouseover: this.choiceOver.bind(this, [el]),
			mousedown: this.choiceSelect.bind(this, [el])
		});
	}
});

Autocompleter.Base.implement(new Events);
Autocompleter.Base.implement(new Options);

Autocompleter.Local = Autocompleter.Base.extend({
	options: {
		minLength: 0,
		filterTokens : null
	},
	initialize: function(el, tokens, options) {
		this.parent(el, options);
		this.tokens = tokens;
		if (this.options.filterTokens) this.filterTokens = this.options.filterTokens.bind(this);
	},
	query: function() {
		this.hideChoices();
		this.queryValue = this.element.value;
		this.updateChoices(this.filterTokens());
	},
	filterTokens: function(token) {
		var regex = new RegExp('^' + this.queryValue.escapeRegExp(), 'i');
		return this.tokens.filter(function(token) {
			return regex.test(token);
		});
	}
});

Autocompleter.Ajax = {};
Autocompleter.Ajax.Base = Autocompleter.Base.extend({
	options: {
		postVar: 'value',
		postData: {},
		ajaxOptions: {},
		onRequest: Class.empty,
		onComplete: Class.empty
	},
	initialize: function(el, url, options) {
		this.parent(el, options);
		this.ajax = new Ajax(url, $merge({
			autoCancel: true
		}, this.options.ajaxOptions));
		this.ajax.addEvent('onComplete', this.queryResponse.bind(this));
		this.ajax.addEvent('onFailure', this.queryResponse.bind(this, [false]));
	},
	query: function(){
		var data = $extend({}, this.options.postData);
		data[this.options.postVar] = this.element.value;
		data['cityId'] = this.element.getProperty('rel').split(':')[1];
		this.fireEvent('onRequest', [this.element, this.ajax]);
		this.ajax.request(data);
	},	
	queryResponse: function(resp) {
		var resp = resp.substr(resp.indexOf("com\">")+5, resp.indexOf("</string>") - resp.indexOf("com\">")-5  );//.net strip		
		this.value = this.queryValue = this.element.value;
		this.selected = false;
		this.hideChoices();
		this.fireEvent(resp ? 'onComplete' : 'onFailure', [this.element, this.ajax], 20);
	}
});

Autocompleter.Ajax.Json = Autocompleter.Ajax.Base.extend({
	queryResponse: function(resp) {		
		var resp = resp.substr(resp.indexOf("com\">")+5, resp.indexOf("</string>") - resp.indexOf("com\">")-5  );//.net strip
        this.parent(resp);
		var choices = Json.evaluate(resp || false);
		if (!choices || !choices.length) return;
		this.updateChoices(choices);
	}
});

Autocompleter.Ajax.Xhtml = Autocompleter.Ajax.Base.extend({

	options: {
		parseChoices: null
	},
	queryResponse: function(resp) {
		this.parent(resp);
		if (!resp) return;
		this.choices.setHTML(resp).getChildren().each(this.options.parseChoices || this.parseChoices, this);
		this.showChoices();
	},
	parseChoices: function(el) {
		var value = el.innerHTML;
		el.inputValue = value;
		el.setHTML(this.markQueryValue(value));
	}
});

var OverlayFix = new Class({
	initialize: function(el) {
		this.element = $(el);
		if (window.ie){
			this.element.addEvent('trash', this.destroy.bind(this));
			this.fix = new Element('iframe', {
				properties: {
					frameborder: '0',
					scrolling: 'no',
					src: 'javascript:false;'
				},
				styles: {
					position: 'absolute',
					border: 'none',
					display: 'none',
					filter: 'progid:DXImageTransform.Microsoft.Alpha(opacity=0)'
				}
			}).injectAfter(this.element);
		}
	},
	show: function() {
		if (this.fix) this.fix.setStyles($extend(
			this.element.getCoordinates(), {
				display: '',
				zIndex: (this.element.getStyle('zIndex') || 1) - 1
			}));
		return this;
	},
	hide: function() {
		if (this.fix) this.fix.setStyle('display', 'none');
		return this;
	},
	destroy: function() {
		this.fix.remove();
	}
});


//MOOdalBox, Copyright (c) 2007 Razvan Brates, <http://e-magine.ro/moodalbox>, MIT Style License.
eval(function(p,a,c,k,e,d){e=function(c){return(c<a?"":e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('7 20="2W.. 2u 2v a 35 2w 2O 1P.<11 /><11 />"+"2x 36 2z.<11 /><11 />"+"<1v>2A 2j 2C O.</1v>";7 1G=18;7 1H=1y;7 1I=1y;7 21=12;7 1J=18;7 1Z=12;7 1K=18;7 1X=2c;7 1W=H;7 1M=H;7 1p={2a:h(d){6.d=2F.1w({22:1G,1k:1H,1Q:1I,1b:21,1q:1J,1D:1Z,1N:1K,1B:1X,1h:1W,1r:1M},d||{});6.1O=[];$A($$(\'a\')).1x(h(m){D(m.N&&m.L&&m.N.2H(\'^2U\',\'i\')){m.z=6.28.1C(m,6);6.1O.2J(m)}},6);6.1S=6.1T.2K(6);6.1f=6.19.y(6);6.E=n p(\'B\').J(\'v\',\'2L\').q(17.1j);6.b=n p(\'B\').J(\'v\',\'2M\').t({R:6.d.1k+\'j\',C:6.d.1Q+\'j\',W:\'-\'+(6.d.1k/2)+\'j\',u:\'14\'}).q(17.1j);6.e=n p(\'B\').J(\'v\',\'2P\').q(6.b);6.c=n p(\'B\').J(\'v\',\'2Q\').F(\'u\',\'14\').q(17.1j);6.1R=n p(\'a\').2S({v:\'2T\',L:\'#\'}).q(6.c);6.26=n p(\'B\').J(\'v\',\'2V\').q(6.c);n p(\'B\').F(\'2X\',\'2Y\').q(6.c);6.1U=n p(\'B\').J(\'v\',\'30\').1e(20);6.1R.z=6.E.z=6.O.y(6);7 l=6.l.y(6);6.k={E:6.E.23(\'S\',{16:12}).1E(),Z:6.b.25({16:6.d.22,10:l}),e:6.e.23(\'S\',{16:12,10:l}),c:6.c.25({16:18,10:l})};6.1L=32.34},28:h(V){I 6.M(V.L,V.1o,V.N)},M:h(1a,29,2b){6.L=1a;6.1o=29;6.N=2b;6.19();6.1g(2c);6.K=Q.1t()+(Q.1u()/15);6.b.t({K:6.K+\'j\',u:\'\'});6.k.E.G(0.8);I 6.1A(1a)},19:h(){6.E.t({K:Q.1t()+\'j\',C:Q.1u()+\'j\'})},1g:h(M){7 1c=$A($$(\'2e\'));1c.1w($$(1z.2f?\'2g\':\'2h\'));1c.1x(h(m){m.T.2k=M?\'2l\':\'\'});7 X=M?\'2n\':\'2o\';1z[X](\'2p\',6.1f)[X](\'Z\',6.1f);17[X](\'2q\',6.1S);6.o=0},1A:h(){D(6.o)I H;6.o=1;7 r=6.N.2s(/[0-9]+/g);6.d.1b=(r&&(r[0]>0))?r[0]:6.d.1D;6.d.1q=(r&&(r[1]>0))?r[1]:6.d.1N;6.c.t({S:\'0\',C:\'2y\',u:\'14\'});6.b.1l=\'27\';6.k.e.1E();7 l=6.l.y(6);7 13=6.13.y(6);7 2d={2B:\'2D\',2E:6.e,1h:6.d.1h,1r:6.d.1r,10:l,2G:13};6.1L=n 2I(6.L,2d).1P();I H},13:h(){6.e.1e(\'\');6.1U.2R().q(6.e);6.l();6.b.F(\'U\',\'1Y\');6.c.F(\'U\',\'1Y\');6.b.z=6.c.z=6.O.y(6)},l:h(){2Z(6.o++){P 1:6.b.1l=\'\';6.b.F(\'U\',\'24\');6.c.F(\'U\',\'24\');6.b.z=6.c.z=\'\';6.26.1e(6.1o);6.e.t({R:6.d.1b+"j",C:6.d.1q+"j"});D(6.b.1d!=6.e.1s){6.k.Z.G({C:[6.b.1d,6.e.1s]});Y}6.o++;P 2:D(6.b.1n!=6.e.1m){6.k.Z.G({R:[6.b.1n,6.e.1m],W:[-6.b.1n/2,-6.e.1m/2]});Y}6.o++;P 3:6.c.t({K:(6.K+6.b.1d)+\'j\',R:6.e.T.R,W:6.b.T.W,u:\'\'});6.k.e.G(0,1);Y;P 4:D(6.d.1B){6.k.c.G({S:[0,1],C:[0,6.c.1F]});Y}6.c.t({S:\'1\',C:6.c.1F+\'j\'});P 5:6.o=0}},1T:h(s){D((s.1V&&s.1i==\'w\')||(s.1V&&s.1i==\'x\')||(s.1i==\'31\')){6.O();s.33()}},O:h(){D(6.o<0)I;6.o=-1;2m(7 f 2r 6.k)6.k[f].2t();6.b.T.u=6.c.T.u=\'14\';6.b.1l=\'27\';6.k.E.2i(6.1g.1C(H,6)).G(0);I H}};Q.2N(1p.2a.y(1p));',62,193,'||||||this|var||||center|bottom|options|contents|||function||px|fx|nextEffect|el|new|step|Element|injectInside|aDim|event|setStyles|display|id|||bind|onclick||div|height|if|overlay|setStyle|custom|false|return|setProperty|top|href|open|rel|close|case|Window|width|opacity|style|cursor|link|marginLeft|fn|break|resize|onComplete|br|500|ajaxFailure|none||duration|document|400|position|sLinkHref|contentsWidth|elements|clientHeight|setHTML|eventPosition|setup|evalScripts|key|body|initialWidth|className|offsetWidth|clientWidth|title|MOOdalBox|contentsHeight|evalResponse|offsetHeight|getScrollTop|getHeight|em|extend|each|250|window|loadContents|animateCaption|pass|defContentsWidth|hide|scrollHeight|_RESIZE_DURATION|_INITIAL_WIDTH|_INITIAL_HEIGHT|_CONTENTS_HEIGHT|_DEF_CONTENTS_HEIGHT|ajaxRequest|_EVAL_RESPONSE|defContentsHeight|anchors|request|initialHeight|closelink|eventKeyDown|keyboardListener|error|control|_EVAL_SCRIPTS|_ANIMATE_CAPTION|pointer|_DEF_CONTENTS_WIDTH|_ERROR_MESSAGE|_CONTENTS_WIDTH|resizeDuration|effect|default|effects|caption|mb_loading|click|sLinkTitle|init|sLinkRel|true|ajaxOptions|object|ActiveXObject|select|embed|chain|anywhere|visibility|hidden|for|addEvent|removeEvent|scroll|keydown|in|match|clearTimer|there|was|with|Please|0px|again|Click|method|to|get|update|Object|onFailure|test|Ajax|push|bindWithEvent|mb_overlay|mb_center|onDomReady|your|mb_contents|mb_bottom|clone|setProperties|mb_close_link|moodalbox|mb_caption|Oops|clear|both|switch|mb_error|esc|Class|stop|empty|problem|try'.split('|'),0,{}))

var MarkerManager = new Class({//manages marker population on the map
    initialize: function(options) {
        this.map = options.map;
        this.mapId = options.mapId;
        this.markerIds = [];
        this.favs = [],
	    this.layers = [];
        this.hiddenLayers = [];
        this.icons = [];
        this.baseImageURL = options.baseImageURL;
        this.layersData = options.layers;
        if (options.layers != null && options.layers.length > 0) {
            for (var i = 0; i < options.layers.length; i++) {
                this.generateIcon(options.layers[i]);
            }
        }
    },
    addMarkers: function(markers) {//markerData: {id, desc, name ,layer ,lon, lat, icon}	    
        for (var i = 0; i < this.markerIds.length; i++) {
            if (!this.favs.contains(this.markerIds[i]))//TODO: IE detection..
                map.removeOverlay(this.markerIds[i]);
        }
        this.markerIds.extend(this.favs);
        for (var i = 0; i < markers.length; i++) {
            var currentMarker = this.markerFactory(markers[i]);
            currentMarker.params = { 'id': markers[i].id, 'category': markers[i].category, 'desc': markers[i].desc };
            this.markerIds.push(currentMarker);
            map.addOverlay(currentMarker);
        }
        //this.renderMarkers(map.getBounds(), map.getZoom())//TODO: remove once only relevant layer comes from server        
    },
    addFavs: function(markers) {//markerData: {id, desc, name ,layer ,lon, lat, icon}	    
        if (markers == null)
            return;
        for (var i = 0; i < markers.length; i++) {
            var currentMarker = this.markerFactory(markers[i]);
            currentMarker.params = { 'id': markers[i].id, 'category': markers[i].category, 'desc': markers[i].desc };
            this.favs.push(currentMarker);
            this.markerIds.push(currentMarker);
            map.addOverlay(currentMarker);
        }
    },
    removeFav: function(markerId, markerCategory) {
        for (var i = 0; i < this.favs.length; i++) {
            var el = this.favs[i];
            if (el.params.id == markerId && el.params.category == markerCategory) {
                this.favs.remove(el);
                map.removeOverlay(el);
            }
        };
    },
    renderMarkers: function(bbox, zoom) {
        var visibleLayers = this.getVisibleLayersForZoom(zoom);
        for (var i = 0; i < this.markerIds.length; i++) {
            if (visibleLayers.contains(this.markerIds[i].params.category)) {
                this.markerIds[i].show();
            }
            else
                this.markerIds[i].hide();
        }
    },
    showLayer: function(layerId) {
        if (layerId == "99") {//weather exception, refactor..
            for (var i = 0; i < this.layersData.length; i++) {
                if (this.layersData[i].id.indexOf('99') == 0)
                    this.layersData[i].vs = true;
            }
        } else {//weather exception ends	         
            var layerData = this.getLayerData(layerId);
            if (layerData.vs == true) {
                return;
            }
            this.getLayerData(layerId).vs = true;
        }
        this.renderMarkers(this.map.getBounds(), this.map.getZoom());
    },
    hideLayer: function(layerId) {
        if (layerId == 99) {//weather exception, refactor..
            for (var i = 0; i < this.layersData.length; i++) {
                if (this.layersData[i].id.indexOf('99') == 0)
                    this.layersData[i].vs = false;
            }
            this.renderMarkers(this.map.getBounds(), this.map.getZoom());
        } else {//weather exception ends	    
            var layerData = this.getLayerData(layerId);
            if (layerData.vs == false) {
                return;
            }
            else {
                layerData.vs = false;
                this.renderMarkers(this.map.getBounds(), this.map.getZoom());
            }
        }
    },
    getLayerData: function(layerId) {
        for (var i = 0; i < this.layersData.length; i++) {
            if (this.layersData[i].id == layerId)
                return this.layersData[i];
        }
    },
    getVisibleLayersForZoom: function(zoomLevel) {
        var layerIds = [];
        for (var i = 0; i < this.layersData.length; i++) {
            if (this.layersData[i].mx > zoomLevel - 1 && this.layersData[i].mn < zoomLevel + 1 && this.layersData[i].vs == true)
                layerIds.push(this.layersData[i].id);
        }
        return layerIds;
    },
    markerFactory: function(markerData) {
        var currentIcon = this.generateIcon({ c: markerData.category });
        var currentMarker = new GMarker(new GLatLng(markerData.lat, markerData.lon), currentIcon);
        currentMarker.tooltip = '<div class="tooltip">' + markerData.desc + '</div>';
        currentMarker.params = { 'id': markerData.id, 'category': markerData.category, 'desc': markerData.desc };

        //--start country marker
        if (markerData.category == "98") {
            currentMarker.category = markerData.category;
            return currentMarker;
        }
        //--End country marker

        if (markerData.category == "1_2" || markerData.category.indexOf('99') != -1) {//zoom in on city/weather markers exception
            if (!(markerData.category.indexOf('99') != -1)) {//do nothing on weather
                GEvent.addListener(currentMarker, "click", function() {
                    map.setCenter(this.getLatLng(), 12);
                });
            }
        } else {
            GEvent.addListener(currentMarker, "click", function() {
                var params = this.params;
                //TODO: add lon/lat to params
                markerManager1.openMarkerBubble(params);
            });
        }
        GEvent.addListener(currentMarker, "mouseover", function() {//bind tooltip
            markerManager1.showTooltip(this);
        });
        GEvent.addListener(currentMarker, "mouseout", function() {//bind tooltip
            tooltip.style.visibility = "hidden";
        });
        currentMarker.category = markerData.category;
        return currentMarker;
    },
    openMarkerBubble: function(params) {
        var mapId = (map.getCenter().lng() > 160) ? 2 : 3; //real time detection, refactor.	    
        var markerId = params.id;
        var markerCategory = params.category;
        var selectedMarker = this.getMarker(markerId); //TODO: condition on null
        var coords = "&lon=" + selectedMarker.getPoint().lng() + "&lat=" + selectedMarker.getPoint().lat();
        setLoader(true);
        var request = new Ajax("Dispatcher/MarkerInfo.aspx?markerId=" + markerId + "&markerCategory=" + markerCategory + "&mapId=" + mapId + coords, {
            method: 'get',
            onSuccess: function(response) {
                setLoader(false);
                this.openInfoWindowHtml(response);
                if ($('suburb')) {
                    var searchInput = $('suburb'); //AC Directions, content specific code               
                    var indicator = new Element('div', {
                        'class': 'autocompleter-loading',
                        'styles': { 'display': 'none' }
                    }).injectAfter(searchInput); // appended after the input      
                    var completer = new Autocompleter.Ajax.Json(searchInput, "webservices/GetGISData.asmx/GetSuburbsForCity", {
                        'postVar': 'query',
                        'onRequest': function(el) {
                            setLoader(false);
                        },
                        'onComplete': function(el) {
                            setLoader(false);
                        }
                    }); //End AC Directions
                }
                if ($('routeSelector')) {
                    addSelectedDD($('routeSelector'));
                }
            } .bind(selectedMarker)
        }).request();
    },
    generateIcon: function(iOptions) {
        var mCategory = iOptions.c.split('.')[0]; //chop ext
        var existingIcon = this.getIcon(mCategory);
        if (existingIcon != null) {
            return existingIcon;
        } else {
            var Icon = new GIcon();
            Icon.category = mCategory;
            Icon.image = this.baseImageURL + "i" + iOptions.c;
            var height = iOptions.h;
            var width = iOptions.w;
            Icon.iconSize = new GSize(width, height);
            //Icon.transparent = "/images/t" +  mCategory + ".png";
            //Icon.printImage  = "/images/p" + mCategory + ".png";
            if (iOptions.c.indexOf('99') == -1) {//weather icon no shadow
                Icon.shadowSize = new GSize(width * 2, height);
                Icon.shadow = this.baseImageURL + "s" + iOptions.c;
            }
            Icon.iconAnchor = new GPoint(width / 2, height);
            Icon.infoWindowAnchor = new GPoint(width / 2, height);
            this.addIcon(mCategory, Icon);
            return Icon;
        }
    },
    addIcon: function(category, icon) {
        if (this.icons.length > 0) {
            for (var i = 0; i < this.icons.length; i++) {
                if (this.icons[i].category == category)
                    return;
            }
        }
        this.icons.push(icon);
    },
    getIcon: function(category) {
        if (this.icons.length > 0) {
            for (var i = 0; i < this.icons.length; i++) {
                if (this.icons[i].category == category)
                    return this.icons[i];
            }
        }
        return null;
    },
    getMarker: function(markerId) {
        for (j = 0; j < this.markerIds.length; j++) {
            if (this.markerIds[j].params.id == markerId)
                return this.markerIds[j];
        }
        return null;
    },
    showTooltip: function(marker) {
        tooltip.innerHTML = marker.tooltip;
        var point = map.getCurrentMapType().getProjection().fromLatLngToPixel(map.getBounds().getSouthWest(), map.getZoom());
        var offset = map.getCurrentMapType().getProjection().fromLatLngToPixel(marker.getPoint(), map.getZoom());
        var anchor = marker.getIcon().iconAnchor;
        var width = marker.getIcon().iconSize.width;
        var pos = new GControlPosition(G_ANCHOR_BOTTOM_LEFT, new GSize(offset.x - point.x - anchor.x + width, -offset.y + point.y + anchor.y));
        pos.apply(tooltip);
        tooltip.style.visibility = "visible";
    }
});

/* Direction Factory */
var DirectionManager = new Class({//manages directions on the map 
	initialize: function(options) {		
		this.map = options.map;
		this.panel = options.panel;				    
	},
	getDirections : function(options) {//fork by query/points ny options here	       
	    var points = ["-36.844963,174.77069", "-37.00477,174.78267"];	        
	    this.GDir = new GDirections();
	    GEvent.addListener(this.GDir, "load", this.onDirectionLoad);
	    this.GDir.loadFromWaypoints(points,{getPolyline : true});  
	},
	onDirectionLoad : function() {	    
	    map.addOverlay(dirManager.GDir.getPolyline());	    	        
	},
	printResult : function() {	
	    var pUrl = "http://maps.google.co.nz/maps?f=d&hl=en&geocode=10131904562613516108,-36.845930,174.760840&saddr="+ this.source +"&daddr="+ this.destination +"&mra=mi&mrsp=1,0&sz=15&sll=-36.864996,174.769006&sspn=0.023588,0.049224&ie=UTF8&z=15&pw=2";
	    window.open(pUrl, "printWindow", "target=_blank,width=800px,scrollbars=yes");	    
	}
});

var map = null;
var markerManager1 = null;
var dirManager = null;

function initMap(startLon, startLat, startZ) {
	if (GBrowserIsCompatible()) {
   		map = new GMap2(document.getElementById("itineraryMap"));
        map.addControl(new GSmallMapControl());
        map.addControl(new GMapTypeControl());
        map.enableContinuousZoom();
        map.setCenter(new GLatLng(startLat, startLon), startZ);
        map.enableScrollWheelZoom();
        map.addControl(new GOverviewMapControl());        
        GEvent.addListener(map, "dragend", function() {//populate markers on pan
  			loadMarkers();  				  					
  		});
  		GEvent.addListener(map, "zoomend", function(oldZ, newZ) {//populate markers on zoom OUT only
  		    loadMarkers();  		      				  					
  		});
  		GEvent.addListener(map, "dblclick", function(oldZ, newZ) {//populate markers on zoom IN only
  			loadMarkers();	  					
  		});

  		$ES('input.RouteCB').each(function(el) {
  		    var layerId = el.getProperty('id');
  		    el.checked = false;
  		    el.addEvent('click', function(e) {//bind each one with event
  		        var isChecked = el.checked;
  		        clearRouteCBs();
  		        clearMapRoutes();
  		        el.checked = isChecked;

  		        var event = new Event(e);
  		        var element = new Element(event.target);
  		        var layerId = element.getProperty('id');
  		        var layerName = element.getProperty('name');
  		        var path = element.getProperty('rel');
  		        if (element.checked) {//expose the layers markers
  		            showRoutes(layerId, layerName, path, true);
  		            collapseOtherRoutes(null);//collapse all divs
  		        } else {//hide the layers markers
  		            showRoutes(layerId, layerName, path, false);
  		        }
  		    });
  		}); 	    	  	    
  	    
  	    $ES('input.LayerCB').each(function(el){
  	        if (el.id != "layer_1_2")
                el.checked = false;
            el.addEvent('click', function(e) {//bind each one with event
  	            loadMarkers();	        	
	        });	    
  	    });  	    
  	    
  	    document.getElementById("itineraryMap").appendChild(tooltip);
        tooltip.style.visibility="hidden";	    
  	    if($("weatherPanelContainer") != null && $("weatherPanelContainer").innerHTML == "")
  	        $("weatherPanelContainer").setStyle("display","none");  	    
  	    var closeWeather = $('closeWeather');
  	        if(closeWeather != null) {
  	            closeWeather.addEvent('click', function(e) {
		        var event = new Event(e);
		        event.stop();
		        var wContainer = $('weatherPanelContainer')
		        var element = new Element(event.target)
			        wContainer.toggleClass('Hide');    			    
			    var linkElm = element;
	            while(linkElm.nodeName != 'A')
                        linkElm = linkElm.parentNode;
	            linkElm.blur();
	            if(wContainer.hasClass('Hide')) {
	                linkElm.setText('Open +');  
	            } else {
	                linkElm.setText('Close X');
	            }      	    
	        });
	    }
	    	    
	    $('clearLink').addEvent('click', function(e) {//Top Tab Functionality
	        location.reload(true);
	    });    	    
	    $ES('#plannerTabs span a').addEvent('click', function(e) {
	        $ES('#plannerTabs .Selected').removeClass('Selected');
	        var event = new Event(e);
		    event.stop();
		    var element = new Element(event.target);
		    element.getParent().addClass('Selected');
		    element.blur();
		    if(element.getProperty('id') == 'myItinerary')
		        setItinMode(true);
		    else
		        setItinMode(false); 
	    });

	    $ES('#layersCollection span.Mag').addEvent('click', function(e) {//zoom functionality
	        var event = new Event(e);
	        event.stop();
	        var element = new Element(event.target);
	        var layerId = element.getParent().getProperty('for')
	        layerId = layerId.split('_')[1] + "_" + layerId.split('_')[2];
	        var layerData = markerManager1.getLayerData(layerId);

	        if (zoomOnMag && markerManager1.mapId == 3) {
	            map.setCenter(new GLatLng(-33.869629, 151.206955), 9);
	        } else if (zoomOnMag && markerManager1.mapId == 2) {
	            //map.setZoom(layerData.mn);
	            map.setCenter(new GLatLng(-36.847208187, 174.76707458), 9);
	        }

	        
	    });

	    refreshMarkersPanel();//update markers status   
  	    
  	    return true;//successfully initialed the map
  	} else {
  		return false;//failed to initial the map
  	}

  	
  	 
}

function clearMapRoutes() {
    routesCollection.each(function(el) {
        el.enabled = false;
    });
    refreshRoutes();
}

var selectedLayers = [];
var selectedRoutes = [];

function setItinMode(itinOnly) {    
    if(itinOnly) {        
        $('workBookLnkInfo').addClass('Hide');//swap info text
        $('myItineraryInfo').removeClass('Hide');    
        disablePanels(true);
        map.setCenter(new GLatLng(mapParams.c_lat, mapParams.c_lon), mapParams.zoom);//scale to fit country
        selectedLayers = [];
        $ES('input.LayerCB').each(function(el){//turn of markers layers and store selection in selectedLayer..
            if(el.checked == true) {            
                var layerId = el.id;
                layerId = layerId.substr(6,layerId.length-6);
  	            selectedLayers.push(layerId);
  	            el.checked = false;
  	        }
  	    });
  	    loadMarkers();        
    } else {
        $('workBookLnkInfo').removeClass('Hide');
        $('myItineraryInfo').addClass('Hide');        
        disablePanels(false);
        $ES('input.LayerCB').each(function(el){//turn of markers layers and store selection in selectedLayer..
            var layerId = el.id;
            layerId = layerId.substr(6,layerId.length-6);                        
            if(el.checked == false && selectedLayers.contains(layerId)) {               
  	            selectedLayers.push(layerId);
  	            el.checked = true;
  	        }
  	    });
  	    loadMarkers();    
    }
}

function loadMarkers() {
    var requestURL = "webservices/getmarkers.asmx/GetItineraryMarkersForBox";
    var request = new Ajax(requestURL , {
        method: "post",
        postBody: 'bbox=' + map.getBounds() + '&layers=' + getActiveLayers() + '&zoom=' + map.getZoom() + '&branchType=campers&mapId=' + markerManager1.mapId,
        onSuccess: function(response){
            var response = response.substr(response.indexOf("com\">")+5, response.indexOf("</string>") - response.indexOf("com\">")-5  );
            var responseJson = Json.evaluate(response);           
            markerManager1.addMarkers(responseJson);       
        }.bind(this)
    }).request();
    
    //Display Magnifiers 
    $ES('#layersCollection ul li').each(function(el){
        var inputCB = $E('input',el);
        var magSpan = $E('.Mag',el);
        var magId = inputCB.getProperty('id');
        magId = magId.substr(6,magId.length-6);        
        magSpan.removeClass('Zoom');   
	    if(inputCB.checked && !markerManager1.getVisibleLayersForZoom(map.getZoom()).contains(magId)) {	    
	        magSpan.addClass('Zoom');
	    }	         
  	});   
}

function getActiveLayers() {
    var layerCBs = $ES('input.LayerCB');
    var layers ='';
    for (var i=0; i< layerCBs.length; i++) {
        var layerId = layerCBs[i].getProperty('name');		    
        if(layerCBs[i].checked) {		        
	        layers +=  layerId + ',';      	    
        }
    }    
    return layers.substr(0,layers.length-1);
}

function getDirections(caller) {//bind each one with event
    var element = new Element(caller);
    var formDiv = element.parentNode;
    var streetAdr = $E('#streetAddress', formDiv);
    var suburb = $E('#suburb', formDiv);
    var dest = element.getProperty('rel');
    var origin = (streetAdr.value == "Enter Street Address" ? "" : streetAdr.value ) + " " + (suburb.value != "Enter Suburb" ? suburb.value.split(',')[0] : "") + " " + suburb.getProperty('rel').split(':')[0];
    dirManager1 = new DirectionManager({
        map: map,
        panel: $('directionsPanelBody')
    });
    dirManager1.getDirections({source:origin, destination: dest});
}

function addToFavs(params) {
    switch(params.category) {
        case '88':
            addRouteDiv(params.id);
            break;
        case '1_3':
            addFavMarker(params);
            break;
        case '1_4':
            addFavMarker(params);
            break;       
        case '1_5':
            addFavMarker(params);
            break;
        case '1_6':
            addFavMarker(params);
            break;
    }    
}

function addFavMarker(params) {
    var routeSelector = $('routeSelector');    
    if ($('fav_' + params.category + "_" +params.id) != null) {
        alert("This favourite has been already added");
        return;
    }
    var selectedRouteFavs = $E('#marker_cat_'+ params.category + ' ul');
    var favElm = new Element('LI');
    favElm.innerHTML = "<small id='fav_" + params.category + "_" + params.id + "' class='Fav Mrk_" + params.category + "' title=\"" + params.name + "\"><a class='Remove' href=\"javascript:removeFav(" + params.id + ", '" + params.category + "');\">x</a>" + (params.name.length > 25 ? /*possible trim point : params.name.substr(0, 25) + ".."*/ params.name : params.name) + "</small>";
    favElm.injectTop(selectedRouteFavs);    
    selectedRouteFavs.getParent().getParent().removeClass('Collapse');

    //update counter
    var counterElm = $E('small', selectedRouteFavs.getParent().getParent());
    var categoryLength = selectedRouteFavs.getChildren().length;
    counterElm.innerHTML = "("+ categoryLength +")";
    counterElm.removeClass('Hidden'); 
    
    var favsArray = new Array();//push into manager
    favsArray.push({id:params.id, lon: params.lon, lat: params.lat, category: params.category, address:'', name:params.name, desc: params.name})
    markerManager1.addFavs(favsArray);       
}

var routesCollection = [];//refactor into RouteMan

function getRouteForId(routeId) {
    for(var i=0; i< routesCollection.length; i++) {
        if(routesCollection[i].id == routeId)
            return routesCollection[i];
    }
   return null;
}

function refreshRoutes() {        
    for(var i=0; i< routesCollection.length; i++) {//irerate and expose visibles
        if(routesCollection[i].poly != null && routesCollection[i].enabled) {
            map.addOverlay(routesCollection[i].poly);
        } else {
            map.removeOverlay(routesCollection[i].poly);
        }
    }
}

function addRouteDiv(routeId){
    if($('route_itin_' + routeId) != null) {
        alert('This driving route has already been added to your itinerary planner');
        return;
    }
    clearRouteCBs();
    var request = new Ajax("Dispatcher/RouteInfo.aspx?routeId=" + routeId + "&mapId=" + markerManager1.mapId, {
        method: 'get',
        onSuccess: function(response) {
            if (response.indexOf('RouteElm') > 0) { //has route
                var routeLI = new Element('li');
                routeLI.innerHTML = response;
                routeLI.injectInside($('selectedRouteList'));
                $('workBook').removeClass('Empty');
                favRoutes.push(this);

                //hide empty msg if any:
                $E('#selectedRouteList li.emptyMsgText').addClass('Hide');
                
                collapseRoute($E('.RouteElm',routeLI));                
            }
        } .bind(routeId)
    }).request();
}

function collapseRoute(caller) {
    var routeElm = new Element(caller);    
    while(!routeElm.hasClass('RouteElm'))
	    routeElm = routeElm.getParent();
	routeElm.toggleClass('Collapse');

	var enableRoute = !routeElm.hasClass('Collapse');	
	var routeId = routeElm.id.split('_')[2];

	clearMapRoutes();//--
	for (var i = 0; i < routesCollection.length; i++) {//remove from map
	    if (routesCollection[i].id == routeId)
	        routesCollection[i].enabled = enableRoute;
	}
	refreshRoutes();
	if (!enableRoute) {
	    clearRouteCBs();
	    clearMapRoutes();
	}  else {
	    collapseOtherRoutes(routeElm);
	}  
}

function collapseOtherRoutes(openDiv) {
    $ES('.RouteElm', 'selectedRouteList').each(function(el) {
        if(el != openDiv)
            el.addClass('Collapse');
    });
}

function clearRouteCBs() {
    $ES('input', 'routesCollection').each(function(el) {
        el.checked = false;
    });   
}

function collapseMarker(caller) {
    var routeElm = new Element(caller);
    while(!routeElm.hasClass('MarkerCat'))
	    routeElm = routeElm.getParent();
	routeElm.toggleClass('Collapse');
}

function removeRoute(caller) {    
    if (!confirm("Select OK to remove this driving route from your Itinerary."))
	    return;
    var routeElm = new Element(caller);
    while(!routeElm.hasClass('RouteElm'))
	    routeElm = routeElm.getParent();
	routeElm.getParent().remove();
	
	//turn on the empty msg:
	if ($ES("#selectedRouteList li").length == 1)
	    $E('#selectedRouteList li.emptyMsgText').removeClass('Hide');
}

function addSelectedDD(selectElm) {
    var numSelected = 0;    
    for(var i=0; i< routesCollection.length; i++) {//irerate and get selected
        if(routesCollection[i].selected = true){
            numSelected++;
            selectElm.options[selectElm.options.length]= new Option(routesCollection[i].name, routesCollection[i].id);
        }
    }
    if (numSelected>0) {
       selectElm.getParent().removeClass('Hidden'); 
    }
}

function showRoutes(layerId, layerName, pathStr, enable) {
    var selectedRouteId = layerId.split('_')[1];
    var selectedRoute = getRouteForId(selectedRouteId);
    if (selectedRoute == null) {//add new route to the collection
        selectedRoute = {id: selectedRouteId, poly: null, enabled : enable, selected : false, name : layerName};       
        var dir1 = null;
        var points = Json.evaluate(pathStr);
        dir1 = new GDirections();          
        routesCollection.push(selectedRoute);
        GEvent.addListener(dir1, "load", function() {
            for(var i=0; i< routesCollection.length; i++) {
                if(routesCollection[i].poly == null) {
                    routesCollection[i].poly = dir1.getPolyline();
                    routesCollection[i].poly.id = routesCollection[i].id
                    GEvent.addListener(routesCollection[i].poly, "mouseover", function() { $('itineraryPlanner').cursor = "pointer"; });
                    GEvent.addListener(routesCollection[i].poly, "click", function() {
		                var selectedRouteElm = getRouteForId(this.id);
                        var routeId = selectedRouteElm.id;
                        var request = new Ajax("Dispatcher/MarkerInfo.aspx?markerId=" + routeId +"&markerCategory=88", {
		                    method: 'get',
		                    onSuccess: function(response){                     
	                            map.openInfoWindowHtml(this.poly.getVertex(0),response);                          
	                        }.bind(selectedRouteElm)
                        }).request();				  					
	                });
                }
            }
            refreshRoutes();          
        });
        dir1.loadFromWaypoints(points,{getPolyline : true});
    } else {//route exists update its visibility
        for(var i=0; i< routesCollection.length; i++) {
            if(routesCollection[i].id == selectedRouteId)
                routesCollection[i].enabled = enable;              
        }
        refreshRoutes();
    }
    //TODO: Hide all polylines
    //TODO: Show only the one with ID : selectedRouteId
    //TODO: using <refreshRoutes();>     
}

function openModal(url, params, caption, width, height) {
    MOOdalBox.open(url + "?" + params, caption, width, height);
}

function getFavs() {
    var favsStr = "";
    var favElms = $ES("#markerListcontainer .Fav");
    for(var i=0; i< favElms.length; i++) 
        favsStr += favElms[i].id + ",";
    if(favsStr.length> 0)
        favsStr.substr(0, favsStr.length-1);//trim tail
    return favsStr;
}

function removeFav(markerId, category) {
    markerManager1.removeFav(markerId, category);
    var liElm = $("fav_" + category + "_" + markerId).getParent();
    liElm.remove();    
    var selectedRouteFavs = $E('#marker_cat_' + category + ' ul');
    var counterElm = $E('small', selectedRouteFavs.getParent().getParent());
    var categoryLength = selectedRouteFavs.getChildren().length;
    counterElm.innerHTML = "(" + categoryLength + ")";
    if (categoryLength == 0) {
        counterElm.addClass('Hidden');
        $E('#marker_cat_' + category).addClass('Collapse');
    }       
}

function refreshMarkersPanel() {
    $ES('.MarkerCat').each(function(el) {
        //update counter
        var counterElm = $E('small', el);
        var markersUL = $E('ul', el);
        var categoryLength = markersUL.getChildren().length;
        counterElm.innerHTML = "(" + categoryLength + ")";
        if (categoryLength > 0) {
            counterElm.removeClass('Hidden');
            el.removeClass('Collapse');
        } else {
            counterElm.addClass('Hidden');
        }
    });
}

function getselectedRoutes() {
    var routeCSV = "";
    for (var i=0; i< favRoutes.length; i++) {
        routeCSV += favRoutes[i] + (i<favRoutes.length-1 ? "," : "");
    };    
    return routeCSV;
}

function sendEmail() {
    var favs= getFavs();
    var routes = getselectedRoutes();
    if(favs == "" && routes == "") {
        alert("Please select at least one favourite or route first.") 
        return;
    }    
    url = "TestEncode.aspx";
    params = "favs=" + favs + "&routes=" + routes + "&mapId=" + markerManager1.mapId;
    openModal(url,params,"", "580 320");
}

function printMap() {
    var favs = getFavs();
    var routes = getselectedRoutes();
    if (favs == "" && routes == "") {
        alert("Please select at least one favourite or route first.")
        return;
    }
    url = "PrintMap.aspx";
    params = "favs=" + favs + "&routes=" + routes + "&mapId=" + markerManager1.mapId;
    openModal(url, params, "", "580 320");
}



function copyToClipboard(elm){
	if(window.ie) {
        Copied = elm.createTextRange();
        Copied.execCommand("Copy");
    }
    elm.select();    
}

function disablePanels(disable) {
    if (disable)
        $('routesSelector').addClass('Disabled');
    else
        $('routesSelector').removeClass('Disabled');
    
    $ES('#routesSelector input').each(function(el){
        el.disabled = disable;           
  	});
  	$ES('#routesSelector label').each(function(el){
        if (disable)
            el.addClass('Disabled');
        else
            el.removeClass('Disabled');        
  	});}

function setLoader(enable) {
    if (enable)
        $('ajaxLoader').addClass('Enabled');
    else
        $('ajaxLoader').removeClass('Enabled');
}

function bindAddThisLink(adLnk) {
    var url = "TestEncode.aspx";
    var favs = getFavs();
    var routes = getselectedRoutes();    
    var params = "favs=" + favs + "&routes=" + routes + "&mapId=" + markerManager1.mapId;
    var request = new Ajax(url + "?" + params, {
        method: 'get',
        onSuccess: function(responseText) {
            var favsURL = responseText.split('txt')[1];
            addthis_open(this, '', favsURL, '[TITLE]');
        } .bind(adLnk)
    }).request();
}
