function Streets(data, options, map){
	
	options = options || {};
	
	options.ajaxOptions = options.ajaxOptions || {};
	options.afterLoad 	 = options.afterLoad || 0;
	
	// events
	options.mouseout	= options.mouseout 	|| 0;
	options.mouseover	= options.mouseover || 0;
	options.click		= options.click 	|| 0;
	options.dblclick	= options.dblclick 	|| 0;	
	
	this.options  = options;
	this.parseLength = map.parseLength;

	this.map 	  = map;
	this.data	  = data;
	this.ajax_url = "";
	this.allHidden = false;
	}
	
Streets.prototype.loadData = function(){
	var data = this.data;
	
	if(typeof(data) == "string"){
		this.ajax_url 	= data;
		this.data	 	= [];
		this.ajaxLoadData();
	}else{
		this.addStreets();
		
		if(this.options.afterLoad)
			this.options.afterLoad();
		}
	}
	
Streets.prototype.addStreets = function(){
	var data = this.data;
	
	this.hash	 = [];		
	this.streets = [];	

	var i,item,m;
	for(i in data){
		item = data[i];
		this.streets.push(this.addStreetEvents(this.addStreet(item)));
		}
	
	if(this.options.filterOpts)
		if(this.options.filterOpts.onInit)
			this.filter();
	
	var me = this; // used because of referencing problems
	GEvent.addListener(this.map,"zoomend", function(){me.refresh(me)});
	GEvent.addListener(this.map,"moveend", function(){me.refresh(me)});
	
	this.refresh();
	}

Streets.prototype.addStreet = function(item){
	
	item.o = 1;
	var polyline = new GPolyline(this.encodeLatLng(item.ll),item.c,item.w,item.o);
	polyline.item = item;
	polyline.isAdded = false;
	
	if(item.id) this.hash[item.id] = polyline;
	
	return polyline;
	}
	
Streets.prototype.encodeLatLng = function(ll){
	var ar = [];
	for(i in ll){
		var c = ll[i];
		var k = new GLatLng(c[0],c[1]);
		ar.push(k);
		}
	return ar;
	}

Streets.prototype.addStreetEvents = function(marker){
	var item = copy_obj(marker.item);
	var me = this;
	
	if(this.options.click){
		GEvent.addListener(marker, "click", me.options.click);
		}
		
	if(this.options.dblclick){
		GEvent.addListener(marker, "dblclick", me.options.dblclick);
		}
		
	if(this.options.mouseover){
		GEvent.addListener(marker, "mouseover", me.options.mouseover);
		}
	
	if(this.options.mouseout){
		GEvent.addListener(marker, "mouseout", me.options.mouseout);	
		}
	
	return marker;
	}

Streets.prototype.ajaxLoadData = function(){
	var me = this;
	$.getJSON(this.ajax_url, this.options.ajaxOptions,
		function(data){
			me.data = data;
			me.loadData();
			}//places loaded
		);
	}

Streets.prototype.refresh =  function(me){
	if(typeof(me) == "undefined") me = this;
	if(this.allHidden == true)
		return;
	var mb   = me.map.getBounds();
	var data = me.streets;
	var zoom = me.map.getZoom();
	var w,i,street;
	
	for(i in data){
		street = data[i];
		if(zoom > 16)
			w = street.item.w;
		else
			w = 1;
		if(mb.intersects(street.getBounds())){
			street.setStrokeStyle({weight:parseInt(w)});
			if(!street.isAdded){
				places_map.addOverlay(street);
				street.isAdded = true;
			}
		}else{
			if(street.isAdded){
				places_map.removeOverlay(street);
				street.isAdded = false;
				}
			}
		}
	}
	
Streets.prototype.searchByName = function(value, limit){
	if(typeof(limit) == "undefined") limit = 1000;
	
	var i,len, streets, results,p,name;
	streets = this.streets;
	len = streets.length;
	results = [];
	for(i=0;i<Math.min(len,limit);i++){
		p = streets[i];
		name = p.item.n.toLowerCase();
		if(name.match(value.toLowerCase())){
			results.push(streets[i]);
			}
		}
	return results;
	}
Streets.prototype.focusOn = function(polyline){
	var map = this.map;
	var bounds = polyline.getBounds();
	map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));
	return polyline;
	}
	
Streets.prototype.getTitle = function(item){
	var baseTitle = item.name;
	if(!this.options.getTitle){
		return (baseTitle)?baseTitle:"";
		}
		
	return this.options.getTitle(item, baseTitle);
	}

Streets.prototype.toggle = function(){
	if(this.allHidden){
		this.allHidden = false;
		return this.refresh();
		}
	this.allHidden = true;
	return this.hideAll();
	}
Streets.prototype.hideAll = function(){
	var me = this;
	var data = me.streets;
	for(i in data){
		street = data[i];
		this.map.removeOverlay(street);
		}
	}
// Street specific
GPolyline.prototype.focusOn	 = function(map){
	var bounds = this.getBounds();
	map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));
	return this;
	}

GPolyline.prototype.highlight = function(color){
	if(typeof(color) == "undefined") color = "#FF9900";
	this.setStrokeStyle({color: color});
	highlightedPolyline = this;
	//timeout = setTimeout(this.unhighlight,20000);
	}
	  
GPolyline.prototype.unHighlight = function (){
	if(typeof(highlightedPolyline) != "undefined" && highlightedPolyline){
		var color = highlightedPolyline.item.c;
		highlightedPolyline.setStrokeStyle({color:color});
		highlightedPolyline = false;
		}
	}
GPolyline.prototype.getParsedLength = function (){
	var len = this.getLength();
	var unit = "m";
	len = Math.ceil(len);
	if(len > 1000){len /= 1000;unit = "km";}
	return len+unit;
	}
