﻿/** @class Class to do basic operations on the points
@extends Ext.Component
*/
TNRIS.GeoCodeCalc = function (config) {
    // Reference: http://pietschsoft.com/post/2008/02/Calculate-Distance-Between-Geocodes-in-C-and-JavaScript.aspx/
    Ext.apply(this,config);
    
    this.EarthRadiusInKilometers = 6378.135;
    this.EarthRadiusInMiles = 3963.15;
};

Ext.extend(TNRIS.GeoCodeCalc,Ext.Component,
    /** @scope TNRIS.GeoCodeCalculator*/
    {
        MILES: 'miles',
        KILOMETERS: 'kilometers',
        
        toRadian : function(v) {
                return v * (Math.PI / 180);
        },
        
        diffRadian : function(v1, v2) {
                return this.toRadian(v2) - this.toRadian(v1);
        },
            
        calcDistance : function(lat1, lng1, lat2, lng2, radius) {
                return radius * 2 * Math.asin(Math.min(1, Math.sqrt(( Math.pow(Math.sin((this.diffRadian(lat1, lat2)) / 2.0), 2.0) + Math.cos(this.toRadian(lat1)) * Math.cos(this.toRadian(lat2)) * Math.pow(Math.sin((this.diffRadian(lng1, lng2)) / 2.0), 2.0))))); 
        },
            
        toDegrees : function(radians){
                return radians * 180 / Math.PI;
        },
        
        calcMultiPointDistance: function(points,unit) {
            var earthRadius;
            var distance = 0;
        
            if (unit == this.MILES) { earthRadius = this.EarthRadiusInMiles; }
            else { earthRadius = this.EarthRadiusInKilometers; }

            for (var i=1; i< points.length; i++) {
                distance += this.calcDistance(points[i-1].Latitude,points[i-1].Longitude,points[i].Latitude,points[i].Longitude,earthRadius);
            }

            return distance;
        },
        
        calcPersistedShapeAttributes: function(shapes,contextID,callbackFunction) {
            var values=[];

            for (var i=0; i< shapes.length; i++) {
                var points = shapes[i].GetPoints();
                var type  = shapes[i].GetType();

                if (points.length >1) { //checking for point shape
                    values.push({type:type , points:points});
                }
            }
                
            if (values.length >0 ) {
                PageMethods.calculateShapeAttributes( {shapes : values},contextID, function(result) {
                    callbackFunction(result);
                }.bind(this));
            }
        },
        
        //to calculate the shape parameters of the shape drawn by map tool bar
        calcDrawingShapeAttributes: function(shape,unit) {
            var length = 0;
            var area =0;
            var radius = 0;

            if (null == shape) {
                return null;
            }
            
            var points = shape.GetPoints();
            var type = shape.GetType();

            if (points.length < 2 ){
                return null;
            }

            if (type == 'Polyline') {
                length = this.calcMultiPointDistance(points,unit);
            } else if (type =='Polygon')  {
            
                //check if first 3 points are the same to check if polygon created with dummy points
                if ( (points[0].Latitude == points[1].Latitude ) && (points[1].Latitude == points[2].Latitude) && (points[0].Longitude == points[1].Longitude) &&(points[1].Longitude == points[2].Longitude)) {
                    return null;
                }
            
                var expectedShape ='unknown' ;
                if (points.length == 5 ) {
                    if ((points[0].Latitude == points[1].Latitude) && (points[0].Longitude == points[3].Longitude)&& (points[2].Latitude == points[3].Latitude)&& (points[2].Longitude== points[1].Longitude) ) {
                        expectedShape = 'rectangle';
                    }
                } else if ((points.length >= 360) && (points.length <= 362))  {
                    expectedShape = 'circle';
                }
            
                switch (expectedShape) {
                    case 'unknown':
                        length = this.calcMultiPointDistance(points,unit);
                        break;
                    case 'rectangle' : 
                        var rec_length = this.calcMultiPointDistance([points[0],points[1]],unit);
                        var rec_breath = this.calcMultiPointDistance([points[1],points[2]],unit);
                        length = (rec_length + rec_breath)* 2;
                        area = rec_length * rec_breath ;
                        break;
                    case 'circle' :
                        radius = (this.calcMultiPointDistance([points[90],points[270]],unit))/2;
                        area = Math.PI* radius * radius;
                        length = Math.PI* radius * 2;
                        break;
                    default: break;
                }
            }
            return ({length : length, area : area, radius : radius});
        }
});

if (typeof(Sys) !== "undefined") { Sys.Application.notifyScriptLoaded(); }
