﻿/**
 * @author Yury Tritenko. Guidelines provided by Marianne Cardwell.
 * @classDescription Implements calls to Indy ISA Web Services and provides utiltity functions for all libraries
 */


/**
 * @namespace Indy.Services
 */
dojo.provide("Indy.Services");

Indy.Services.Utilities = function() {
    /******** Private variables (begins)********/
	/** Private variable **/
    var handlerURL = 'handler/AJAXProxyHandler1.ashx?url=';
	/** Private variable **/
	var applicationURL = document.URL;
	/** Private variable **/
    var applicationURLSplit = applicationURL.split("/");
	/** Private variable **/
    var applicationDomain = applicationURLSplit[2];
	/** Private variable. 
	 * Error handler
	 */
	var addressError = new Error (" ERROR: Inconsistent address (address cannot be an empty string)"); 
   /** Private variable. 
	 * Error handler (inconsistent address)
	 */
    var levelError = new Error (" ERROR: Level value is out of the enumeration scope");
    /** Private variable. 
	 * Error handler (inconsistent minimum canidate score)
	 */
	var minimumCandidateScoreError = new Error (" ERROR: Inconsistent minimumCandidateScore (cannot be an empty string or greater than 100)");
     /** Private variable. 
	 * Error handler (inconsistent map)
	 */
	var mapError = new Error (" ERROR: Inconsistent map source (map cannot be null)");
    /** Private variable. 
	 * Error handler (inconsistent layers source)
	 */
	var layersError = new Error (" ERROR: Inconsistent layers source (layers cannot be null)");
    /** Private variable. 
	 * Error handler (inconsistent geometry)
	 */
	var geometryError = new Error (" ERROR: Inconsistent geometry (geometry cannot be null)");
    /** Private variable. 
	 * Error handler (inconsistent coordinates)
	 */
	var coordinatesError = new Error (" ERROR: Inconsistent coordinates (coordinates cannot be null or nothing)");
    /** Private variable. 
	 * Error handler (inconsistent features)
	 */
	var featuresError = new Error (" ERROR: Inconsistent features source (features cannot be null)");
	/** Private variable. 
	 * Error handler (inconsistent candidate and/or match scores)
	 */
	var candidatesError = new Error ("ERROR: Candidate score is greater than Match score or they have incosistent values (empty or greater than 100)");
	/** Private variable. 
	 * Error handler (inconsistent geocode levels)
	 */
	var geocodeLevelsError = new Error ("ERROR: startLevel cannot be greater than endLevel");
	/******** Private variables (ends)********/

    /******** Private methods (begins)********/
	
    /**
    * Private method. 
    * This function implements direct calls to service web methods (calls within same domain)
    * @param {String} url specifies url to the service endpoint
    * @param {object} parameters parameters to be passed to the service's Web method (object)
    * @param {function} onComplete the function to be called when the query is complete.
    *                   Input parameter for this function is the data returned by the Web method.
    * @param {function} onError the function to be called when the query is incomplete.
    *                   Input parameter for this function is the error message returned by the Web service.
    * @return nothing
    */
	var callServiceDirectly = function(url, parameters, onComplete, onError) {
        //convert parameters to JSON string
		var parametersJSON = dojo.toJson(parameters); 
        //forms request to the specified Web method
		dojo.rawXhrPost({ 
            url: url,
            handleAs: 'json',
            postData: parametersJSON,
            headers: { "Content-Type": "text/json" },
            timeout: 45000,
            //function to be run in case of successful call to the specified Web method
			load: function (data) { 
                if (data == null)
                {
                    onError (data);
                /*}else if (data.Errors){
                    if (data.Errors.length > 0){
                        var dataErrorMessage = "Web service has been accessed with errors..."
                        onError (dataErrorMessage);
                        errors = data.Errors;
                        for (var x in errors){
                            onError (errors[x].Message);
                        }
                    }else{
                        onComplete(data);
                    }*/
                }else{
                    console.log("Indy.Services.Utilities.callServiceDirectly--> Web service has been accessed directly");
                    onComplete(data);
                }  
            },
            //function to be run in case of failed call to the specified Web method
			error: function (error) { 
                onError(error);
            }
       });
    }
    
    /**
    * Private method. 
    * This function implements calls to service web methods through proxy (inter-domain calls)
    * @param {String} url specifies url to the service endpoint
    * @param {object} parameters parameters to be passed to the service's Web method (object)
    * @param {function} onComplete the function to be called when the query is complete.
    *                   Input parameter for this function is the data returned by the Web method.
    * @param {function} onError the function to be called when the query is incomplete.
    *                   Input parameter for this function is the error message returned by the Web service.
    * @return nothing
    */
	var callServiceProxy = function(url, parameters, onComplete, onError) {
        //convert parameters to JSON string
		var parametersJSON = dojo.toJson(parameters);
        //forms request to the specified Web method
		dojo.rawXhrPost({ 
            //url: handlerURL + url + '&input=' + parametersJSON,
            url: handlerURL + url,
            handleAs: 'json',
            postData: parametersJSON,
            headers: { "Content-Type": "text/json" },
            timeout: 45000,
            //function to be run in case of successful call to the specified Web method
			load: function (data) { 
                if (data == null)
                {
                    onError (data);
                /*}else if (data.Errors){
                    if (data.Errors.length > 0){
                        var dataErrorMessage = "Web service has been accessed with errors..."
                        onError (dataErrorMessage);
                        errors = data.Errors;
                        for (var x in errors){
                            onError (errors[x].Message);
                        }
                    }else{
                        onComplete(data);
                    }*/
                }else{
                    console.log("Indy.Services.Utilities.callServiceProxy--> Web service has been accessed through proxy");
                    onComplete(data);
                }  
            },
            //function to be run in case of failed call to the specified Web method
			error: function (error) { 
                onError(error);
            }
       });
    }
   	/******** Private methods (ends)********/
   
    /******** Public methods (begins)********/
    /**
    * Public method. 
    * This function creates layer object
    * @param {String} layerName specifies name of the layer to be queried
    * @param {String} filter specifies filter for the layer query
    * @param {Array} fields specifies fields to be queried within the given layer
    * @return {Object} Returns layer object
    */ 
	var createLayer = function(layerName, filter, fields){   
        var layer = { //forms layer as an object
            name: layerName,
            filterWhere: filter,
            fields: fields
        }
        return layer;
    }
    
    
	/**
	* Public method. 
    * This function creates layer object
    * @param {Array} layers specifies array of layer objects.
    * @return {String} Returns XML string.
    */ 
    var createLayerRequest = function(layers) {
        var xmlRequest = "<Request><Layers>";
        for (var x in layers)
        {
            xmlRequest = xmlRequest + "<Layer Name=" + '"' + layers[x].name + '"' + ' ' + "FilterWhere=" + '"' + layers[x].filterWhere + '"' + ">" + "<Fields>";
            var fields = layers[x].fields;
            for (var y in fields)
            {
                xmlRequest = xmlRequest + "<Field Name=" + '"' + fields[y] + '"' + " " + 'Value=""' + "/>";
            }
            xmlRequest = xmlRequest + "</Fields></Layer>";
        }
        xmlRequest = xmlRequest + "</Layers></Request>";
        return xmlRequest;
    }
    
	
    /**
    * Public method. 
    * This function redirects calls to services' endpoints according to the domain of calling application
    * @param {String} url path to the speceified Web method
   	* @param {object} parameters parameters to be passed to the service's Web method (object)
    * @param {function} onComplete the function to be called when the query is complete.
    *                   Input parameter for this function is the data returned by the Web method.
    * @param {function} onError the function to be called when the query is incomplete.
    *                   Input parameter for this function is the error message returned by the Web service.
    * @return nothing
    */
	var callService = function(url, parameters, onComplete, onError) {
        var urlSplit = url.split("/");
        var serviceDomain = urlSplit[2];
        if (applicationDomain == serviceDomain){
            console.log("Indy.Services.Utilities.callService--> Direct call to the service...");
            callServiceDirectly(url, parameters, onComplete, onError);
        }else{
            console.log("Indy.Services.Utilities.callService--> Call to the service through proxy...");
            callServiceProxy(url, parameters, onComplete, onError);
        } 
    }
    
    
    /**
     * Public method. 
     * This function generates GML format string for specified geometry object
     * @param {esri.geometry.Geometry | OpenLayers.Geometry} geom specifies geometry object
     * @param {Boolean} buffer specifies format features of the generated string
     * @return {String} Returns GML format string
     */
	var createGML = function(geom, buffer) {
        var gml = '';
        switch (geom.type) {
            case "point":
                if (buffer == true)
                {
                    gml = '<RequestGeometries><Geometries><BufferGeometry><Geometry><gml:Point xmlns:gml="http://www.opengis.net/gml>';
                }else{
                    gml = '<gml:Point xmlns:gml="http://www.opengis.net/gml>';
                }
                gml = gml + '<gml:pos>' + geom.x + ' ' + geom.y + '</gml:pos>';
                if (buffer == true)
                {
                    gml = gml + '</gml:Point></Geometry></BufferGeometry></Geometries></RequestGeometries>';
                }else{
                    gml = gml + '</gml:Point>';
                }
                break;
            case "multipoint": //not sure about this GML
                var points = geom.points;
                gml = '<gml:MultiPoint xmlns:gml="http://www.opengis.net/gml>';
                for (var ii = 0; ii < points.length; ii++) {
                    var point = points[ii];
                    gml = gml + '<gml:Point><gml:pos>' + point.x + ' ' + point.y + '</gml:pos></gml:Point>';
                }
                gml = gml + '</gml:MultiPoint>';
                break;
            case "polyline":
                var paths = geom.paths;
                gml = '<gml:LineString>';
                for (var ii = 0; ii < paths.length; ii++) {
                    var points = paths[ii];
                    gml = gml + '<gml:posList>';
                    for (var jj = 0; jj < points.length; jj++) {
                        var point = points[jj];
                        gml = gml + point[0] + ',' + point[1] + ' ';
                    }
                    gml = gml + '</gml:posList>';
                }
                gml = gml + '</gml:LineString>';
                break;
            case "polygon":
                var rings = geom.rings;
                if (buffer == true)
                {
                    gml = '<RequestGeometries><Geometries><BufferGeometry><Geometry><gml:Polygon xmlns:gml="http://www.opengis.net/gml"><gml:PolygonPatch><gml:exterior>';
                }else{
                    gml = '<gml:Polygon xmlns:gml="http://www.opengis.net/gml"><gml:PolygonPatch><gml:exterior>';
                }
                for (var ii = 0; ii < rings.length; ii++) {
                    var points = rings[ii];
                    gml = gml + '<gml:LinearRing><gml:posList>';
                    var pointStart = points[0];
                    coordStart = pointStart[0] + ',' + pointStart[1];
                    for (var jj = 0; jj < points.length; jj++) {
                        var point = points[jj];
                        gml = gml + point[0] + ',' + point[1] + ' ';
                    }
                    gml = gml + coordStart + '</gml:posList></gml:LinearRing>';
                }
                if (buffer == true)
                {
                    gml = gml + '</gml:exterior></gml:PolygonPatch></gml:Polygon></Geometry></BufferGeometry></Geometries></RequestGeometries>'
                }else{
                    gml = gml + '</gml:exterior></gml:PolygonPatch></gml:Polygon>';
                }
                break;
            case "extent":
                var xmax = geom.xmax;
                var xmin = geom.xmin;
                var ymax = geom.ymax;
                var ymin = geom.ymin;
                gml = '<gml:Polygon xmlns:gml="http://www.opengis.net/gml"><gml:exterior><gml:LinearRing><gml:posList>';
                gml = gml + xmin + ' ' + ymin + ' ' + xmin + ' ' + ymax + ' ' + xmax + ' ' + ymax + ' ' + xmax + ' ' + ymin + ' ' + xmin + ' ' + ymin;
                gml = gml + '</gml:posList></gml:LinearRing></gml:exterior></gml:Polygon>';
                break;
        }
        return gml;
    }
    
    
    /**
     * Public Method
     * This function generates esri.geometry objet based on the GML string passed to the function
     * @param {esri.Map | VEMap | OpenLayers.Map} map the map the result will be placed on 
	 *				(also necessary for projection).
     * @param {String} gml GML string describing geometry object
     * @return {String} Returns esri.geometry.Geometry object
     */
    var GMLToGeometry = function (map, gml){
        var mapType = Indy.Maps.Utilities.determineMapType(map);
        var geom;
        //Find out which type of geometry has to be generated (polygon, point, line)
		switch(mapType)
		{
		case "esri.Map":
		    var spatialReference = Indy.Maps.Utilities.getProjection(map);
		    var typePolygon = gml.indexOf('gml:Polygon',0);
		    var typePoint = gml.indexOf('gml:Point',0);
		    var typeLine = gml.indexOf('gml:LineString',0)
            //Case when the geometry type supposed to be generated is Polygon
		    if (typePolygon != -1){
                console.log(typePolygon);
                geom = new esri.geometry.Polygon(); 
                var positionRing = 0; 
                var positionPosList = 0;
                var geomRingsArray = [];
                while (positionRing != -1)
                {
                    positionRing = gml.indexOf('<gml:LinearRing>', (positionRing + 1));
                    console.log(positionRing);
                    positionPosList = gml.indexOf('<gml:posList>', (positionPosList + 1));
                    console.log(positionPosList);
                    var startRingValues = gml.indexOf('>', positionPosList);
                    var endRingValues = gml.indexOf('<', startRingValues);
                    var ringString = gml.slice((startRingValues + 1), (endRingValues));
                    var ringArray = ringString.split(' ');
                    var geomRingArray = [];
                    for (var x in ringArray){
                        var ringPoint = ringArray[x];
                        var ringPointArray = ringPoint.split(',');
                        var xCoordRingPoint = ringPointArray[0];
                        var yCoordRingPoint = ringPointArray[1];
                        var geomPointArray = [xCoordRingPoint, yCoordRingPoint];
                        geomRingArray.splice(geomRingArray.length, 0, geomPointArray);
                    }
                    geomRingsArray.splice(geomRingsArray.length, 0, geomRingArray);
                    positionRing = gml.indexOf('<gml:LinearRing>', (positionRing + 1));
                }
                console.log(geomRingsArray);
                geom.rings = geomRingsArray;
            }
		    //Case when the geometry type supposed to be generated is Point
		    else if (typePoint != -1){
			    var positionPos = gml.indexOf('<gml:pos>', 0);
			    var positionStartPos = gml.indexOf('>', positionPos);
			    var positionEndPos = gml.indexOf('<', positionStartPos);
			    var pointString = gml.slice((positionStartPos + 1), positionEndPos);
			    console.log(pointString);
			    var pointArray = pointString.split(',');
			    geom = new esri.geometry.Point(pointArray, spatialReference);
		    }
		    //Case when the geometry type supposed to be generated is Polyline
		    else if (typeLine != -1){
		        var positionPos = gml.indexOf('<gml:posList>', 0);
		        var positionStartPos = gml.indexOf('>', positionPos);
			    var positionEndPos = gml.indexOf('<', positionStartPos);
			    var pointString = gml.slice((positionStartPos + 1), positionEndPos);
			    console.log(pointString);
			    var pointsArray = [];
			    var pointsStringArray = pointString.split(' ');
			    for (var i in pointsStringArray){
			        var pointCoord = pointsStringArray[i].split(',');
			        pointsArray.push(pointCoord);
			    }
			    var paths = [];
			    for (var j in pointsArray){
			        var point = new esri.geometry.Point(pointsArray[j], spatialReference);
			        paths.push(point);
			    }
			    var geom = new esri.geometry.Polyline(spatialReference);
			    geom.addPath(paths);
		    }
		    break;
		case "MSVE_MapContainer":
		    var typePolygon = gml.indexOf('gml:Polygon',0);
		    var typePoint = gml.indexOf('gml:Point',0);
		    var typeLine = gml.indexOf('gml:LineString',0)
		    //Case when the geometry type supposed to be generated is a VE Point
		    if (typePoint != -1){
			    var positionPos = gml.indexOf('<gml:pos>', 0);
			    var positionStartPos = gml.indexOf('>', positionPos);
			    var positionEndPos = gml.indexOf('<', positionStartPos);
			    var pointString = gml.slice((positionStartPos + 1), positionEndPos);
			    console.log(pointString);
			    var pointArray = pointString.split(',');
			    var point = new VELatLong(pointArray[0], pointArray[1]);
                geom = new VEShape(VEShapeType.Pushpin, point);
		    }
		    //Case when the geometry type supposed to be generated is a VE Polygon
		    else if (typePolygon != -1){
		        var positionPos = gml.indexOf('<gml:posList>', 0);
			    var positionStartPos = gml.indexOf('>', positionPos);
			    var positionEndPos = gml.indexOf('<', positionStartPos);
			    var pointsString = gml.slice((positionStartPos + 1), positionEndPos);
			    var coordArray = pointsString.split(' ');
			    var pointsArray = [];
			    for (var i in coordArray){
			        var pointString = coordArray[i];
			        var pointArray = pointString.split(",");
			        pointsArray.push(pointArray);
			    }
			    var points = [];
			    for (var i in pointsArray){
                    var pointCoord = pointsArray[i];
                    var xCoord = parseFloat(pointCoord[0]);
                    var yCoord = parseFloat(pointCoord[1]);
                    var point = new VELatLong(xCoord, yCoord);
                    points.push(point);
                }
                map.SetMapView(points);
                var geom = new VEShape(VEShapeType.Polygon, points);
		    }
		    //Case when the geometry type supposed to be generated is Polyline
		    else if (typeLine != -1){
		        var positionPos = gml.indexOf('<gml:posList>', 0);
			    var positionStartPos = gml.indexOf('>', positionPos);
			    var positionEndPos = gml.indexOf('<', positionStartPos);
			    var pointsString = gml.slice((positionStartPos + 1), positionEndPos);
			    var coordArray = pointsString.split(' ');
			    var pointsArray = [];
			    for (var i in coordArray){
			        var pointString = coordArray[i];
			        var pointArray = pointString.split(",");
			        pointsArray.push(pointArray);
			    }
			    var points = [];
			    for (var i in pointsArray){
                    var pointCoord = pointsArray[i];
                    var xCoord = parseFloat(pointCoord[0]);
                    var yCoord = parseFloat(pointCoord[1]);
                    var point = new VELatLong(xCoord, yCoord);
                    points.push(point);
                }
                map.SetMapView(points);
                var geom = new VEShape(VEShapeType.Polyline, points);
		    }
		    break;
		case "OpenLayers.Map":
		    var typePolygon = gml.indexOf('gml:Polygon',0);
		    var typePoint = gml.indexOf('gml:Point',0);
		    var typeLine = gml.indexOf('gml:LineString',0)
		    //Case when the geometry type supposed to be generated is a OL Point
		    if (typePoint != -1){
			    var positionPos = gml.indexOf('<gml:pos>', 0);
			    var positionStartPos = gml.indexOf('>', positionPos);
			    var positionEndPos = gml.indexOf('<', positionStartPos);
			    var pointString = gml.slice((positionStartPos + 1), positionEndPos);
			    console.log(pointString);
			    var pointArray = pointString.split(',');
			    var point = new OpenLayers.Geometry.Point(pointArray[0], pointArray[1]);
                var geom = [point];
		    }
		    //Case when the geometry type supposed to be generated is a OL Polygon
		    else if (typePolygon != -1){
		        var positionPos = gml.indexOf('<gml:posList>', 0);
			    var positionStartPos = gml.indexOf('>', positionPos);
			    var positionEndPos = gml.indexOf('<', positionStartPos);
			    var pointsString = gml.slice((positionStartPos + 1), positionEndPos);
			    var coordArray = pointsString.split(' ');
			    var pointsArray = [];
			    for (var i in coordArray){
			        var pointString = coordArray[i];
			        var pointArray = pointString.split(",");
			        pointsArray.push(pointArray);
			    }
			    var points = [];
			    for (var i in pointsArray){
                    var pointCoord = pointsArray[i];
                    var xCoord = parseFloat(pointCoord[0]);
                    var yCoord = parseFloat(pointCoord[1]);
                    var point = new OpenLayers.Geometry.Point(xCoord, yCoord);
                    points.push(point);
                }
                console.log(points);
                var linearRing = new OpenLayers.Geometry.LinearRing(points);
                var geom = new OpenLayers.Geometry.Polygon([linearRing]);
		    }
		    //Case when the geometry type supposed to be generated is Polyline
		    else if (typeLine != -1){
		        var positionPos = gml.indexOf('<gml:posList>', 0);
			    var positionStartPos = gml.indexOf('>', positionPos);
			    var positionEndPos = gml.indexOf('<', positionStartPos);
			    var pointsString = gml.slice((positionStartPos + 1), positionEndPos);
			    var coordArray = pointsString.split(' ');
			    var pointsArray = [];
			    for (var i in coordArray){
			        var pointString = coordArray[i];
			        var pointArray = pointString.split(",");
			        pointsArray.push(pointArray);
			    }
			    var points = [];
			    for (var i in pointsArray){
                    var pointCoord = pointsArray[i];
                    var xCoord = parseFloat(pointCoord[0]);
                    var yCoord = parseFloat(pointCoord[1]);
                    var point = new OpenLayers.Geometry.Point(xCoord, yCoord);
                    points.push(point);
                }
                var geom = new OpenLayers.Geometry.LineString(points);;
		    }
		    break;
		}
        return geom;
    }
    
    
   /**
    * Public method
    * This function generates array of array objects. Each array object represents pair of coordinates
    * @param {String} coordString string representing point coordinates
    * @return {Array} Returns array of object arrays with points coordinates
    */
    var generatePointsArray = function(coordString){
        var pointsArray = [];
        var ringArray = coordString.split(" ");
        var ringArrayLength = ringArray.length;
        //Case if passed string represents coordinates of one point
		if (ringArrayLength == 1){
            var pointsArray = ringArray[0].split(",");
        }
		//Case if passed string represents coordinates of 2 or more points
		else{
            for (var i in ringArray){
                var pointArray = ringArray[i].split(",");
                pointsArray.push(pointArray);
            }
        }
        console.log(pointsArray);
        return pointsArray;
    }
    
    
	/** 
	* Public property 
	* @type {Number}
	*/
	var units = {
        None: 0, 
        Feet: 1, 
        Yards: 2, 
        Miles: 3, 
        Meters: 4, 
        Kilometers: 5
    };
    
	/** 
	* Public property
	* @type {Number}
	*/
	var spatialRelationship = { 
        Intersects: 0, 
        Contains: 1 
        };
		
	 /**
	  * Public method. 
	  * Checks address for consistency
	  * @param {String} address address to be validated for consistency
	  * @exception {addressError} Throws address exception
	  * @return nothing
	  */
	 var checkAddressConsistency = function(address){
        if (address == ''){
            throw addressError;
        }
    }
	 
 	/**
	 * Public method. 
	 * Checks level for consistency
	 * @param {number} level
	 * @exception {levelError} Throws level exception
	 * @return nothing
	 */
	var checkLevelConsistency = function(level){
        if (level != 0 && level != 1 && level !=2 && level != 3){
            throw levelError;
        }
    }
	
	/**
	 * Public method.
	 * Checks minimum candidate score for errors
	 * @param {Number} minimumCandidateScore 
	 * @exception {minimumCandidateScoreError} Throws minimum candidate score exception
	 * @return nothing
	 */
    var checkMinimumCandidateScore = function(minimumCandidateScore){
        if (minimumCandidateScore == '' || minimumCandidateScore > 100){
            throw minimumCandidateScoreError;
        }
    }
    
	/**
	 * Public method
	 * Checks map for errors
	 * @param {Object} map
	 * @exception {mapError} Throws map exception
	 * @return nothing
	 */
	var checkMapConsistency = function(map){
        if (map == null){
            throw mapError;
        }
    }
    
	/**
	 * Public method. 
	 * Checks layers for errors
	 * @param {Object} layers
	 * @exception {layersError} Throws layers exception
	 * @return nothing
	 */
	var checkLayersConsistency = function(layers){
        if (layers == null){
            throw layersError;
        }
    }
    
	/**
	 * Public method.
	 * Checks geometry for errors
	 * @param {Object} geom
	 * @exception {geometryError} Throws geometry exception
	 * @return nothing
	 */
	var checkGeometryConsistency = function(geom){
        if (geom == null){
            throw geometryError;
        }
    }
    
	/**
	 * Public method. 
	 * Checks coordinates values for errors
	 * @param {Object} x
	 * @param {Object} y
	 * @exception {coordinatesError} Throws coordinates exception
	 * @return nothing
	 */
	var checkCoordinatesConsistency = function (x, y){
        if (x == "" || x == null || y == "" || y == null){
            throw coordinatesError;
        }
    }
    
	/**
	 * Public method.
	 * Checks features for errors
	 * @param {Object} features
	 * @exception {featuresError} Throws features exception
	 * @return nothing
	 */
	var checkFeaturesConsistency = function (features){
        if (features == null){
            throw featuresError;
        }
    }
    
    /**
     * Public method
     * Checks candidate scores
     * @param {Number} minimumCandidateScore
     * @param {Number} minimumMatchScore
     * @exception {scoresError} Throws geocode score exception
     * @return nothing
     */
    var checkGeocodeScores = function(minimumCandidateScore, minimumMatchScore){
        if (minimumCandidateScore == '' || minimumCandidateScore > 100 || minimumMatchScore == '' || minimumMatchScore > 100 || minimumCandidateScore > minimumMatchScore)
        {
            throw scoresError;
        }
    }
    
    /**
     * Public method
     * Checks geocode levels
     * @param {Number} startLevel
     * @param {Number} minimumMatchScore
     * @exception {levelError} Throws geocode score exception
     * @return nothing
     */
    var checkGeocodeLevels = function(startLevel, endLevel){
        if (startLevel != 0 && startLevel != 1 && startLevel !=2 && startLevel != 3)
        {
            throw levelError;
        }else if (endLevel != 0 && endLevel != 1 && endLevel !=2 && endLevel != 3){
            throw levelError;
        }else if (startLevel > endLevel){
            throw geocodeLevelsError;
        }
    }
    
    
	return {
		callService: callService,
        createLayer:createLayer,
        createLayerRequest:createLayerRequest,
        createGML:createGML,
        units:units,
        spatialRelationship: spatialRelationship,
        checkAddressConsistency:checkAddressConsistency,
        checkLevelConsistency:checkLevelConsistency,
        checkMinimumCandidateScore:checkMinimumCandidateScore,
        checkMapConsistency:checkMapConsistency,
        checkLayersConsistency:checkLayersConsistency,
        checkGeometryConsistency:checkGeometryConsistency,
        checkCoordinatesConsistency:checkCoordinatesConsistency,
        checkFeaturesConsistency:checkFeaturesConsistency,
        checkGeocodeScores:checkGeocodeScores,
        GMLToGeometry:GMLToGeometry,
        generatePointsArray:generatePointsArray
		/** Public property **/
		/******** Public Properties (ends)********/
   }
} ();