/**
 * @author administrator
 */
require([
	"dojo/_base/declare",
	"dojo/Deferred", 
	"dojo/_base/lang",
	"esri/Map",
	"esri/Graphic",
	"esri/views/MapView",
	"esri/request",
	"esri/rest/locator", 
	"dojo/_base/array",
	"esri/geometry/SpatialReference",
	"esri/rest/geometryService",
	"esri/rest/support/ProjectParameters",
	"esri/geometry/Point",
	"esri/symbols/PictureMarkerSymbol"
], function (declare, Deferred, lang, Map, Graphic, MapView, esriRequest, locator, arrayUtils, SpatialReference, GeometryService, ProjectParameters, Point, PictureMarkerSymbol) 
{
	wvgistcLocator = new function(){
		//this.locatorEsri 		= new locator("https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer");
		//this.locatorWvgistc 	= new locator("https://services.wvgis.wvu.edu/arcgis/rest/services/Geocode/WV_Composite/GeocodeServer");
		//this.geometryService 	= new GeometryService("https://services.wvgis.wvu.edu/arcgis/rest/services/Utilities/Geometry/GeometryServer");
	
		this.view 		= null;
		
		//this.handleStandardAddress 	= new Object();
		this.handleGistcLocator		= new Object();
		
		this.standardAddress= "";
		this.address 		= null;
		this.locator_name 	= "";
		
		this.warning = "<font color='red'>Input can't be located as an address but an area. Please have your address in the standard format: <b>street address, city, state, zip</b>, and try it again.</font>";
	
		this.pSymbol 		= new PictureMarkerSymbol("img/geoLocate2.png", 25, 25);
		

		this.geocodePoint 	= new Point();

		this.locateAddress = function(callback) {
			this.view.graphics.removeAll();
			var queryParam = {
				address : this.address,
				outFields : ["Loc_name"]
			};
			
			//handleStandardAddress = this.locatorEsri.on("address-to-locations-complete", this.getStandardAddress);
	
			//this.locatorEsri.outSpatialReference = this.view.spatialReference;
			//this.locatorEsri.addressToLocations(queryParam).then(this.getStandardAddress);
			locator.addressToLocations("https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer",queryParam)
				.then(this.getStandardAddress)
				.catch(function(error){
					console.log(error);
				});
		};
		
		/*
		 * Standard Address is returned from ESRI's Address locator
		 */
		this.getStandardAddress = function(e) {
			//handleStandardAddress.remove();
			var gl = wvgistcLocator;
			var addrCandidateEsri;
	
			//arrayUtils.every(e.addresses, function(candidate) {
			if (e.length > 0) {
				addrCandidateEsri = e[0];
				gl.locator_name = addrCandidateEsri.attributes.Loc_name;
	
				wvgistcLocator.geocodePoint.x = addrCandidateEsri.location.x;
				wvgistcLocator.geocodePoint.y = addrCandidateEsri.location.y;
				wvgistcLocator.geocodePoint.spatialReference = new SpatialReference(102100);
	
				//console.log(addrCandidateEsri.score);
				var formalAddress = addrCandidateEsri.address;
				wvgistcLocator.standardAddress = formalAddress;
	
				if (addrCandidateEsri.score > 0) {
	
					// If the user input can be treated as standard address, gistc's geocoding service will be used first.
					// If good locations can't be found, the ESRI's geocoding results will be used.
					//Sample standardized address: 1004 Pineview Dr, Morgantown, WV, 26505
					if (formalAddress.split(",").length == 4) {
						var address1 = formalAddress.split(",");
	
						var full_address1 = address1[0];
						var full_address1_number = full_address1.split(" ")[0];
						var streetAddress = address1[0];
						var zipCode = "";
	
						// isNaN(): check the input whether it is a number or not.
						// 			The return is false if the input is a number
	
						// In this case, 	if the first part of the address section ia number, the return address formamt of ESRI will be taken.
						// 					otherwise, the orginal input will be forwarded to GISTC's geocoding service
						if (isNaN(parseInt(full_address1_number))) {
							//streetAddress = ((this.address.replace(".",",")).split(","))[0];
	
						} else {
							zipCode = address1[3];
						}
	
						// the format of address for GISTC's geocoding locator
						var objAddress = {
							Street: streetAddress,
							City: address1[1],
							State: (address1[2]),
							Zone: zipCode
						}
						// Specify output fileds from Geocoding results.
						var myOutFields = ["Loc_name", "Score"];
	
						// combine address and output field to generate a geocoding paramter
						// The acutual parameter including address, outFields, searchExtent
						var queryParam = {
							address : objAddress,
							outFields : myOutFields
						}
	
						//gl.locatorWvgistc.outSpatialReference 	= gl.view.spatialReference;
						//gl.locatorWvgistc.addressToLocations(queryParam).then(gl.LocateWithWvgistcLocator);
						locator.addressToLocations("https://services.wvgis.wvu.edu/arcgis/rest/services/Geocode/WV_Composite/GeocodeServer",queryParam)
							.then(this.LocateWithWvgistcLocator)
							.catch(function(error){
								console.log(error);
							});
					}

					// if the input is just a place name or esri's locator can't process it
					else {
						console.log(formalAddress);
						// use GISTC's locator to locate the orginal user input
						var oa = wvgistcLocator.address.SingleLine.split(",");
						
						if ( oa.length ==4 ){
							var objAddress = {
								Street : oa[0],
								City : oa[1],
								State : oa[2],
								Zone : oa[3]
							};
							
							var queryParam = {
								address : objAddress,
								outFields : myOutFields
							}
	
							//gl.locatorWvgistc.outSpatialReference 	= gl.view.spatialReference;
							
							//gl.locatorWvgistc.addressToLocations({address : objAddress, outFields : ["*"]});
							//handleGistcLocator = gl.locatorWvgistc.on("address-to-locations-complete", gl.LocateWithWvgistcLocator);
							//gl.locatorWvgistc.addressToLocations(queryParam).then(gl.LocateWithWvgistcLocator);
							//gl.locatorWvgistc.on("error", function(e){
								//console.log(e);
							//});
							locator.addressToLocations("https://services.wvgis.wvu.edu/arcgis/rest/services/Geocode/WV_Composite/GeocodeServer",queryParam)
							.then(this.LocateWithWvgistcLocator)
							.catch(function(error){
								console.log(error);
							});
							
						}
						else {
							console.log("Esri locator service: " + gl.locator_name);
							//document.getElementById("locatorSource").innerHTML = "(Source: ESRI locator service - " + gl.locator_name + ")";
							//document.getElementById("locatorSource").style.display = "block";
							//gl.map.centerAndZoom(gl.geocodePoint, 8);
							console.log(gl.geocodePoint);
							gl.view.center = gl.geocodePoint;
							gl.view.zoom = 12;
						}
					}					
				} 
				else {
					addressInfo = {	"LocatorName": "A third party locator",
									"FormalAddress": formalAddress,
									"Warning": "<font color='red'>Oops: Input can't be located as an address but an area. </font>",
									"ActualLocation": ""};
					
					console.log("Esri locator service" + addrCandidateEsri.attributes.Loc_name);
					//document.getElementById("locatorSource").innerHTML = "(Source: ESRI locator service)";
					//document.getElementById("locatorSource").style.display = "block";
					gl.view.graphics.add(new Graphic(gl.geocodePoint, gl.pSymbol));
					// pSymbol: defined at the very top of the function of getStandardAddress
					//gl.map.centerAndZoom(gl.geocodePoint, 6);
					gl.view.center = gl.geocodePoint;
					gl.view.zoom = 10;
				}
			} else {
				addressInfo = {	"LocatorName": wvgistcLocator.standardAddress,
								"FormalAddress": wvgistcLocator.standardAddress,
								"Warning": "<font color='red'>Oops: Input can't be located as an address but an area. </font>",
								"ActualLocation": ""};
					
				console.log("Address can't be located!");
				alert("Address can't be located. Please make sure your input meets the stardard address format.");
			}
		};
		
		this.ondone = function(e) {
			alert(e);	
		};
		
		this.showError = function(e) {
			alert(e);
		};
	
		this.LocateWithWvgistcLocator = function(e) {
			//handleGistcLocator.remove();
			var gl = wvgistcLocator;
	
			if (e.length > 0) {
				var addrCandidate = e[0];
				var pt1 = new Point();
				pt1.x = addrCandidate.location.x;
				pt1.y = addrCandidate.location.y;
				pt1.spatialReference = gl.view.spatialReference;
	
				// if WV Locator got good geocoding score, the bing's address will be replaced
				// otherwise, jump to ELSE statement to display ESRI's address
				if (addrCandidate.score > 79) {
					var locatorName = addrCandidate.attributes.Loc_name;
					var locatortext = "";
					
					if (locatorName.toLowerCase().indexOf("site")>-1)
					{
						locatortext = "WV Site Locator";
					}
					if (locatorName.toLowerCase().indexOf("street")>-1)
					{
						locatortext = "WV Street Locator";
					}

					addressInfo = {	"LocatorName": locatortext,
									"FormalAddress": addrCandidate.address,
									"Warning": "<font color='red'>Warning</font>: Verify the building address on the map. If the map location is incorrect, then navigate to the correct location.",
									"ActualLocation": 'Geographic Coordinate: (' + addrCandidate.location.x.toFixed(2) + ',' + addrCandidate.location.y.toFixed(2) + ')'};
					console.log("WV Site or Street Locator");
					//document.getElementById("locatorSource").innerHTML = "(Source: " + locatortext + ")";
					//document.getElementById("locatorSource").style.display = "block";				
					gl.view.graphics.add(new Graphic(pt1, gl.pSymbol));
					// pSymbol: defined at the very top of the function of getStandardAddress
					//gl.map.centerAndZoom(pt1, 12);
					gl.view.center = pt1;
					gl.view.zoom = 14;
					/*var params = new ProjectParameters();
					params.geometries = [pt1];
					params.outSpatialReference = new SpatialReference({wkid:4326});
	
					gl.geometryService.project(params).then(function(newPoints){
						console.log("WV Site or Street Locator");
						//document.getElementById("locatorSource").innerHTML = "(Source: " + locatortext + ")";
						//document.getElementById("locatorSource").style.display = "block";				
						//gl.view.graphics.add(new Graphic(pt1, gl.pSymbol));
						// pSymbol: defined at the very top of the function of getStandardAddress
						//gl.map.centerAndZoom(pt1, 12);
						gl.view.center = pt1;
						gl.view.zoom = 12;
					}, function(e){
						console.log(e);
						//$("#" + warning11).css("display", "table-row");
						//alert("This parcel has no corresponding geometry available.");
					});*/
				}
				// if the locator score is less than 80, the Esri's address will keep
				else {
					addressInfo = {	"LocatorName": "A third party locator",
									"FormalAddress": '<font color="red">Returned address</font>: ' + addrCandidate.address,
									"Warning": 'Search on a different address or navigate using the zoom or pan functions to the area of interest.',
									"ActualLocation": ""};
					
					console.log("Esri locator service: " + gl.locator_name);
					//document.getElementById("locatorSource").innerHTML = "(Source: ESRI locator service - " + gl.locator_name + ")";
					//document.getElementById("locatorSource").style.display = "block";
					gl.view.graphics.add(new Graphic(gl.geocodePoint, gl.pSymbol));
					gl.view.center = gl.geocodePoint;
					gl.view.zoom = 10;
				}
			}
			// if no result from Gistc's locator
			else {
				addressInfo = {	"LocatorName": "A third party locator",
								"FormalAddress": '<font color="red">Returned address</font>: ' + wvgistcLocator.standardAddress,
								"Warning": "<font color='red'>Input is in Stree Address format. But, it can't be located by WV geocoding locators.</font>",
								"ActualLocation": ""};
				
				console.log("Input is in Street Address format. But locating result is from ESRI locator service: " + gl.locator_name);
				//document.getElementById("locatorSource").innerHTML = "(Source: ESRI locator service - " + gl.locator_name + ")";
				//document.getElementById("locatorSource").style.display = "block";
				gl.view.graphics.add(new Graphic(gl.geocodePoint, gl.pSymbol));
				gl.view.center = gl.geocodePoint;
				gl.view.zoom = 10;
			}
		};		
	}
})