﻿function StringBuffer() {
   this.buffer = [];
}

StringBuffer.prototype.append = function append(string) {
   this.buffer.push(string);
   //return this;
};

StringBuffer.prototype.toString = function toString() {
   return this.buffer.join("");
};

var Utility = {
   /// <summary>
   ///   static Utility class
   /// </summary>

   OnFailed: function(error) {
      /// <summary>
      ///     This is the failed callback function for all webservices.
      /// </summary>  
      /// <param name="error">The error object from the webservice</param>          

      var stackTrace = error.get_stackTrace();
      var message = error.get_message();
      var statusCode = error.get_statusCode();
      var exceptionType = error.get_exceptionType();
      var timedout = error.get_timedOut();

      // Display the error.    
      var RsltElem =
            "Stack Trace: " + stackTrace + "<br/>" +
            "Service Error: " + message + "<br/>" +
            "Status Code: " + statusCode + "<br/>" +
            "Exception Type: " + exceptionType + "<br/>" +
            "Timedout: " + timedout;

      alert(RsltElem);
   },

   decodeLine: function(encoded) {
      /// <summary>
      ///     Decode an encoded string into a list of VE lat/lng.
      /// </summary>  
      /// <param name="encoded">The encoded string</param>       
      /// <returns>Array of VELatLong</returns>

      var len = encoded.length;
      var index = 0;
      var array = [];
      var lat = 0;
      var lng = 0;
      try {
         while (index < len) {
            var b;
            var shift = 0;
            var result = 0;
            do {
               b = encoded.charCodeAt(index++) - 63;
               result |= (b & 0x1f) << shift;
               shift += 5;
            } while (b >= 0x20);
            var dlat = ((result & 1) ? ~(result >> 1) : (result >> 1));
            lat += dlat;

            shift = 0;
            result = 0;
            do {
               b = encoded.charCodeAt(index++) - 63;
               result |= (b & 0x1f) << shift;
               shift += 5;
            } while (b >= 0x20);
            var dlng = ((result & 1) ? ~(result >> 1) : (result >> 1));
            lng += dlng;

            array.push(new VELatLong((lat * 1e-5), (lng * 1e-5)));
         }
      } catch (ex) {
         //error in encoding.
      }
      return array;
   },

   decodeBase64: function(input) {

      var output = new StringBuffer();
      var chr1, chr2, chr3;
      var enc1, enc2, enc3, enc4;
      var i = 0;

      input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

      while (i < input.length) {

         enc1 = this._keyStr.indexOf(input.charAt(i++));
         enc2 = this._keyStr.indexOf(input.charAt(i++));
         enc3 = this._keyStr.indexOf(input.charAt(i++));
         enc4 = this._keyStr.indexOf(input.charAt(i++));

         chr1 = (enc1 << 2) | (enc2 >> 4);
         chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
         chr3 = ((enc3 & 3) << 6) | enc4;

         output.append(String.fromCharCode(chr1));

         if (enc3 != 64) {
            output.append(String.fromCharCode(chr2));
         }
         if (enc4 != 64) {
            output.append(String.fromCharCode(chr3));
         }

      }

      var str_output = this._utf8_decode(output.toString());

      return str_output;

   },

   createEncodings: function(points) {
      /// <summary>
      ///     Create the encoded bounds.
      /// </summary>  
      /// <param name="points">Array of VELatLong</param>       
      /// <returns>The encoded string</returns>    
      var i = 0;
      var plat = 0;
      var plng = 0;
      var encoded_points = "";

      for (i = 0; i < points.length; ++i) {
         var point = points[i];
         var lat = point.Latitude;
         var lng = point.Longitude;

         var late5 = Math.floor(lat * 1e5);
         var lnge5 = Math.floor(lng * 1e5);

         dlat = late5 - plat;
         dlng = lnge5 - plng;

         plat = late5;
         plng = lnge5;

         encoded_points += this._encodeSignedNumber(dlat) + this._encodeSignedNumber(dlng);
      }
      return encoded_points;
   },

   _encodeSignedNumber: function(num) {
      /// <summary>
      ///     Encode a signed number in the encode format.
      /// </summary>  
      /// <param name="num">signed number</param>       
      /// <returns>encoded string</returns>       
      var sgn_num = num << 1;

      if (num < 0) {
         sgn_num = ~(sgn_num);
      }

      return (this._encodeNumber(sgn_num));
   },

   _encodeNumber: function(num) {
      /// <summary>
      ///     Encode an unsigned number in the encode format.
      /// </summary>  
      /// <param name="num">unsigned number</param>       
      /// <returns>encoded string</returns>        
      var encodeString = "";

      while (num >= 0x20) {
         encodeString += (String.fromCharCode((0x20 | (num & 0x1f)) + 63));
         num >>= 5;
      }

      encodeString += (String.fromCharCode(num + 63));
      return encodeString;
   },

   // private property
   _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",


   // private method for UTF-8 decoding
   _utf8_decode: function(utftext) {
      var output = new StringBuffer();
      
      var i = 0;
      var c = c1 = c2 = 0;

      while (i < utftext.length) {

         c = utftext.charCodeAt(i);

         if (c < 128) {
            output.append(String.fromCharCode(c));
            i++;
         }
         else if ((c > 191) && (c < 224)) {
            c2 = utftext.charCodeAt(i + 1);
            output.append(String.fromCharCode(((c & 31) << 6) | (c2 & 63)));
            i += 2;
         }
         else {
            c2 = utftext.charCodeAt(i + 1);
            c3 = utftext.charCodeAt(i + 2);
            output.append(String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)));
            i += 3;
         }

      }

      return output.toString();
   }

}

if (typeof(Sys) !== "undefined") Sys.Application.notifyScriptLoaded();

