
var KWMap_marker_type = function(obj){
	this.name = obj.name;
	this.image = obj.image;
	this.wd = obj.wd;
	this.ht = obj.ht;
	this.x = obj.x;
	this.y = obj.y;
	this.visible = obj.visible;
	this.mouseover = obj.mouseover;
	this.mouseout = obj.mouseout;
	this.click = obj.click;
	this.byoption = obj.byoption;
	this.altimg = obj.altimg;
}


var KWMap_marker_layer = function(layer_name, map){
	this.map = map;
	this.layer_name = layer_name;
	this.marker_lists = new Object(); 
	this.marker_keys  = new Object();
	this.marker_types = new Object();
	this.public_state = new Object();

	
	this.marker_layer = new OpenLayers.Layer.Markers(this.layer_name ,{minResolution:0.000010,maxResolution:0.513848});
	this.map.addLayer(this.marker_layer);

	
	this.state = function (key, value){
		if(value !== undefined){
			this.public_state[key] = value;
		}
		return this.public_state[key];
	}

	
	this.marker_type_add = function(mt){
		this.marker_types[mt.name] = mt;
	}

	this.marker_type_get = function(mt_name){
		return this.marker_types[mt_name];
	}

	
	this.marker_add = function(name, ll, data){
		var mt = this.marker_types[name];
		var alt;
		var img;

		if(mt === undefined){
			
			return null;
		}

		img = mt.image;
		alt = mt.altimg;

		if(mt.byoption == 1){
			if(data.option){
				img = mt.image + data.option + '.png';
			}
			if(mt.altimg){
				alt = mt.altimg + data.option + '.png';
			}
		}

		var foobar = kw_decode_txt(ll);
		var foobar_arr = foobar.split(';');
		
		var new_marker = this._create_marker(mt, new OpenLayers.LonLat(foobar_arr[1], foobar_arr[0]), img);
		if(data === undefined){
			var data = {};
		}

		new_marker.kwdata = data;

		
		if((new_marker.kwdata !== undefined) && (new_marker.kwdata.title !== undefined)){
			new_marker.icon.imageDiv.title = new_marker.kwdata.title;
		}			

		new_marker.kwset_zindex = function(n){
			
			// n is the state
			// 0 normal
			// 1 highlight
			if(n == 0){
				this.icon.imageDiv.style.zIndex = '100';
			} else if(n == 1){
				this.icon.imageDiv.style.zIndex = '101';
			}
		}
		new_marker.kwset_zindex(0);

		new_marker.kwmarker_data = {	'layer_name'   : this.layer_name,
						'marker_type'  : mt.name,
						'index'        : 0,
						'kwmap_ml'     : this,
						'imgurl'       : img,
						'alturl'       : alt
					};

		if(mt.visible){
			new_marker.icon.display(true);
		} else {
			new_marker.icon.display(false);
		}
	
		if(mt.click !== undefined){
			if(KW_PAGE_CONFIG.device_type === 'touch'){
				new_marker.events.register("touchstart", new_marker, function(e) {
					if ( e.touches.length == 1 ) {
					/* Ignore if the marker is touched as part of a doubletouch (pinch) */
					}
					//mt.click(new_marker);
				});
				new_marker.events.register("click", new_marker, function(e) {
					mt.click(new_marker);
				});
			} else {
				new_marker.events.register("click", new_marker, function(e) {
					mt.click(new_marker);
				});
			}
		}

		if(mt.mouseover !== undefined){
			new_marker.events.register("mouseover", new_marker, function(e) {
				mt.mouseover(new_marker);
			});
		}

		if(mt.mouseout !== undefined){
			new_marker.events.register("mouseout", new_marker, function(e) {
				mt.mouseout(new_marker);
			});
		}

		if(this.marker_lists[mt.name] === undefined){
			this.marker_lists[mt.name] = new Array();
		}

		if(this.marker_keys[mt.name] === undefined){
			this.marker_keys[mt.name] = new Object();
		}

				
		new_marker.kwmarker_data.index = this.marker_lists[mt.name].length;
		this.marker_lists[mt.name].push(new_marker);
		this.marker_layer.addMarker(new_marker);
		new_marker.icon.imageDiv.style.cursor = 'pointer';

		if((data !== undefined) && (data.key !== undefined)){
			this.marker_keys[mt.name][data.key] = new_marker;
		}
		
		return new_marker;
		
	}; // end marker_add

	
	this.markers_update = function(uobject){
		var bound = new OpenLayers.Bounds();
		var marker;
		var smarker;
		var i;
		var key;
		var type;
		var ll;
		var data;

		this.marker_layer.setVisibility(false);

		// Clear the old markers from the search keys
		for(type in uobject){
			for(i in this.marker_lists[type]){
				marker = this.marker_lists[type][i];
				marker.icon.display(false);
				key = marker.kwdata.key;

				if(this.marker_keys[type] !== undefined && this.marker_keys[type][key] !== undefined){
					// Delete the marker
					delete this.marker_keys[type][key];
				}
			}
		}	
		var k = 0;
		for(type in uobject){
			for(i in uobject[type]){
				if(i >= this.marker_lists[type].length){
					// Make a new marker
					marker = this.marker_add(type, uobject[type][i].ll, uobject[type][i].data); 	
				} else {
					// Reuse Maker
					marker = this.marker_lists[type][i];
					if((uobject[type][i].data !== undefined) && (uobject[type][i].data.key !== undefined)){
	
						// Create the key list if if does not exist.
						if(this.marker_keys[type] === undefined){
							this.marker_keys[mt.name] = new Object();
						}

						// Add the new marker to the key list
						this.marker_keys[type][uobject[type][i].data.key] = marker;
					}

					// Add the new data into the new marker
					marker.kwdata = uobject[type][i].data;
					ll = uobject[type][i].ll;
					var foobar = kw_decode_txt(ll);
					var foobar_arr = foobar.split(';');
					marker.lonlat = new OpenLayers.LonLat(foobar_arr[1], foobar_arr[0]);

					// update images.
					var mt = this.marker_types[type];
					if(mt.byoption == 1){
						var alt = mt.altimg;
						var img = mt.image;
						var d = uobject[type][i].data;
						if(mt.byoption == 1){
							if(d.option){
								img += d.option + '.png';
							}
							if(mt.altimg){
								alt += d.option + '.png';
							}
						}
				
						if(marker.icon.url !== img){
							marker.setUrl(img);	
							marker.kwmarker_data.imgurl = img;
							marker.kwmarker_data.alturl = alt;
							marker.kwset_zindex(0);
						}
					}
				}
				// Create a new boundry
				if(k++ < 100){ 
					bound.extend(marker.lonlat);
				}
				marker.icon.display(true);
			}
		}

		if(typeof(bound.top) === 'number'){
			this.marker_layer.setVisibility(true);
		}
		return bound;
	}

	
	this.marker_update_by_i = function(type, i, ll, data){
		if(this.marker_lists[type] === undefined || this.marker_lists[type][i] === undefined){
			return 0;
		}

		var marker = this.marker_lists[type][i];
		marker.kwdata = data;
		delete this.marker_keys[type][data.key];

		if((data !== undefined) && (data.key !== undefined)){
			this.marker_keys[type][data.key] = marker;
		}
		return 1;
	}
		
	
	this.marker_get_by_i = function(type, i){
		if(this.marker_lists[type] !== undefined){
			return this.marker_lists[type][i];
		}
	};

	
	this.marker_get_by_key = function(type, key){
		if(this.marker_keys[type] !== undefined){
			return this.marker_keys[type][key];
		}
	};

	
	this._create_icon = function(mt,img){
		if(img === undefined){
			return new OpenLayers.Icon(	mt.image, 
							new OpenLayers.Size(mt.wd,mt.ht), 
							new OpenLayers.Pixel(-mt.x,-mt.y));
		} else {
			return new OpenLayers.Icon(	img, 
							new OpenLayers.Size(mt.wd,mt.ht), 
							new OpenLayers.Pixel(-mt.x,-mt.y));
		}
	};

	
	this._create_marker = function(mt, ll, img){
		return new OpenLayers.Marker(ll,this._create_icon(mt,img));
	};

	return this;
}


function KWMap_on_zoomend() {
	var iz;
	for ( iz=0; iz < this.numZoomLevels; iz++ ) {
		this.kw_map_scale_icon_list[iz].display(false);
	}
	this.draw_scale();
}


function kw_highlight_marker(new_marker){
	var i  = new_marker.kwmarker_data.index;
	var ml = new_marker.kwmarker_data.kwmap_ml;
	var m  = ml.marker_get_by_i("normal", i);
	var ms = ml.marker_get_by_i("normal_shadow", i);

	if(m.kwmarker_data.alturl){
		m.setUrl(m.kwmarker_data.alturl);
	} else {
		m.setUrl(ml.marker_type_get("highlight").image);
	}

	if(ms.kwmarker_data.alturl){
			ms.setUrl(ms.kwmarker_data.alturl);
	} else {
		ms.setUrl(ml.marker_type_get("highlight_shadow").image);
	}

	m.kwset_zindex(1);
}

function kw_highlight_marker_off(new_marker){
	var i  = new_marker.kwmarker_data.index;
	var ml = new_marker.kwmarker_data.kwmap_ml;
	var m  = ml.marker_get_by_i("normal", i);
	var ms = ml.marker_get_by_i("normal_shadow", i);

	if(m.kwmarker_data.imgurl){
		m.setUrl(m.kwmarker_data.imgurl);
	} else {
		m.setUrl(ml.marker_type_get("normal").image);
	}
	m.kwset_zindex(0);
	if(ms.kwmarker_data.imgurl){
		ms.setUrl(ms.kwmarker_data.imgurl);
	} else {
		ms.setUrl(ml.marker_type_get("normal_shadow").image);
	}
}

function mouseover_action(new_marker) {
	var i = new_marker.kwmarker_data.index;
	
	kw_highlight_marker(new_marker);

	if(KW_MAP_API.enabled !== 1){
		
		
		KWResults.kwresult_highlight(i);
	}
}

function mouseout_action(new_marker) {
	var i = new_marker.kwmarker_data.index;
	
	
		if(KW_VARS.current_detail !== new_marker){
			kw_highlight_marker_off(new_marker);
		}
	

	if(KW_MAP_API.enabled !== 1){
		KWResults.kwresult_highlight_off(i);
	}

}

function click_action(new_marker) {
	var i  = new_marker.kwmarker_data.index;
	var ml = new_marker.kwmarker_data.kwmap_ml;
	var m  = ml.marker_get_by_i("normal", i);
	
	if(KW_PAGE_CONFIG.device_type === 'touch'){
		var x = kwFindPosX(m.icon.imageDiv);
		var y = kwFindPosY(m.icon.imageDiv);
		document.location = "kw:markerClick:" + m.kwdata.key + ":" + x + ":" + y;
		return;
	}

	
	if(KW_VARS.current_detail !== undefined){
		kw_highlight_marker_off(KW_VARS.current_detail);
	}
	KW_VARS.current_detail = new_marker;
	kw_highlight_marker(new_marker);

	DD_remove_markers();

	kwshow_detail(m.kwdata.key);

	var p = Math.floor(i / KWResults.results_per_page);
	if(p !== KWResults.page_current) {
		KWResults.show_page(p);
	}

	KWMap_zoom(m.lonlat.lat, m.lonlat.lon, KW_PAGE_CONFIG.detail_zoom_level);
}

function kw_on_resize() {
	kwresize();
}

function kwresize () {
	if(KW_VARS.mapdone !== 1){
		return;
	}
	// resize map when page resized
	document.getElementById('LOCAL_MAP').style.width = KWMap_width() + 'px';
	document.getElementById('LOCAL_MAP').style.height = KWMap_height() + 'px';
	if(KW_PAGE_CONFIG.device_type !== 'touch'){
		localmap.controls[0].redraw();
	}
	localmap.updateSize();
	localmap.draw_copyright();
	
		localmap.draw_scale();
	
	// move markers and copyright - not done yet
	
		KW_VARS.vlpoi.moveTo(localmap.getCenter());
		KW_VARS.vlpoi.onMapResize();
		kwmap_ol();
	
	
}

function KWMap_width() {
	var wt;
	if(KW_MAP_API.enabled == 1){
		if(KW_MAP_API.width > 0){
			wt = KW_MAP_API.width;
		} else {
			wt = windowWidth() - KW_MAP_API.padding_width;
		}

		wt = Math.min(KW_MAP_API.max_width, wt);
		wt = Math.max(KW_MAP_API.min_width, wt);
		return wt;
	}
 
	if(KW_VARS.current_page=='details')
	{	wt = windowWidth() - KW_PAGE_CONFIG.det_width - KW_PAGE_CONFIG.horizontal_margins;
		wt = Math.min(KW_PAGE_CONFIG.max_det_map_width, wt);
		wt = Math.max(KW_PAGE_CONFIG.min_det_map_width, wt);
	}
	else if(KW_VARS.current_page=='dd')
	{	wt = windowWidth() - KW_PAGE_CONFIG.dd_width - KW_PAGE_CONFIG.horizontal_margins;
		wt = Math.min(KW_PAGE_CONFIG.max_dd_map_width, wt);
		wt = Math.max(KW_PAGE_CONFIG.min_dd_map_width, wt);
	}
	else	// search results page or other
	{	wt = windowWidth() - KW_PAGE_CONFIG.sr_width - KW_PAGE_CONFIG.horizontal_margins;
		wt = Math.min(KW_PAGE_CONFIG.max_sr_map_width, wt);
		wt = Math.max(KW_PAGE_CONFIG.min_sr_map_width, wt);
	}
	return wt;
}

function KWMap_height () {
	var ht;
	if(KW_MAP_API.enabled == 1){
		if(KW_MAP_API.height > 0){
			ht = KW_MAP_API.height;
		} else {
			ht = windowHeight() - KW_MAP_API.padding_height;
		}

		ht = Math.min(KW_MAP_API.max_height, ht);
		ht = Math.max(KW_MAP_API.min_height, ht);
		return ht;
	}
	
		ht = windowHeight() - KW_PAGE_CONFIG.unusable_height;
	

	if(KW_VARS.current_page=='details')
	{	ht = Math.min(KW_PAGE_CONFIG.max_det_map_height, ht);
		ht = Math.max(KW_PAGE_CONFIG.min_det_map_height, ht);
	}
	else if(KW_VARS.current_page=='dd')
	{	

		ht = Math.min(KW_PAGE_CONFIG.max_dd_map_height, ht);
		ht = Math.max(KW_PAGE_CONFIG.min_dd_map_height, ht);
	}
	else	// (KW_VARS.current_page=='results')
	{	ht = Math.min(KW_PAGE_CONFIG.max_sr_map_height, ht);
		ht = Math.max(KW_PAGE_CONFIG.min_sr_map_height, ht);
	}

	// subtract top/bottom border of map
	border = "1px";
	b = border.replace('px','');
	ht -= b*2;

	return ht;
}

function KWMap_style(){
	var map_div = document.getElementById('LOCAL_MAP');
	map_div.style.height = KWMap_height () + 'px';
	map_div.style.width = KWMap_width () + 'px';
}

function KWMap_zoom(lat, lon, zoom) {
	var location = new OpenLayers.LonLat;
	location.lat = lat;
	location.lon = lon;
	localmap.setCenter(location,zoom,1,1)
	if ( localmap.hl_marker ) {
		localmap.hl_marker.icon.display(false);
	}
	if ( localmap.hl_shadow ) {
		localmap.hl_shadow.icon.display(false);
	}
}	

function KWMap_panTo(lat, lon) {
	var location = new OpenLayers.LonLat;
	location.lat = lat;
	location.lon = lon;
	localmap.panTo(location);
}	

function KWMap_Bounds() {
	var that = new OpenLayers.Bounds();
	that.extend_by_loc = function(loc) {
		var foobar = kw_decode_txt(loc);
		var foobar_arr = foobar.split(';');
		this.extend(new OpenLayers.LonLat(foobar_arr[1],foobar_arr[0]));
	}
	return that;
}

function DD_markers(lat_start, lon_start, lat_end, lon_end, key) {
	var dl = localmap.plugins["standard_dd_layer"];

	if(dl === undefined){
		return;
	}

	
	
	var nl = localmap.plugins["standard_marker_layers"];
	nl.state("current_dd", key);

	var n = nl.marker_get_by_key("normal", key);
	var ns = nl.marker_get_by_key("normal_shadow", key);
	n.icon.display(false);
	ns.icon.display(false);

	var dds  = dl.marker_get_by_i("dd_start",  0);
	var dde  = dl.marker_get_by_i("dd_end",    0);
	var ddss = dl.marker_get_by_i("dd_shadow", 0);
	var ddes = dl.marker_get_by_i("dd_shadow", 1);

	dds.lonlat  = new OpenLayers.LonLat(lon_start, lat_start);
	ddss.lonlat = new OpenLayers.LonLat(lon_start, lat_start);
	dde.lonlat  = new OpenLayers.LonLat(lon_end, lat_end);
	ddes.lonlat = new OpenLayers.LonLat(lon_end, lat_end);
		
	dds.icon.display(true);
	ddss.icon.display(true);
	dde.icon.display(true);
	ddes.icon.display(true);

	var bound = new OpenLayers.Bounds();
	bound.extend (dds.lonlat);
	bound.extend (dde.lonlat);

	localmap.zoomToExtent(bound);
	var startpixel = localmap.getPixelFromLonLat(dds.lonlat);
	var endpixel = localmap.getPixelFromLonLat(dde.lonlat);

	if (startpixel.y < - dds.icon.offset.y || endpixel.y < - dde.icon.offset.y || 
			startpixel.x < - dds.icon.offset.x || endpixel.x < - dde.icon.offset.x ||
			localmap.getSize().w - startpixel.x < dds.icon.size.w + dds.icon.offset.x ||
			localmap.getSize().w - endpixel.x < dde.icon.size.w + dde.icon.offset.x) {
		localmap.zoomOut();
	}
}

function DD_remove_markers() {
	var dl = localmap.plugins["standard_dd_layer"];
	if(dl === undefined){
		return;
	}

	var nl = localmap.plugins["standard_marker_layers"];
	var key = nl.state("current_dd");
	if(key === undefined){
		return;
	}
	nl.state("current_dd", undefined);

	var n = nl.marker_get_by_key("normal", key);
	var ns = nl.marker_get_by_key("normal_shadow", key);
	n.icon.display(true);
	ns.icon.display(true);

	dl.marker_get_by_i("dd_start",  0).icon.display(false);
	dl.marker_get_by_i("dd_end",    0).icon.display(false);
	dl.marker_get_by_i("dd_shadow", 0).icon.display(false);
	dl.marker_get_by_i("dd_shadow", 1).icon.display(false);
}

function kwFindPosX(obj)
{
	var curleft = 0;
	if(obj.offsetParent)
		while(1) 
		{
			curleft += obj.offsetLeft;
			if(!obj.offsetParent)
				break;
			obj = obj.offsetParent;
		}
	else if(obj.x)
		curleft += obj.x;
	return curleft;
}

function kwFindPosY(obj)
{
	var curtop = 0;
	if(obj.offsetParent)
		while(1)
		{
			curtop += obj.offsetTop;
			if(!obj.offsetParent)
				break;
			obj = obj.offsetParent;
		}
	else if(obj.y)
		curtop += obj.y;
	return curtop;
}



	

	function kw_poi_mouseout(f,p){
		var ll = localmap.getLonLatFromViewPortPx(p);
		kwsearch({ll: ll.lat + "," + ll.lon, stype: 'poimove'});
	}

	function kwmap_click_search(evt){
		var ll = localmap.getLonLatFromViewPortPx(new OpenLayers.Pixel(evt.xy.x, evt.xy.y) );
		kwsearch({ll: ll.lat + ", " + ll.lon, stype: 'click'});
	}

	
	function kwmap_search_onmove(m){
		if(m === 'end'){
			if(KW_VARS.current_map_bounds){
				var center = localmap.getCenter();
				if(!KW_VARS.current_map_bounds.containsLonLat(center)){
					if(KW_VARS.current_page && KW_VARS.current_page == 'results'){
						kwsearch({ll: center.lat + ", " + center.lon, stype: 'pan'});
					}
				}
			}
		}
	}



(function() {
    window.KWExtendedDevice = { };
})();
KWExtendedDevice.CLASS_NAME = "KWExtendedDevice"
KWExtendedDevice.touch_events = ["touchstart", "touchmove", "touchhold", "touchend", "touchcancel" ];
KWExtendedDevice.gesture_events = ["gesturechange", "gesturestart", "gestureend"];
KWExtendedDevice.touch_devices = [ "ipad", "iphone", "ipodtouch" ];
KWExtendedDevice.supported_devices = [ "ipodtouch", "iphone", "ipad" ];
KWExtendedDevice.OLHandler = {};
KWExtendedDevice.OLControl = {};
KWExtendedDevice.isinstance = function(instance, klass){
         if(instance.CLASS_NAME==klass.prototype.CLASS_NAME) {
             return true;
         }
         return false;
};
KWExtendedDevice.initialize = function(device,openlayers) {
    if (this.supported_devices.toString().indexOf(device) == -1) {
	return;
    } 
    this.type = device;
    this.isTouchDevice = KWExtendedDevice.touch_devices.toString().indexOf(device) > -1;
    if ( openlayers && this.isTouchDevice ) {
	/* * Add touch_events to OL */
	for(var i=0; i<KWExtendedDevice.touch_events.length; i++) {
		OpenLayers.Events.prototype.BROWSER_EVENTS.push(KWExtendedDevice.touch_events[i]);
		OpenLayers.Map.prototype.EVENT_TYPES.push(KWExtendedDevice.touch_events[i]);
	}
	for(var i=0; i<KWExtendedDevice.gesture_events.length; i++) {
		OpenLayers.Events.prototype.BROWSER_EVENTS.push(KWExtendedDevice.gesture_events[i]);
		OpenLayers.Map.prototype.EVENT_TYPES.push(KWExtendedDevice.gesture_events[i]);
	}

	/* * Decorate getMousePosition */
	var getMousePosition = OpenLayers.Events.prototype.getMousePosition;
	OpenLayers.Events.prototype._old_getMousePosition = getMousePosition;
	OpenLayers.Events.prototype.getMousePosition = function (evt){
		if (KWExtendedDevice.touch_events.toString().indexOf(evt.type) > -1){
			if(evt.touches.length == 1){
				evt.clientX = evt.touches[0].clientX;
				evt.clientY = evt.touches[0].clientY;
			} else if ( evt.touches.length == 2 ) {
				evt.clientX = (evt.touches[0].clientX+evt.touches[1].clientX)/2;
        			evt.clientY = (evt.touches[0].clientY+evt.touches[1].clientY)/2;
			}
		}
		return this._old_getMousePosition(evt);
	};
    }
}
/*
 * OpenLayers Controls define the abstract actions to be accomplished with the screen objects
 * examples: pan, zoom, select, etc.
 * OpenLayers Handlers translate the device events into Control actions: 
 * Example: the Drag Handler maps the (device) 'touchmove' event to the (ol control) DragPan 'pan' action
 */

/* Add OpenLayers controls 
 * ExtendedNavigation ( class for extended device navigation of openlayers )
 *     TouchZoom
 *     DragPan
 * OrientationChange
 */


KWExtendedDevice.OLHandler.Pinch = OpenLayers.Class(OpenLayers.Handler, {
    /*
     * A guesture where we only care about scale and center, but not
     * rotation
     *
     * callbacks: 'scale', 'zoom'
     */

    pinching: false,
    pinched: false,
    interval: '0', 
    touchmove: function(evt){
	evt.preventDefault(); /* prevent iphone/itouch/ipad scaling */
        if(this.pinching && evt.touches.length == 2 ) {
	   	this.new_scale = evt.scale;
		var pinchCenter = this.map.events.getMousePosition(evt);
		if ( !this.pinchLonLat ) {
		/* record the lat/lon of the starting pinch */
        		this.pinchLonLat = this.map.getLonLatFromPixel(pinchCenter);
		}
		this.pinchXY = pinchCenter;
            	if (!this.timeoutId ) {
			this.pinched = true;
                	this.callback('scale', [evt.scale, this.pinchXY]);/*this.control.scaleMap(evt);*/
			if ( this.interval > 0) {
                		this.timeoutId = setTimeout(OpenLayers.Function.bind(this.removeTimeout, this), this.interval+'ms');
			}
            	} 
        }  
    },
    removeTimeout: function() {
        this.timeoutId = null;
	if ( this.pinching && this.scale != this.new_scale ) {
	/* need to account for any movement since last timeout was set*/
               	this.callback('scale', [this.new_scale,this.pinchXY]);/*this.control.scaleMap(evt);*/
	}
    },

    gesturestart:function(evt){
        evt.preventDefault(); /*disable iphone/itouch/ipad pinch open gesture*/
	this.pinching = true;
	this.pinched = false;
	this.control._init_zoom(evt);
	this.pinchLonLat = null;
    },
    gesturecancel: function(evt){
	this.pinching = false;
    },

    gestureend:function(evt){
        evt.preventDefault(); /*disable iphone/itouch/ipad pinch close gesture*/
	if ( this.pinched ) {
		this.callback('zoom', [evt]);
	}
	this.pinching = false;
	this.pinched = false;
    },

    CLASS_NAME: "KWExtendedDevice.OLHandler.Pinch"
});
KWExtendedDevice.OLHandler.DoubleTap = OpenLayers.Class(OpenLayers.Handler, {

    timeout: 500,

    doubletap_timer:false,
    in_doubletap:false,

    tap1:null,
    tap2:null,

    /*
     * we want to cancel the doubletap if the touchmoves
     */

    touchmove: function(evt){
	evt.preventDefault(); /* prevent scrolling */
        if(this.in_doubletap == true){
//console.warn("touchmove:dtap");
            this.in_doubletap = false;
            this.doubletap_timer = false;
            this.tap1 = null;
            this.tap2 = null;
        }
    },

    touchstart: function(evt){
        evt.preventDefault();
        if(evt.touches.length == 1) {
            if(!this.doubletap_timer){
            }

            // start here
            if(!this.in_doubletap) {
                this.tap1 = evt.xy;
                this.in_doubletap = true;
                function setTap(obj){
			return function () {
                    obj.in_doubletap = false;
                    obj.doubletap_timer = false;
			}
                }
        	var timeout = this.timeout;
                this.doubletap_timer = setTimeout(setTap(this), timeout);
            } else {
                var center = this.center;
                this.tap2 = evt.xy;
                this.in_doubletap = false;
                var args = [evt, evt.xy];
                this.callback('doubletap', args);
                this.center = null;
            }
        } 
    },

    CLASS_NAME: "KWExtendedDevice.OLHandler.DoubleTap"
});

KWExtendedDevice.OLControl.TouchZoom = OpenLayers.Class(OpenLayers.Control, {
    /**
     * A control for using the touch paradign to zoom on a map
     */

    doubleTapClass:KWExtendedDevice.OLHandler.DoubleTap,

    pinchClass:KWExtendedDevice.OLHandler.Pinch,

    doubleTapHandler:null,

    pinchHandler:null,

    scale: 1,
    minZoom: 2,
    maxZoom: 0,
    zoom:"out",
    zoomMomentum: '',

    /*
     * true: tapping only zooms in
     * false: tapping alternates
     */

    tapZoomInOnly: true,

    // alter to just zoom in ala mobile google map

    tapZoom: function(evt, xy){
        var out = "out";
        var newCenter = this.map.getLonLatFromPixel(xy);
        if (this.zoom == null ||  this.tapZoomInOnly || this.zoom == out){
            this.map.setCenter(newCenter,this.map.getZoom() + 1,true,true);
            this.zoom = "in";
            } else {
                this.map.setCenter(newCenter,this.map.getZoom() - 1,true,true);
                this.zoom = out;
            }
    },

    initialize: function(options) {
        this.handlers = [];
        OpenLayers.Control.prototype.initialize.apply(this, arguments);
	this.maxZoom = this.map.getNumZoomLevels() - 1;
/* This stuff doesn't work smoothly
	var callback_binder = function(obj) {
		return function(evt) {
			console.warn("callback evt"+evt.type);
			obj.zoomMap();
		}
	}
	this.map.layerContainerDiv.addEventListener('webkitTransitionEnd', 
					callback_binder (this) ,
					false );
*/
    },

    activate: function(){
        for(var i=0; i<this.handlers.length; i++){
            this.handlers[i].activate();
        }
        return OpenLayers.Control.prototype.activate.apply(this,arguments);
    },

    deactivate: function(){
        for(var i=0; i<this.handlers.length; i++){
            this.handlers[i].deactivate();
        }
        return OpenLayers.Control.prototype.deactivate.apply(this,arguments);
    },

    _init_zoom: function(evt) {
	this.zoomRes = this.map.getResolutionForZoom(this.map.getZoom());
	var zoomOutRes = this.map.getResolutionForZoom(2);
	this.centerLatLon = this.map.getCenter();
	this.map_wid = KWMap_width();
	this.map_hgt = KWMap_height();
	if ( z == this.maxZoom ) {
		this.zoomInLimit = 1.0;
	} else {
		var zoomInRes = this.map.getResolutionForZoom(this.maxZoom);
		this.zoomInLimit = (this.zoomRes/zoomInRes);
	}
	this.zoomOutLimit = (this.zoomRes/zoomOutRes);
//console.warn("zoomOutRes="+zoomOutRes+" zoomRes:"+zoomRes+" zoomInRes:"+zoomInRes);
//console.warn("this.maxZoom="+this.maxZoom+" zoom="+z+ " zInL:"+this.zoomInLimit+" zOutL:"+this.zoomOutLimit);
    },

    _get_zoom_resolution_for_scale: function(evt) {
	var newRes = this.zoomRes / evt.scale;
//console.warn("_get_zoom_res scale:"+evt.scale+" zoomRes:"+this.zoomRes+" newRes:"+newRes);
	var next_zoom = this.map.getZoom();
	mapRes = this.zoomRes;
	var previousRes = mapRes;
	if ( evt.scale > 1.0) {
	/* zoom in */
		while ( mapRes > newRes && next_zoom < this.maxZoom ) {
			next_zoom += 1;
			previousRes = mapRes;
			mapRes = this.map.getResolutionForZoom(next_zoom);
		}
		if ( this.zoomMomentum > 0 ) {
		/* user has dilated, but started to  pinch back in,
		 * so round to nearest actual zoom level
		 */
//console.warn("rounded");
			var midRes = (previousRes+mapRes)/2;
			if ( newRes > midRes ) {
				mapRes = previousRes;
			}
		} 
	} else if ( evt.scale < 1.0) {
	/* zoom out */
		while ( mapRes < newRes && next_zoom > this.minZoom ) {
			next_zoom -= 1;
			previousRes = mapRes;
			mapRes = this.map.getResolutionForZoom(next_zoom);
		}
		if ( this.zoomMomentum < 0 ) {
		/* user has pinched, but started to dilate back out,
		 * so round to nearest actual zoom level
		 */
//console.warn("rounded");
			var midRes = (previousRes+mapRes)/2;
			if ( newRes < midRes ) {
				mapRes = previousRes;
			}
		} 
	}  
	return(mapRes);
    },

    scaleMap: function(new_scale,pinch_xy) {
    /* resize the map images, but don't effectively "zoom" the map which
     * requires loading of tiles
     */
	if ( this.pinchHandler.pinching ) {
	    var scaleDiv = '';
	    var translateDiv = '';
	    var center = this.map.getCenter();
	    var zLev = this.map.getZoom();

	    this.centerOffset = new OpenLayers.Pixel( Math.round( (pinch_xy.x - this.map_wid/2) ),
								  Math.round( (pinch_xy.y - this.map_hgt/2) )) ;
	    var offsetx = 0;
	    var offsety = 0;
	    var newRes = this.zoomRes ;

	    /* If we are at maximum zoom out then can only rescale if scale > 1.0 */
	    if ( zLev > this.minZoom || new_scale > 1.0 ) {
	    	if ( (new_scale <= this.zoomInLimit && new_scale >= this.zoomOutLimit )) {
			scaleDiv = ' scale('+new_scale+') ';
			offsetx =  Math.round((this.map_wid - (this.map_wid * new_scale))*0.5);
			offsety =  Math.round((this.map_hgt - (this.map_hgt * new_scale))*0.5);
	   		this.scale = new_scale;
	    		/* momentum > 0.0 == zoom out, momentum < 0.0. == zoom in */
			this.zoomMomentum = this.scale - new_scale;
			newRes /= new_scale;
		}
	    }
	    var translatedCenter = new OpenLayers.LonLat(
				this.pinchHandler.pinchLonLat.lon - (newRes*this.centerOffset.x) ,
				this.pinchHandler.pinchLonLat.lat + (newRes*this.centerOffset.y) );
	    offsetx += Math.round((center.lon-translatedCenter.lon)/newRes);
	    offsety -= Math.round((center.lat-translatedCenter.lat)/newRes);
//console.warn("new_scale:"+new_scale+" xoffset:"+this.centerOffset.x+" yoffset:"+this.centerOffset.y);
	    var translateDiv = ' translate('+offsetx+'px,'+offsety+'px)';
	    this.map.layerContainerDiv.style.webkitTransform =   translateDiv + scaleDiv ;
       }
    },
    zoomMap: function(evt) {
	var zRes = this._get_zoom_resolution_for_scale(evt);
	zTarget = this.map.getZoomForResolution(zRes);
	var snap_scale = this.zoomRes/zRes;
//	if ( this.pinchHandler.pinching ) {
//console.warn("snapped scale:"+snap_scale);
//console.warn("   this.scale:"+this.scale);
//console.warn("zoomMap (ztarget="+zTarget+") (current z="+this.zoom+")");
//console.warn("zoomMap("+zRes+")");
		if ( snap_scale != this.scale ) {
			this.scaleMap(snap_scale,this.pinchHandler.pinchXY);
		}
//	}
	
	var numZ = this.map.getNumZoomLevels();
	if ( zTarget < numZ && zTarget >= 0 ) {
//console.warn("current:"+this.map.getZoom()+ " zoomTo: "+zTarget);
		var newCenter = this.map.getCenter();
		if ( this.pinchHandler.pinching ) {
//console.warn("old center lat:"+newCenter.lat+" lon:"+newCenter.lon);
//console.warn("pinch      lat:"+this.pinchHandler.pinchLonLat.lat+" lon:"+this.pinchHandler.pinchLonLat.lon);
//console.warn(" zres:"+zRes+" y:"+this.centerOffset.y+"x:"+this.centerOffset.x);
			newCenter.lat = this.pinchHandler.pinchLonLat.lat + (zRes*this.centerOffset.y);
			newCenter.lon = this.pinchHandler.pinchLonLat.lon - (zRes*this.centerOffset.x);
//console.warn("new center lat:"+newCenter.lat+" lon:"+newCenter.lon);
		}
//console.warn("current z:"+this.map.getZoom()+"    raw scale:"+evt.scale+" zTarget:"+zTarget);
        	this.map.setCenter(newCenter,zTarget,true,true);
		//this.map.zoomTo(zTarget) ;
	}
	var newRes = this.map.getResolution();
if ( newRes != zRes ) {
//	console.warn("not the same scale...");
}
	var new_scale = newRes/this.mapRes;
	
	/* return the device view to normal */
	this.map.layerContainerDiv.style.left = '0px';
	this.map.layerContainerDiv.style.top = '0px';
	this.map.layerContainerDiv.style.webkitTransform = 'scale(1.0)';
	this.scale = 1.0;
    },

    draw: function(){
        if(this.doubleTapClass != null){
            this.doubleTapHandler =
                new this.doubleTapClass(this, {doubletap: this.tapZoom});
            this.handlers.push(this.doubleTapHandler);
        }

        if(this.pinchClass != null){
            this.pinchHandler =
                new this.pinchClass(this, {scale:this.scaleMap, zoom:this.zoomMap });
            this.handlers.push(this.pinchHandler);
        }
    },

    limitZoomOut: function(){
        // Set the most zoomed out level allowed
        if ( this.map.getZoom() <= 1 ) {
            return true;
        }
        return false;
    },

    CLASS_NAME: "KWExtendedDevice.OLControl.TouchZoom"

});

KWExtendedDevice.OLHandler.Drag = OpenLayers.Class(OpenLayers.Handler.Drag, {
    interval: '0',
    stopDown: true,

    touchstart: function (evt) {
	if ( evt.touches.length == 2  ) {
	    /* 2 touches means device is being pinched*/
	    if ( this.started ) {
	        var xy = this.map.events.getMousePosition(evt);
		/* Stop the drag and let the pinch take over */
		this.started = false;
		this.dragging = false;
            	this.callback("up", [xy]);
	    }
	    return(this.stopDown);
	} else if ( evt.touches.length == 1 ) {
//console.warn("single touch");
		this.started = true;
        	this.callback("down", [this.start]);
		this.start = this.map.events.getMousePosition(evt);
		this.last = this.start;
        	OpenLayers.Event.stop(evt);
        	return !this.stopDown;
	}
    },

    touchmove: function (evt) {
	
	var xy = this.map.events.getMousePosition(evt);
//console.warn("drag:timeoutId:"+this.timeoutId);
        this.new_xy = xy;
//console.warn("touch x:"+xy.x+" y:"+xy.y);
        if (this.started && (xy.x != this.last.x || xy.y != this.last.y)) {
//console.warn("touchmove:drag (scale="+evt.scale);
            this.dragging = true;
	    if ( !this.timeoutId ) {
            	if (this.interval > 0) {
                	this.timeoutId = setTimeout(OpenLayers.Function.bind(this.removeTimeout, this), this.interval+'ms');
           	}
	    	var dx = this.last.x - xy.x;
	    	var dy = this.last.y - xy.y;
            	this.callback("move", [dx,dy]);
            	this.last = xy;
            	OpenLayers.Event.stop(evt);
	    }
        }
        return true;
    },
    removeTimeout: function() {
        this.timeoutId = null;
	if ( this.dragging && 
	     this.new_xy.x != this.last.x && this.new_xy.y != this.last.y ) {
	/* need to account for any movement since last timeout was set*/
	    var dx = this.last.x - this.new_xy.x;
	    var dy = this.last.y - this.new_xy.y;
            this.callback("move", [dx,dy]);
            this.last = this.new_xy;
	}
    },

    touchend: function (evt) {
        if (this.started) {
            var dragged = (this.start != this.last);
            this.started = false;
            this.dragging = false;
	    var xy = this.map.events.getMousePosition(evt);
            this.last = xy;
            // TBD replace with CSS classes
            this.callback("up", [xy]);
            if(dragged) {
                this.callback("done", [xy]);
            }
        }
        return true;
    },

    CLASS_NAME: "KWExtendedDevice.OLHandler.Drag"
});
KWExtendedDevice.OLControl.DragPan = OpenLayers.Class(OpenLayers.Control.DragPan, {
    /**
     * Property: interval
     * {Integer} The number of milliseconds that should ellapse before
     *     panning the map again. Set this to increase dragging performance.
     *     Defaults to 25 milliseconds.
     */

    // placeholder for custom drag handler

    handlerClass: KWExtendedDevice.OLHandler.Drag,

    /**
     * Method: draw
     * Creates a Drag handler, using <panMap> and
     * <panMapDone> as callbacks.
     */
    draw: function() {
        this.handler = new this.handlerClass(this, {
		"down": this.panMapStart,
                "move": this.panMap,
		"up": this.panMapStop,
                "done": this.panMapDone
            }, {
                interval: this.interval
            }
        );
    },
    panMapStart: function() {
        this.map.div.style.cursor = "move";
	this.centerLatLon = this.map.getCenter();
	this.resolution = this.map.getResolution();
//console.warn("centerLatLon lat"+this.centerLatLon.lat+" lon:"+this.centerLatLon.lon);
    },
    panMapStop: function() {
	this.map.div.style.cursor = "";
    },
    panMap: function(dx,dy) {
        /* Just move the existing tiles around */
 	   //var centerPx = this.map.getViewPortPxFromLonLat(this.centerLatLon);
	   //this.centerLatLon = this.map.getLonLatFromPixel(centerPx.add(dx,dy));
	   //this.map.centerLayerContainer(this.centerLatLon);
	var curx = this.map.layerContainerDiv.style.left.replace("px","");
	var cury = this.map.layerContainerDiv.style.top.replace("px","");
	curx -= dx;
	cury -= dy;
	this.centerLatLon.lat -= dy*this.resolution;
	this.centerLatLon.lon += dx*this.resolution;
	this.map.layerContainerDiv.style.left = curx + 'px';
	this.map.layerContainerDiv.style.top = cury + 'px';
//console.warn("before curx="+curx+" cury="+cury);
    },
    panMapDone: function() {
	/* Change the position of the map...forcing loading of new tiles if necessary */
//console.warn("centerLatLon lat"+this.centerLatLon.lat+" lon:"+this.centerLatLon.lon);
	    this.map.moveTo(this.centerLatLon, null, null);
    },
    initialize: function(options) {
        OpenLayers.Control.prototype.initialize.apply(this, arguments);
    },

    CLASS_NAME: "KWExtendedDevice.OLControl.DragPan"

});
KWExtendedDevice.OLControl.ExtendedNavigation = OpenLayers.Class(OpenLayers.Control.Navigation, {
    zoomEnabled: true,
    panEnabled: true,

    /*
     * There may be quite a few things that the ExtendedNavigation doesn't need to inherit
     * but for now, we'll only override the bits we need to
     * */
    dragPanClass: KWExtendedDevice.OLControl.DragPan,


    /**
     * if touchZoomClass is set, a touchZoom controller will
     * be instantiated
     */

    touchZoomClass: KWExtendedDevice.OLControl.TouchZoom,

    /**
     * Constructor: OpenLayers.Control.Navigation
     * Create a new navigation control
     *
     * Parameters:
     * options - {Object} An optional object whose properties will be set on
     *                    the control
     */
    initialize: function(options) {
        // Add ability to pass in dragpan class
        this.handlers = {};
        OpenLayers.Control.prototype.initialize.apply(this, arguments);
    },

    /**
     * Method: activate
     */
    activate: function() {
	if ( this.panEnabled ) {
        	this.dragPan.activate();
	}
        if(this.touchZoom != null){
            this.touchZoom.activate()
        }
        return OpenLayers.Control.prototype.activate.apply(this,arguments);
    },

    /**
     * Method: deactivate
     */
    deactivate: function() {
	if ( this.panEnabled ) {
		this.dragPan.deactivate();
	}
	if ( this.touchZoom != null ) {
        	this.touchZoom.deactivate();
	}
        return OpenLayers.Control.prototype.deactivate.apply(this,arguments);
    },

    /**
     * Method: draw
     */
    draw: function() {
        // disable right mouse context menu for support of right click events
        if (this.handleRightClicks) {
            this.map.div.oncontextmenu = function () { return false;};
        }

	if ( this.panEnabled ) {
        	this.dragPan = new this.dragPanClass( OpenLayers.Util.extend({map: this.map}, this.dragPanOptions));
        	this.dragPan.draw();
        }

	if ( this.zoomEnabled ) {
        	this.touchZoom = new KWExtendedDevice.OLControl.TouchZoom({map: this.map});
        	this.touchZoom.draw();
	}

        this.activate();
    },

    zoom:function (evt){
	/* callback hook for Handler Class: TouchZoom */
    },

    scale:function (evt){
	/* callback hook for Handler Class: TouchZoom */
    },

    pan: function (evt) {
	/* callback hook for Handler Class: DragPan */
    },

    CLASS_NAME: "KWExtendedDevice.OLControl.ExtendedNavigation"
});

if(KW_PAGE_CONFIG.device_type === 'touch'){
	OpenLayers.Control.Navigation.prototype.zoomWheelEnabled = false;
}

if(KW_PAGE_CONFIG.device_type === 'touch'){
	KWExtendedDevice.initialize('iphone',true); /* adds device unique events to OpenLayers */
}

var kw_decode = new Array();
kw_decode['X'] = '6';
kw_decode['b'] = '3';
kw_decode['f'] = '7';
kw_decode['8'] = '9';
kw_decode['g'] = '2';
kw_decode['Y'] = '+';
kw_decode['l'] = '-';
kw_decode['n'] = '8';
kw_decode['5'] = '1';
kw_decode['I'] = '4';
kw_decode['q'] = '0';
kw_decode['P'] = '.';
kw_decode['Z'] = ';';
kw_decode['x'] = '5';



OpenLayers.Util.onImageLoadError = function() {

	this._attempts = (typeof(this._attempts) === "number") ? (this._attempts + 1) : 0;
	if (this._attempts < OpenLayers.IMAGE_RELOAD_ATTEMPTS) {
		this.src = this.src;
	} else if(this._attempts === OpenLayers.IMAGE_RELOAD_ATTEMPTS){
		this.src = "http://tile.know-where.com/tiles/nodata.gif";
	} else {
		this.style.backgroundColor = OpenLayers.Util.onImageLoadErrorColor;
	}
	this.style.display = "";	
};


if(KW_PAGE_CONFIG.device_type === 'touch'){
	OpenLayers.Layer.TileCache.prototype.buffer = 2;
} else { 
	OpenLayers.Layer.TileCache.prototype.buffer = 0;
}


function init_renderTile(obj) {
	if (obj.imgDiv == null) {
		obj.initImgDiv();
	}

	obj.imgDiv.viewRequestID = obj.layer.map.viewRequestID;

	// needed for changing to a different serve for onload error
	if (obj.layer.url instanceof Array) {
		obj.imgDiv.urls = obj.layer.url.slice();
	}
	obj.url = obj.layer.getURL(obj.bounds);
	// position the frame
	OpenLayers.Util.modifyDOMElement(obj.frame, null, obj.position, obj.size);
}
function finish_renderTile(obj) {
	var imageSize = obj.layer.getImageSize();
        if (obj.layerAlphaHack) {
            OpenLayers.Util.modifyAlphaImageDiv(obj.imgDiv,
                    null, null, imageSize, obj.url);
        } else {
            OpenLayers.Util.modifyDOMElement(obj.imgDiv,
                    null, null, imageSize) ;
            obj.imgDiv.src = obj.url;
        }
}
KWImage_renderTile = function() {

	var queue_id = new Date().getTime();
	var args = arguments;
	var call_back_binder = function(obj, args, id){
		return function(){
			if ( obj.layer != null ) {
			
			var current_time = new Date().getTime();
			if ( queue_id === obj.kw_queue_id ) {
				
				
				if ( id != null ) {
				/*OpenLayers.Tile.Image.prototype.renderTile.apply(obj,args);*/
				finish_renderTile(obj);
				}

	                	obj.layer.map.kw_tile_throttle.eventCounter( new Object() );
				obj.delay_drawn = true;

				
			} 
			if ( id == null && obj.delay_drawn) {
			     obj.kw_queue_id = null;
			}
			}
		}
	}

	init_renderTile(this);

	if ( this.kw_queue_id == null ) {
		
		this.kw_queue_id = queue_id;
		this.delay_drawn = false;
		setTimeout(call_back_binder(this, arguments, queue_id), 350);
		setTimeout(call_back_binder(this,arguments,null),1000);
	} else {
		

		this.kw_queue_id = queue_id;
		this.delay_drawn = false;
		
		setTimeout(call_back_binder(this, arguments, queue_id), 600);
		
		setTimeout(call_back_binder(this,arguments,null),1000);
	}
	return(true);
}
OpenLayers.Layer.TileCache.prototype.addTile = function(bounds, position) {

        var url = this.getURL(bounds);
        var atile = new OpenLayers.Tile.Image(this, position, bounds,
                                             url, this.tileSize);
	atile.renderTile = KWImage_renderTile;
	return(atile);
}
function KWMap_moveTo(lonlat, zoom, options) {

	var move = true;
	var current_time = new Date().getTime();
	var throttled = this.kw_tile_throttle.eventCounter( null );
	if ( throttled ) {
/*console.error("throttle on: skipping");*/
			move = false;
			this.kw_move_skipped = true;
			if ( lonlat != null ) {
			this.kw_save_lonlat = lonlat.clone();
			} else {
				this.kw_save_lonlat = null;
			}
			this.kw_save_zoom = zoom;
			this.kw_save_options = options;
	} else {
		if ( this.kw_move_skipped ) {
/*console.error("rendering skipped");*/
			lonlat = this.kw_save_lonlat;
			zoom = this.kw_save_zoom;
			options = this.kw_save_options;
			this.kw_save_lonlat = null;
			this.kw_save_zoom = null;
			this.kw_save_options = null;
		} 
	}
	if ( lonlat === null && zoom === null && options === null ) {
		move = false;
	}
	if ( move ) {
		
        	OpenLayers.Map.prototype.moveTo.apply(this,arguments);
		this.kw_move_skipped = false;
	} 
}
KWMap_moveThrottle.prototype.counter = 0;
KWMap_moveThrottle.prototype.on = false;
KWMap_moveThrottle.prototype.start = null;
KWMap_moveThrottle.prototype.end = null;
KWMap_moveThrottle.prototype.eventCounter = function (event) {

	var current_time = new Date().getTime();

	
	var throttle_interval = 3000;
	
	throttle_interval = throttle_interval - 500;
	
	var throttle_max = 90;
	

	
	while( this.end != null  && (current_time - this.start.time) > throttle_interval ) {
		this.start = this.start.next;
		this.counter--;
		if ( this.start === null ) {
			this.end = null;
			this.counter = 0;
		}
	}
	
	if ( event != null ) {
		event.time = current_time;
		event.next = null;
		if ( this.end == null ) {
			this.end = event;
			this.start = event;
		} else {
			this.end.next = event;
			this.end = event;
		}
		this.counter++;
	}

	
	if ( this.counter >= throttle_max  ) {
		this.on = true;
	} else if ( this.on ) {
		this.on = false;
	}
/*
if ( event != null ) {
console.error(current_time+":event#: "+this.counter+" throttle interval:"+throttle_interval+ " throttle_max:"+throttle_max+" return:",this.on);
}
*/
	return(this.on);
}
function KWMap_moveThrottle(map) {

	this.map = map;
	this.map.moveTo = KWMap_moveTo;
	return(this);
}



OpenLayers.Control.PanZoomBar.prototype.destroy = function () {
	
	
	this.div.removeChild(this.slider);
        this.slider = null;

        this.sliderEvents.destroy();
        this.sliderEvents = null;

        this.div.removeChild(this.zoombarDiv);
        this.zoomBarDiv = null;

        this.divEvents.destroy();
        this.divEvents = null;

        this.map.events.un({
            "zoomend": this.moveZoomBar,
            "changebaselayer": this.redraw,
            scope: this
        });
	

        OpenLayers.Control.PanZoom.prototype.destroy.apply(this, arguments);

}
OpenLayers.Control.PanZoomBar.prototype.zoomStopWidth = 16;
OpenLayers.Control.PanZoomBar.prototype.buttonDown = function (evt) {
	if (!OpenLayers.Event.isLeftClick(evt)) {
            return;
        }


	switch (this.action) {
		case "panup":
			this.map.pan(0, -this.getSlideFactor("h"));
		break;
		case "pandown":
			this.map.pan(0, this.getSlideFactor("h"));
		break;
		case "panleft":
			this.map.pan(-this.getSlideFactor("w"), 0);
		break;
		case "panright":
			this.map.pan(this.getSlideFactor("w"), 0);
		break;
		case "panSE":
			this.map.pan(this.getSlideFactor("w"), this.getSlideFactor("h"));
		break;
		case "panSW":
			this.map.pan(-this.getSlideFactor("w"), this.getSlideFactor("h"));
		break;
		case "panNE":
			this.map.pan(this.getSlideFactor("w"), -this.getSlideFactor("h"));
		break;
		case "panNW":
			this.map.pan(-this.getSlideFactor("w"), -this.getSlideFactor("h"));
		break;
		case "zoomin":
			this.map.zoomIn();
		break;
		case "zoomout":
			this.map.zoomOut();
		break;
		case "zoomworld":
			this.map.zoomToMaxExtent();
		break;
	}

OpenLayers.Event.stop(evt);
}
OpenLayers.Control.PanZoomBar.prototype._addButton = function(id,img,xy,sz) {
	var button_div = OpenLayers.Control.PanZoom.prototype._addButton.apply(this,arguments);
	button_div.style.cursor = 'pointer';
	return button_div;
}
OpenLayers.Control.PanZoomBar.prototype.draw = function(px) {

        OpenLayers.Control.prototype.draw.apply(this, arguments);
        px = this.position.clone();


        this.buttons = [];

        var top_bottom_button_sz = new OpenLayers.Size(33,25);
		var corner_button_sz = new OpenLayers.Size(28,30);
        var right_left_button_sz = new OpenLayers.Size(23,34);
        var zoombar_plus_minus_sz = new OpenLayers.Size(20,24);
        var zoom_plus_minus_sz = new OpenLayers.Size(20,20);
		var button_pad = 8;
        var origin_x = px.x-button_pad;
        var origin_y = px.y-button_pad;
		var map_width = KWMap_width();
		var map_height = KWMap_height();
		var map_ctr = new OpenLayers.Pixel (map_width/2, map_height/2);


        this.slideFactor = map_ctr.y-10;
		px.x = origin_x+map_ctr.x-(top_bottom_button_sz.w/2)
		px.y = origin_y;
        var button = this._addButton("panup", "north-mini.png", px, top_bottom_button_sz);
		button.style.cursor = 'pointer';
		px.y = map_height - top_bottom_button_sz.h;
        this._addButton("pandown", "south-mini.png", px, top_bottom_button_sz);

	

        px.x = origin_x;
	

        px.y = origin_y + map_ctr.y - (right_left_button_sz.h/2);
        this.slideFactor = map_ctr.x-10;
        this._addButton("panleft", "west-mini.png", px, right_left_button_sz);

        px.x = map_width - right_left_button_sz.w;
        this._addButton("panright", "east-mini.png", px, right_left_button_sz);

	
		
			px.x = origin_x + right_left_button_sz.w;
		
		
			
				px.y = origin_y + button_pad;
			
		
        	this._addButton("zoomin", "zoombar-plus-mini.png", px, zoombar_plus_minus_sz);
        	px = this._addZoomBar(px.add(1, zoombar_plus_minus_sz.h-1));
		this.slider.style.cursor = 'pointer';
        	this._addButton("zoomout", "zoombar-minus-mini.png", px.add(-1,0), zoombar_plus_minus_sz);
	
        return this.div;
}

function KWMap_configure_copyright( ) {
	this.copyright_icon = new OpenLayers.Icon(
					"http://dt.know-where.com/DiscountTire/Icon/copyright.png", 
					new OpenLayers.Size(125,12), 
					new OpenLayers.Pixel(0,0) );
					this.copyright_icon.imageDiv.style.zIndex = 999;
	this.copyright_icon.map = this;
	this.draw_copyright = function() {
		this.copyright_icon.draw();
	}
	this.copyright_icon.draw = function() {
		
			var margin = 4;
		
		var imgURL = this.imageDiv.childNodes[0].src;
		OpenLayers.Icon.prototype.draw.apply( this, new Array(new OpenLayers.Pixel(
					
						KWMap_width() - (this.size.w+margin),
					
						KWMap_height() - (this.size.h+margin))) );
		
		if ( imgURL === "" ) {
			this.map.viewPortDiv.appendChild(this.imageDiv);
		}
	}
}

function KWMap_configure_map_scale() {
	this.events.register("zoomend",that,KWMap_on_zoomend );
	this.draw_scale = function() {
		var z = this.getZoom();
		
			var margin = 4;
		
		var imgURL = this.kw_map_scale_icon_list[z].imageDiv.childNodes[0].src;
		this.kw_map_scale_icon_list[z].display(true);
		this.kw_map_scale_icon_list[z].draw(new OpenLayers.Pixel(
					margin,
					KWMap_height() - (this.kw_map_scale_icon_list[z].size.h+margin)));
		if ( imgURL === "" ) {
			this.viewPortDiv.appendChild(this.kw_map_scale_icon_list[z].imageDiv);
		}
	}
	var zoom_num = this.numZoomLevels;
	this.kw_map_scale_icon_list = new Array(zoom_num);
	var z;
	for ( z=0; z < zoom_num; z++ ) {
		this.kw_map_scale_icon_list[z] =  new OpenLayers.Icon(
				"http://dt.know-where.com/DiscountTire/Icon/map_scale/zoom"+z+".png",
				new OpenLayers.Size(104,16), 
				new OpenLayers.Pixel(0,0) );
		this.kw_map_scale_icon_list[z].imageDiv.style.zIndex = 998;
	}
}


function kw_decode_txt(src) {
	var val = '';
	var c;
	for ( c=0; c < src.length; c++ ) {
		var newc = kw_decode[src.charAt(c)];
		val = val + newc;
	}
	return val;
}

function KWMap_draw_line(points) {
		if ( this.line_layer == null ) {
			this.line_layer = new OpenLayers.Layer.Vector( "Lines",
				{minResolution:0.000010,maxResolution:0.513848} );
			this.addLayer(this.line_layer);
		}
		var line_style = {
			strokeColor: "#00FF00",
			strokeWidth: 15,
			strokeRadius: 30,
			strokeOpacity: 0.6,
			pointerEvents: "visiblePainted"
		};
		var line_feature = new OpenLayers.Feature.Vector(
			new OpenLayers.Geometry.LineString(points),
			null,
			line_style
			);
		this.line_layer.addFeatures([line_feature]);
}

function KWMap_remove_line() {
	if ( this.line_layer != null ) {
		this.removeLayer(this.line_layer);
		this.line_layer = null;
	}
}

function KWMap_tilecache_layer(name) {
	var tile_size = 512;
	var n_zoom = 12;
	var zoom_levels = new Array(n_zoom-2);
	/* degrees lat/pixel @ most zoomed in level (1000 pix/mile & 69 miles/deg of lat)*/
	var zoom_max_pixel = 0.000014;  /* kwmap only support 6 decimals of precision */
	for ( z=2; z < n_zoom; z++ ) { /* limit to 10 zooms for now until we get world working properly */
		/* OpenLayers expects zoom resolution defined in units per pixel*/ 
		zoom_levels[z-2] = (zoom_max_pixel * Math.pow(2.6,n_zoom-(z+1))).toFixed(6);
	}
	var layer = new OpenLayers.Layer.TileCache( name,
			[ "http://tile.know-where.com/DiscountTire/tile" ],
			"custom",
			{format: 'image/gif',
			tileSize: new OpenLayers.Size(tile_size,tile_size),
			maxExtent : new OpenLayers.Bounds(-180,-60,180,90),
			resolutions: zoom_levels, transitionEffect: 'resize' });

	return layer;
}

function KWMap(mapid,lat,lon,zoom) {

	var base_layer   = KWMap_tilecache_layer("Streets");
	var mapOptions = { controls: [], resolutions: base_layer.resolutions };
	that = new OpenLayers.Map( mapid,mapOptions );
	that.addLayer(base_layer);
	that.kw_tile_throttle = new KWMap_moveThrottle(that);


	KWMap_configure_map_scale.apply(that);

	KWMap_configure_copyright.apply(that);

	/* 
	 * Set map center & zoom level together, so that map
	 * only loads tiles once on creation
	 * Every change of center or zoom causes a "moveTo"
	 * on the map, which must load new tiles.
	 */
	var zoom_num = 0;
	if ( typeof(zoom) == "number" ) {
		zoom_num = zoom;
	} else {
		zoom_num = base_layer.getZoomForExtent(zoom);
	}
	that.setCenter(new OpenLayers.LonLat(lon,lat),zoom_num);
	that.copyright_icon.draw();
	/* Add controls*/
	if(KW_PAGE_CONFIG.device_type === 'touch'){
		that.addControl( new KWExtendedDevice.OLControl.ExtendedNavigation());
	} else {
		that.addControl( new OpenLayers.Control.PanZoomBar() );
		that.addControl( new OpenLayers.Control.Navigation() );
		that.addControl( new OpenLayers.Control.DragPan() );
	}
	that.kw_center_lat  = lat;
	that.kw_center_lon  = lon;

	that.draw_line = KWMap_draw_line;
	that.remove_line = KWMap_remove_line;

	that.add_plugin = function(name, plugin){
		if(this.plugins === undefined){
			this.plugins = new Object();
		} 
		if(this.plugins[name] === undefined){
			this.plugins[name] = new Object();
		}

		this.plugins[name] = plugin;
	}

	
		that.restrictedExtent = new OpenLayers.Bounds(-170.0,15.5,-48.6,73.0);
	
		

/* Return the new map */
	return (that);
}





