PPolyCreator = function(options) {
	if (options)
		this.options = options;
	else
		this.options = new PPolyCreatorOptions();

	this.click = null;
	this.points = [];
	this.savePoints = [];
	//this.places = [];
	//this.radius = null;
	//this.allPolylines = [];
	this.polyline = null;
	this.name = null;
	this.description = null;
	// This array will keep track of all the overlays added to the map that are used for building the region
	// So either the markers and polylines used for drawing an overlay, or the polygons used in assembling, or the marker and polygon for radius
	this.buildingOverlays = [];

	this.eventTypes = new Object();
	this.eventTypes.addpoly = 'addpoly';
	this.eventTypes.savepoly = 'savepoly';
	this.eventTypes.saveAssembledPoly = 'saveassemblepoly';
	this.eventTypes.saveCirclePoly = 'savecirclepoly';
	this.eventTypes.removepoly = 'removepoly';

	this.eventManager = new _eventManager();
	for (var ev in this.eventTypes)
		this.eventManager.registerEventID(ev);

	this.buildType = null;

	// 3 different type of custom regions that you can build
	// each type has an object to keep track of the required data
	this.DRAW = {};
	this.DRAW.title = 'Show Boundaries in Region:';
	this.DRAW.regions = {}; // keeps track of all drawn regions
	this.DRAW.ctypeid = '1';

	this.ASSEMBLE = {};
	this.ASSEMBLE.title = '<span>Select Areas on the Map By:</span>';
	this.ASSEMBLE.polygons = []; // used to keep track of the polygons as they're being added
	this.ASSEMBLE.places = [];
	this.ASSEMBLE.placeids = [];
	this.ASSEMBLE.ctypeid = '2';

	this.CIRCLE = {};
	this.CIRCLE.title = 'Show Boundaries in Region:';
	this.CIRCLE.centerpoint = null;
	this.CIRCLE.address = null;
	this.CIRCLE.radius = null;
	this.CIRCLE.ctypeid = '3';

	// keeps track of the custom places place objects and polygons as they're added to the map
	// this way we can remove the polygons and also keep track of each place so when using getPlacesWithin we have the right info
	this.customPlaces = {};
	this.customPlacesCount = 0;

	// keeps track of the polygons that are shown within the custom places so we know which overlays to remove when user clears the polygons within
	this.polygonsWithin = [];	
};

PPolyCreator.prototype.addListener = function(eventId, func) {
	this.eventManager.registerForEvent(eventId, [], func);
};

PPolyCreator.prototype.removeListener = function(eventId, func) {
	this.eventManager.deregisterForEvent(eventId, [], func);
};

PPolyCreator.prototype.attachMap = function(map) {
	this.map = map;
	this.initCustomRegionType();
};

PPolyCreator.prototype.detachMap = function() {
	if (this.map && this.click) 
		this.map.removeListener(this.click);
};

PPolyCreator.prototype.cancelPoly = function(stillBuilding) {
	if (!stillBuilding)
		this.resetBuildType();

	this.resetBuildOptions();
	//this.map.clearOverlays();
	this.clearBuildingOverlays();
	//this.detachMap();

	// since same widget is used for assembling and showing places within
	// we need to re-populate the boundaryWidget so it resets to the places within version
	this.boundaryWidget.populate();
};

// clear only the overlays for the custom region that's in the process of being built
PPolyCreator.prototype.clearBuildingOverlays = function() {
	var overlays = this.buildingOverlays;
	for (var i=0; i<overlays.length; i++) {
		this.map.removeOverlay(overlays[i]);
	}
	this.buildingOverlays = [];
};

PPolyCreator.prototype.resetBuildOptions = function() {
	this.points = [];
	this.places = [];
	this.name = null;
	this.description = null;
	// these are used in assembling by places
	this.ASSEMBLE.verts = [];
	this.ASSEMBLE.places = [];
	this.boundaryWidget.removeMapLayers();
	this.assembleInfoWidget.update();
	// these are used for custom circles
	this.CIRCLE.radius = null;
	this.CIRCLE.centerpoint = null;
	this.CIRCLE.centeraddress = null;

	if (this.map)
		this.map.closeInfoWindow();
};

PPolyCreator.prototype.reset = function() {
	this.resetBuildOptions();

	// clear object
	this.resetPlaces();

	// hide the widgets
	this.toggleWidgets();
};

PPolyCreator.prototype.resetPlaces = function() {
	// clear object
	this.customPlaces = {};
	this.customPlacesCount = 0;
};

PPolyCreator.prototype.addPoly = function(point, radius, places) {
	if (radius) {
		this.eventManager.triggerEvent('addpoly', [point]);
	}
	else if (places) {
		var point = this.ASSEMBLE.places[0].getVertices()[0][0];
		this.eventManager.triggerEvent('addpoly', [point]);
	}

	if (point.equals(this.points[0])) {
		this.points.push(point);
		//this.map.clearOverlays();
		this.clearBuildingOverlays();
		var polygon = new PPolygon(this.points,this.options.poly.color,this.options.poly.weight,this.options.poly.opacity,this.options.poly.fill);
		this.buildingOverlays.push(polygon);
		this.map.addOverlay(polygon);
		this.savePoints = this.points.slice();
		this.points = [];
		this.eventManager.triggerEvent('addpoly', this.savePoints);
	}
};
	
PPolyCreator.prototype.addPointLine = function(point) {
	this.points.push(point);
	if (this.map) {
		var marker = new PMarker(point, this.options.icon);
		this.buildingOverlays.push(marker);
		this.map.addOverlay(marker);
		if (this.points.length > 1) {
			var polyline = new PPolyline([point,this.points[this.points.length-2]],this.options.line.color,this.options.line.weight,this.options.line.opacity);
			this.buildingOverlays.push(polyline);
			this.map.addOverlay(polyline);
		}
	}
};

PPolyCreator.prototype.saveDrawPoly = function() {
	// ensure polygon and closed
	if (this.savePoints.length < 4) return;
	if (!this.savePoints[0].equals(this.savePoints[this.savePoints.length-1]))
		this.savePoints.push(this.savePoints[0]);

	//map.clearOverlays();
	this.clearBuildingOverlays();

	// send to servlet
	var query = "&vtc=MULTIPOLYGON(((";
	for (var i=0; i<this.savePoints.length; i++) {
		query += this.savePoints[i].lng() + "%20" + this.savePoints[i].lat();
		if (i < this.savePoints.length-1)
			query += ",";
	}
	query += ")))";
	query += "&name=" + encodeURIComponent(this.name);
	query += "&desc=" + encodeURIComponent(this.description);
	query += "&userid=" + session2.get('_userid');
	//query += "&contents=" + this.places.join(",");
	query += "&ctypeid=" + this.DRAW.ctypeid;
	
	var eman = this.eventManager;
	//eman.triggerEvent('savepoly',places);
	PAsync2.call(PEnvironment.polyUrl + '?' + query, function(places) { eman.triggerEvent('savepoly',places); });
	//this.reset();
};

PPolyCreator.prototype.sharePoly = function(id, boundaryName, shareTo, message, callback) {
	var query = PEnvironment.polyUrl + "?act=sha"
	query += "&id=" + id;
	query += "&userid=" + session2.get('_userid');
	query += "&bn=" + encodeURIComponent(boundaryName);
	query += "&to=" + encodeURIComponent(shareTo);
	query += "&m=" + encodeURIComponent(message);
	PAsync2.call(query,callback);
};

PPolyCreator.prototype.renamePoly = function(id, newName, callback) {
	PAsync2.call(PEnvironment.polyUrl + '?act=ren&id=' + id + '&userid=' + session2.get('_userid') + '&name=' + encodeURIComponent(newName), callback);
};

PPolyCreator.prototype.deletePoly = function(id, callback) {
	PAsync2.call(PEnvironment.polyUrl + '?act=del&id='+id+'&userid='+session2.get('_userid'),callback);
};

PPolyCreator.prototype.load = function(ids, callback) {
	PAsync2.call(PEnvironment.polyUrl + '?act=dsp&ids='+ids,callback);
};

PPolyCreator.prototype.polyload = function(bid, pname, plat, plng, callback) {
	PAsync2.call(PEnvironment.polyUrl + '?act=dpp&bid=' + bid + '&pname=' + encodeURIComponent(pname) + '&plat=' + plat + '&plng=' + plng, callback);
};

PPolyCreator.prototype.loadByUser = function(id, callback) {
	if (id != null)
		PAsync2.call(PEnvironment.polyUrl + '?act=get&fmt=js&userid='+id,callback);
};

PPolyCreator.prototype.initDrawRegion = function() {
	var polycreator = this;
	this.detachMap();

	this.click = PEvent.addListener(this.map, 'click', function(overlay, point) {
		if (overlay && polycreator.points.length < 3) {
			// if the user is trying to draw a line let them know that's crazy
			var alerter = new PAlerter();
			var text = "You need at least one more point to complete a proper custom region. Click OK and continue where you left off to finish your custom region.";
			alerter.popup(text, null, null, "OK");
		} else if (overlay) {
			polycreator.addPoly(overlay.point);
		} else if (point) {
			polycreator.addPointLine(point);
		}
	});
};

PPolyCreator.prototype.addPolyMarker = function(place, polylines, map) {
	if (!this.map && map)
		this.map = map;

	// the points that are used for the clear and info markers
	var point1 = polylines[0].points[0];
	var midpos = Math.round(polylines[0].points.length/2);
	var point2 = polylines[0].points[midpos];

	// set up the markers
	var icon = new PIcon(PIcon.POINT);
	icon.iconSize = new PSize(12,12);
	icon.shadow = "";
	icon.image = '/images/remove_icon_active.png';
	var clearmarker = new PMarker(point2, icon);
	clearmarker.buildtype = this.buildType;
	icon.image = '/images/pins/polygon_red.png';
	var infomarker = new PMarker(point1, icon);

	clearmarker.image.index = this.getCustomPlacesCount();
	clearmarker.image.polylines = polylines;
	clearmarker.image.polycreator = this;
	clearmarker.image.infomarker = infomarker;
	clearmarker.image.clearmarker = clearmarker;
	clearmarker.image.place = place;
	// store the markers used for this custom region so we can remove them when necessary
	this.customPlaces[place.id].markers = [infomarker,clearmarker];
	
	var polycreator = this;
	// since the event actually gets applied to the image of the marker object
	// we need to add the marker to the image so we can use it to open the infowindow in the mousedown event
	infomarker.image.infomarker = infomarker;
	infomarker.image.place = place;

	// add events to to the markers
	PEvent.addListener(infomarker,'mousedown',function() {
		// Get the content of the info bubble.
		var content = PMIdentificationPrinter.printCustomPolyPlaces(this.place);
		this.marker.openInfoWindowHtml(content);
	});
	PEvent.addListener(clearmarker, 'mousedown', function() {
		var index = this.index;
		var regions = this.polycreator.customPlaces;
		// remove place from map, it also removes the place from the session and from the dropdown if dropdown is active
		this.polycreator.removeCustomRegionFromMap(this.place);
	});

	this.map.addOverlay(clearmarker);
	this.map.addOverlay(infomarker);
};

PPolyCreator.prototype.saveAssemblePoly = function() {
	this.map.closeInfoWindow();
	this.showSavingDialog();

	var places = this.ASSEMBLE.places;

	this.clearBuildingOverlays();
	var labels = "";

	var pids = [];
	for (var p=0; p<places.length; p++) {
		pids.push(places[p].id);
	}

	// send to servlet
	var query = "&pids=" + pids.toString();
	query += "&name=" + encodeURIComponent(this.name);
	query += "&desc=" + encodeURIComponent(this.description);
	query += "&userid=" + session2.get('_userid');
	query += "&ctypeid=" + this.ASSEMBLE.ctypeid;

	var eman = this.eventManager;
	PAsync2.call(PEnvironment.polyUrl + '?' + query, function(places) { eman.triggerEvent('savepoly',places); });
};

PPolyCreator.prototype.saveCirclePoly = function() {
	this.clearBuildingOverlays();

	var points = this.CIRCLE.points;
	//var centerpoint = this.CIRCLE.centerpoint;
	var radius = this.CIRCLE.radius;
	var address = this.CIRCLE.address;

	// send to servlet
	var query = "&vtc=MULTIPOLYGON(((";
	for (var i=0; i<points.length; i++) {
		query += points[i].lng() + "%20" + points[i].lat();
		if (i < points.length-1)
			query += ",";
	}
	query += ")))";
	//query += "&cpoint=" + centerpoint.lat() + ", " + centerpoint.lng();
	query += "&rad=" + radius;
	if (address)
		query += "&caddr=" + address;

	query += "&name=" + encodeURIComponent(this.name);
	query += "&desc=" + encodeURIComponent(this.description);
	query += "&userid=" + session2.get('_userid');
	query += "&ctypeid=" + this.CIRCLE.ctypeid;

	var eman = this.eventManager;
	PAsync2.call(PEnvironment.polyUrl + '?' + query, function(places) { eman.triggerEvent('savepoly',places); });
};

PPolyCreator.prototype.initAssembleRegion = function(ptype) {
	// clear the polygons from previous type if there are any
	this.resetType();

	// show assemble info widget
	if (this.isBuildOn())
		this.assembleInfoWidget.show();

	this.detachMap();

	var polycreator = this;
	this.click = PEvent.addListener(this.map, 'click', function(overlay, point) {
		if (overlay)
			return;

		polycreator.addPlace(ptype, point)
	});
};

PPolyCreator.prototype.removeAssembledPlaceIfExists = function(place) {
	var assplaces = this.ASSEMBLE.places;
	var assverts = this.ASSEMBLE.verts;
	// if place is already selected remove place from assemble array and from vertices array
	for (var j=0; j<assplaces.length; j++) {
		if (assplaces[j].id == place.id) {
			for (var p=0; p<assplaces[j].savedPolys.length; p++)
				map.removeOverlay(assplaces[j].savedPolys[p]);
			assplaces.splice([j],1);
			assverts.splice([j],1);

			// update info displayed
			polycreator.assembleInfoWidget.update();
			return true;
		}
	}
	return false;
};

PPolyCreator.prototype.addPlace = function(ptype, point) {
	var geocoder = new PClientGeocoder();
	geocoder.getPlacesContaining(point, ptype, function(places) {
		var place = places[0];

		// Kluge for cities to not use unincorporated cities.
		// Unincorported cities have no state value in the db so that's how we know it's unincorporated
		if (ptype == PPlaceType.CITY) {
			for (var i=0; i<places.length; i++) {
				if (places[i].state != null)
					place = places[i];
			}
		}

		var verts = place.getVertices();
		var assverts = polycreator.ASSEMBLE.verts;
		var assplaces = polycreator.ASSEMBLE.places

		place.savedPolys = [];
		for (var i=0; i<verts.length; i++) {
			// check if place is already on map, if so remove it.
			// only need to check one time
			if (i == 0) {
				// this removes the polygons from the map if place is found and then returns true or false if it removed it or not
				if (polycreator.removeAssembledPlaceIfExists(place))
					return true;
			}

			var polygon = new PPolygon(verts[i], "#eb5920", 1, 0.5, '#ffffff');
			polycreator.ASSEMBLE.polygons.push(polygon);
			polycreator.buildingOverlays.push(polygon);
			polycreator.map.addOverlay(polygon);

			polycreator.ASSEMBLE.lastpoint = point;

/*			var html = "<div style='width: 200px; font-size: 11px'>";
			html += "Click other boundaries or<br />";
			html += "<a onmouseup='polycreator.showSaveInfoWindow(polycreator.ASSEMBLE.lastpoint)'>Save Region</a>";
			html += "</div>";

			polycreator.map.openInfoWindowHtml(point, html);
*/
			assverts.push(verts[i]);
			place.savedPolys.push(polygon);
			// Only store the place once all polygons are drawn so it doesn't duplicate
			if (i==verts.length-1)
				assplaces.push(place);

			// update info displayed
			polycreator.assembleInfoWidget.update();
		}
	});	
};

PPolyCreator.prototype.showSaveInfoWindow = function(point) {
	var polycreator = this;
	if (this.buildType == this.DRAW) {
		var html = "<div class='polycreatorInfoBubble'>";
		html += "Name: <input type='text' maxlength='64' onchange='polycreator.name=this.value;' /><br>";
		html += "Description:<br><textarea onchange='polycreator.description=this.value;' cols='20' rows='3' /></textarea><br>";
		html += "<input type='submit' value='Save' onmouseup='javascript:polycreator.saveDrawPoly()' /> ";
		html += "<input type='button' value='Cancel' onmouseup='javascript:polycreator.cancelPoly(true)' />";
		html += "</div>";

		var icon = new PIcon(PIcon.POINT);
		icon.iconSize = new PSize(12,12);
		icon.shadow = "";
		icon.image = '/images/pins/polygon_red.png';
		var marker = new PMarker(point, icon);
		marker.image.point = point;
		PEvent.addListener(marker, "click", function() {
			polycreator.showSaveInfoWindow(this.point);
		});
		this.buildingOverlays.push(marker);

		this.map.addOverlay(marker);
		marker.openInfoWindowHtml(html);
		this.points = [];
	}
	else if (this.buildType == this.ASSEMBLE) {
		// don't allow if only one place is used
		if (this.ASSEMBLE.places.length < 2) {
			customAlert("You need more than one place to create this type of custom regions. Select another place and then click save region again.");
			return;
		}

		var html = "<div class='polycreatorInfoBubble'>";
		html += "Name: <input type='text' maxlength='64' onchange='polycreator.name=this.value;' /><br>";
		html += "Description:<br><textarea onchange='polycreator.description=this.value;' cols='20' rows='3' /></textarea><br>";
		html += "<input type='submit' value='Save' onmouseup='javascript:polycreator.saveAssemblePoly()' /> ";
		html += "<input type='button' value='Cancel' onmouseup='javascript:map.closeInfoWindow()' />";
		html += "</div>";
		this.map.openInfoWindowHtml(point, html);
	}
	else if (this.buildType == this.CIRCLE) {
		var html = "<div class='polycreatorInfoBubble'>";
		html += "Name: <input type='text' maxlength='64' onchange='polycreator.name=this.value;' /><br>";
		html += "Description:<br><textarea onchange='polycreator.description=this.value;' cols='20' rows='3' /></textarea><br>";
		html += "<input type='submit' value='Save' onmouseup='javascript:polycreator.saveCirclePoly()' /> ";
		html += "<input type='button' value='Cancel' onmouseup='javascript:polycreator.cancelPoly(true)' />";
		html += "</div>";

		var icon = new PIcon(PIcon.POINT);
		icon.iconSize = new PSize(12,12);
		icon.shadow = "";
		icon.image = '/images/pins/polygon_red.png';
		var marker = new PMarker(point, icon);
		marker.image.point = point;
		PEvent.addListener(marker, "click", function() {
			polycreator.showSaveInfoWindow(this.point);
		});
		this.buildingOverlays.push(marker);

		this.map.addOverlay(marker);
		marker.openInfoWindowHtml(html);
		this.points = [];
	}
};

PPolyCreator.prototype.resetType = function() {
	this.ASSEMBLE.verts = [];
	this.ASSEMBLE.places = [];

	// Clear all the polygons added with assembling if there are any
	var polygons = this.ASSEMBLE.polygons;
	for (var i=0; i<polygons.length; i++) {
		map.removeOverlay(polygons[i]);
	}
	this.assembleInfoWidget.update();
};

PPolyCreator.prototype.initRadiusRegion = function() {
	var polycreator = this;
	this.clearBuildingOverlays();
	this.detachMap();

	this.click = PEvent.addListener(this.map, 'click', function(overlay, point) {
		if (overlay)
			return;
		var miles = document.getElementById('radiusSetting').value;
		if (miles == 0 || miles == null) {
			var alerter = new PAlerter();
			var text = 'You need to add a radius.';
			var position = getAlertPosition(parseInt(alerter.box.style.width));
			alerter.popup(text, position[0], position[1], "OK");
			return;
		}

		// set the point as the value in the searchbox
		var searchValue = point.lat() + "," + point.lng();
		polycreator.circleWidget.searchbox.textbox.value =  searchValue;
//		polycreator.drawCircle(point, miles);
		var vert = polycreator.drawCircle(point, miles);
		var icon = new PIcon(PIcon.POINT);
		icon.iconSize = new PSize(12,12);
		icon.shadow = "";
		icon.image = '/images/pins/polygon_red.png';
		var marker = new PMarker(point, icon);
		polycreator.map.addOverlay(marker);
		polycreator.buildingOverlays.push(marker);

		var polyline = new PPolyline(vert, '#e68000');
		polycreator.buildingOverlays.push(polyline);
		polycreator.map.addOverlay(polyline);

		polycreator.eventManager.triggerEvent('addpoly', [point]);
	});
};

PPolyCreator.prototype.drawCircle = function(point, miles, recenter) {
	this.clearBuildingOverlays();

	var centerpoint = point;
	dist = miles * 1609.344

	// Gets the distance for the radius
	var radiusX = centerpoint.moveBy("0 1N", dist);
	var radiusY = centerpoint.moveBy("90 1N", dist);
	var xRadiusMetres = radiusX.lat() - centerpoint.lat();
	var yRadiusMetres = radiusY.lng() - centerpoint.lng();

	// Points for setting zoom bounds
	var pointyeast = centerpoint.lng() + yRadiusMetres;
	var pointywest = centerpoint.lng() - yRadiusMetres;
	var pointxsouth = centerpoint.lat() - xRadiusMetres;
	var pointxnorth = centerpoint.lat() + xRadiusMetres;
		
	var sw = new PLatLng(pointxsouth, pointywest);
	var ne = new PLatLng(pointxnorth, pointyeast);

	if (recenter)
		this.map.setCenterBounds(new PLatLngBounds(sw, ne));

	var circlepoints = [];
	with (Math) {
		for (var a = 0 ; a < 361 ; a+=5 ) {
			var aRad = a*(PI/180);
			var pointx = centerpoint.lat() + xRadiusMetres * cos(aRad);
			var pointy = centerpoint.lng() + yRadiusMetres * sin(aRad);

			var p = new PLatLng(pointx,pointy);
			circlepoints.push(p);
		}
	}
	this.CIRCLE.centerpoint = centerpoint;
	this.CIRCLE.radius = miles;
	this.CIRCLE.points = circlepoints;

	return circlepoints;
};

PPolyCreator.prototype.customRegionsOn = function() {
	if (this.getCustomPlacesCount() > 0)
		return true;
	else
		return false;
};

PPolyCreator.prototype.toggleWidgets = function() {
	// hide the circle and assembe widgets
	this.circleWidget.hide();
	this.assembleInfoWidget.hide();

	// Note: put this in the if statement below when showing places within custom regions is added back to the app
	// There are a few places in MapCommon.js that need to be uncommented out, all are noted just as is it is here
	this.boundaryWidget.hide();

	// clear and remove widget related things if no custom regions are on map
	if (!this.customRegionsOn()) {
		this.clearPolygonsWithin();
		this.clearBuildingOverlays();
	}
};

PPolyCreator.prototype.addPlacesWithinAllRegions = function(type) {
	// clear all the polygons everytime type is changed
	this.clearPolygonsWithin();
	var count = this.getCustomPlacesCount();
	var places = this.customPlaces;
	if (count > 0) {
		for (var i in places) {
			this.showPlacesWithin(places[i].place, type);
		}
	}
};

PPolyCreator.prototype.showPlacesWithin = function(place, type) {
	var polycreator = this;
	// get all the places within and add polygons for each
	place.getPlacesWithin(type, function(places) {
		for (var i=0; i<places.length; i++) {
			for (var j=0; j<places[i].getVertices().length; j++) {

				var poly = new PPolygon(places[i].getVertices()[j], '#eb5920', 3, 0.1, '#eb5920', 0.4);
				polycreator.map.addOverlay(poly);

				// need to keep track of all added polygons so we can remove them
				polycreator.polygonsWithin.push(poly);
			}
		}
	}, 3);
};

PPolyCreator.prototype.clearPolygonsWithin = function() {
	if (this.polygonsWithin.length > 0) {
		for (var i=0; i<this.polygonsWithin.length; i++)
			map.removeOverlay(this.polygonsWithin[i]);
	}
};

PPolyCreator.prototype.clearPolyline = function(polylines) {
	for (var i=0; i<polylines.length; i++) {
		this.map.removeOverlay(polylines[i]);

		if (polylines[i].infomarker) {
			this.map.removeOverlay(polylines[i].infomarker);
			this.map.removeOverlay(polylines[i].clearmarker);
		}
	}
};

PPolyCreator.prototype.clearPolylineAssembled = function(polylines) {
	// Clear all the polylines used in assembled area
	for (var i=0; i<polylines.length; i++) {
		for (var j=0; j<polylines[i].length; j++) {
			this.map.removeOverlay(polylines[i][j]);
		}
		if (polylines[i].infomarker) {
			this.map.removeOverlay(polylines[i].infomarker);
			this.map.removeOverlay(polylines[i].clearmarker);
		}
	}
};

// start the build process based on what type of region user selected
PPolyCreator.prototype.initCustomRegionType = function() {
	if (this.buildType == this.DRAW) {
		this.initDrawRegion();
	}
/*
	else if (this.buildType == this.ASSEMBLE) {
		this.initAssembleRegion(this.ASSEMBLE.placetype);
	}
*/
	else if (this.buildType == this.CIRCLE) {
		this.initRadiusRegion();
	}
};

PPolyCreator.prototype.isBuildOn = function() {
	return this.buildType ? true : false;
};

PPolyCreator.prototype.resetBuildType = function() {
	this.buildType = null;
};

PPolyCreator.prototype.addPolylines = function(place, map) {
	if (!map)
		this.map = map;
	var polylines = [];
	var vertices = place.getVertices();
	// populate object with the respective poylines and place so to keep track and be able to remove them from the map and sessions
	this.customPlacesCount++;
	this.customPlaces[place.id] = {};
	this.customPlaces[place.id].place = place;
	this.customPlaces[place.id].polylines = [];
	for (var i=0; i<vertices.length; i++) {
		var polyline = new PPolyline(vertices[i], '#e68000');
		//this.allPolylines.push(polyline);
		place.polyline = polyline;
		this.polyline = polyline;
		map.addOverlay(polyline);
		this.customPlaces[place.id].polylines.push(polyline);
		polylines.push(polyline);
	}

	this.addPolyMarker(place, polylines, map);

	// add to session
	this.addCustomRegionToSession(place);
};

PPolyCreator.prototype.addCustomRegionForTable = function(place, norefresh) {
	// Handles adding custom regions to polycreator's list of custom regions,
	// updating the session, and adding them to the cube's load queue.
	// Accepts a single region or an array of regions.
	
	// Put together an array of all places we need to load.
	var placesToLoad = [];
	if(place instanceof Array) {
		placesToLoad = place;
	} else {
		placesToLoad.push(place);
	}
	
	for(var i=0; i<placesToLoad.length; i++) {
		// Add the region to the list of custom regions.
		this.customPlacesCount++;
		this.customPlaces[placesToLoad[i].id] = {}
		this.customPlaces[placesToLoad[i].id].place = placesToLoad[i];
	}
	
	// Add the places to the queue of places that need to be loaded
	if(!norefresh) {
		refreshCubeQueue(placesToLoad);
	}
	
	// Update the custom regions in the session.
	this.addCustomRegionToSession(placesToLoad[0]);
};

PPolyCreator.prototype.removeCustomRegionFromMap = function(place) {
	var region = this.customPlaces[place.id];
	
	// delete place from object and subtract from count
	delete this.customPlaces[place.id];
	this.customPlacesCount--;

	this.clearPolyline(region.polylines);
	var markers = region.markers;
	// remove the info and clear markers
	for (var i=0; i<markers.length; i++) {
		this.map.removeOverlay(markers[i]);
	}
	var dropdownEl = region.dropdownEl;
	if (dropdownEl) {
		dropdownEl.on = false;
		dropdownEl.className = "";
	}

	// remove from session
	this.removeCustomRegionFromSession(place);

	// Note: This will be needed when we re-enable the boundaries within widget
	//this.toggleWidgets();
};

PPolyCreator.prototype.removeCustomRegionFromTable = function(place) {
	// This is called by cubeRemoveListener, which is called when the user
	// either clicks the X to remove a column on the table, or clicks the X
	// to remove a custom region in the dropdown. This function
	// unhighlights the region in the dropdown and removes it from the
	// session and this object's customPlaces array.
	
	var regions = this.customPlaces;
	
	if(regions[place.id]) {
		// Unhighlight the region in the dropdown.
		var dropdownEl = regions[place.id].dropdownEl;
		if (dropdownEl) {
			dropdownEl.on = false;
			dropdownEl.className = "";
		}
		
		// Delete the place from the object.
		delete regions[place.id];
		this.customPlacesCount--;
	}
	
	// Update the custom regions in the session.
	this.removeCustomRegionFromSession(place);
};

PPolyCreator.prototype.getCustomPlacesCount = function() {
	return this.customPlacesCount;
};

PPolyCreator.prototype.addCustomRegionToSession = function(place) {
	// Add custom region to session
	// Loop through all the custom regions on the map and add them all to the session
	var places = this.customPlaces;
	var cp = "";
	for (var i in places) {
		cp += places[i].place.id + ',';
	}
	cp = cp.substring(0,cp.length-1)

	session2.put('cp', cp);
};

// This is exactly the same as the above addCustomRegionToSession
// It's still being used though
// Will remove it and rename above function to be used in all custom region remove/add circumstances when there's time
PPolyCreator.prototype.removeCustomRegionFromSession = function(place) {
	var places = this.customPlaces;
	var cp = "";
	for (var i in places) {
		cp += places[i].place.id + ',';
	}
	cp = cp.substring(0,cp.length-1)

	session2.put('cp', cp);
};

PPolyCreator.prototype.hasBuildOverlays = function() {
	return (this.buildingOverlays.length > 0) ? true : false; 
};

// Creates and fades in the "Saving custom region..."
PPolyCreator.prototype.showSavingDialog = function() {

	// Create the div.
	if (!this.saveLoading) {
		var div = $('<div/>');
		this.savingDialog = div; //document.createElement('div');
		div.attr({id:"savingCustomRegionDialog"});
		div.hide();
		div.html("<img src='/images/busy.gif' class='center'><br />Building and saving your custom region...");

		var mapDiv = $(this.map.getContainer());
		mapDiv.append(div);
	}

	// Display the div.
	jQuery(this.savingDialog).fadeIn();
}

PPolyCreator.prototype.hideSavingDialog = function() {
	jQuery(this.savingDialog).hide();
}

PPolyCreator.prototype.addSavedPoly = function(places) {
	// remove each place from the map
	if (PEnvironment.pageName == "report_area") {
		var customplaces = polycreator.customPlaces;
		for (var i in customplaces) {
			polycreator.removeCustomRegionFromMap(customplaces[i].place);
		}
	}

	custom_place = places[0];

	//polycreator.addPolyMarker(places[0].getVertices(),map);
	polycreator.addPolylines(places[0], map);

	// Note: uncomment out this line when the option to fill the places within the custom region needs to be added back in to the app
	// There are a few places in MapCommon.js that need to be uncommented out, all are noted just as is it is here
	//polycreator.boundaryWidget.enable();
	if (polycreator.buildType == polycreator.ASSEMBLE) {
		polycreator.resetBuildType();
		// Note: uncomment out this line when the option to fill the places within the custom region needs to be added back in to the app
		// There are a few places in MapCommon.js that need to be uncommented out, all are noted just as is it is here
		//polycreator.boundaryWidget.show();
	}
	if (polycreator.buildType == polycreator.CIRCLE) {
		polycreator.circleWidget.hide();
	}

	toggleCustomRegion();

	// animate mypolicymap link
	saveEffect();

	// refresh the drop down with the new custom place
	polycreator.dropdown.setUsersPlaces();
	polycreator.hideSavingDialog();
}

/**************************************************************
***** Custom Region:: Build Draw, Assembled, Radius Regions ****
***************************************************************/
function toggleCustomRegion() {
	var custreg = document.getElementById("customregion");
	if (!isCustomRegionOn()) {
		map.closeInfoWindow();
		custreg.innerHTML = "Disable Custom Region";
		jQuery(custreg).parent().addClass("on");
		//jQuery('#buildregionbox').slideDown(300);
		var alerter = new PAlerter2();
		var content = "<h2>Select the type of custom region you wish to build:</h2>" +
				"<div id='customregionoptions'><input type='radio' name='customregiontype' value='1' checked/><label>Drawn Custom Region</label><br />" +
				"<input type='radio' name='customregiontype' value='2' /><label>Assembled Custom Region</label><br />" +
				"<input type='radio' name='customregiontype' value='3' /><label>Radius Region</label></div>";
		var position = getAlertPosition(parseInt(alerter.box.style.width));
		var next = function() {
			var type = jQuery("#customregionoptions").find("input:checked").attr("value");
			selectCustomRegionType(type);
		};
		var cancel = function() {cancelCustomRegion()};
		alerter.popup(content,position[0],position[1],"Cancel","OK", next, cancel)
	} else {
		cancelCustomRegion();
		map.disablePolyCreator(polycreator);
//		if (polycreator.boundaryWidget)
//		polycreator.boundaryWidget.hide();
		polycreator.cancelPoly();
		polycreator.toggleWidgets();
		// enable the map options link under the map because if user was assembling region than this would've been disabled
		if(PEnvironment.pageName == 'maps' || PEnvironment.pageName == 'analytics') {
			mapOptionsEnable();
		}
	}
}

function selectCustomRegionType(type) {
	var alerter = new PAlerter2();
	var content = "";
	if (type == 1) {
		polycreator.buildType = polycreator.DRAW;
		content = "<h2>Drawn Custom Region</h2>" +
			"<p>To create a Drawn Custom Region, click a spot on the map, move your mouse to another spot and click, " +
			"and continue until you close the region by clicking on the first point.</p>" +
			"<p>At that point you may name the region and save it to My PolicyMap. </p>" +
			"<p>To disable this feature, click \"Disable Custom Region\".</p>";
	} else if (type == 2) {
		polycreator.buildType = polycreator.ASSEMBLE
		content = "<h2>Assembled Custom Region</h2>" +
			"<p>To create an Assembled Custom Region, click inside the boundaries you wish to include.  To remove a boundary, click it again.</p>" +
			"<p>When you are finished, click \"Save Region\" to name your region and save it to My PolicyMap.</p>" +
			"<p>The map will display the default boundary for the current zoom level.  The boundary will display in the pulldown and can be changed there.</p>" +
			"<p>To disable this feature, click \"Disable Custom Region\" at the bottom of the map.</p>";
	} else if (type == 3) {
		polycreator.buildType = polycreator.CIRCLE;
		content = "<h2>Radius Region</h2>" +
			"<p>To create a Radius Region, either enter an address to center the radius, or click directly on the map.</p>" +
			"<p>The default radius is 0.5 miles, which can be changed in the white box on the map. When you are finished, click \"GO\", which will allow you to name your region and click \"Save\" to save it to My PolicyMap.</p>" +
			"<p> To disable this feature, click \"Disable Custom Region\".</p>";
	}
	var position = getAlertPosition(parseInt(alerter.box.style.width));
	var next = function() {
		map.enablePolyCreator(polycreator);
		polycreator.initCustomRegionType();

		// When radius selection show the widget with the address search in it
		if (polycreator.buildType == polycreator.CIRCLE)
			polycreator.circleWidget.show();

		// When assembling places the boundary widget should start as enabled
		// For the other custom regions it enables once the place is saved
		if (polycreator.buildType == polycreator.ASSEMBLE) {
			polycreator.boundaryWidget.enable();
			// For now we need to refresh the map options layers every time user wants to build an assembled region.
			// To fix we probably need to make the map options an object that then we can keep track of if layers were turned on before user started to build
			// and then when the user disables building a custom region those map layers can be turned back on that were on.
			if (PEnvironment.pageName == 'maps') {
				map.mapOptions.setToDefault();
				// make sure the map options box is hidden
				jQuery("#optsbox").hide();

				// disables the map options link under the map
				mapOptionsDisable();
			}

			// Note: Put this out of this if statement when seeing polygons within custom regions is added back to the app
			polycreator.boundaryWidget.show();
		}
	};
	var cancel = function() {cancelCustomRegion()};
	alerter.popup(content,position[0],position[1],"Cancel","OK", next, cancel)
}

function cancelCustomRegion() {
	var custreg = document.getElementById("customregion");
	custreg.innerHTML = "Build Custom Region";
	jQuery(custreg).parent().removeClass("on");
}


/*****************************
*** Class: PMap extensions ***
*****************************/
PMap.prototype.enablePolyCreator = function(polycreator) {
	polycreator.attachMap(this);
};

PMap.prototype.disablePolyCreator = function(polycreator) {
	polycreator.detachMap(this);
};

