text: /* Copyright© 2000 - 2021 SuperMap Software Co.Ltd. All rights reserved.
   * This program are made available under the terms of the Apache License, Version 2.0
   * which accompanies this distribution and is available at http://www.apache.org/licenses/LICENSE-2.0.html.*/
  import {
      SuperMap
  } from '../SuperMap';
  import {
      Format
  } from './Format';
  
  /**
   * @class SuperMap.Format.JSON
   * @classdesc 安全的读写 JSON 的解析类。使用 {@link SuperMap.Format.JSON} 构造函数创建新实例。
   * @category BaseTypes Format
   * @param {Object} [options] - 参数。
   * @param {string} [options.indent="    "] - 用于格式化输出，indent 字符串会在每次缩进的时候使用一次。
   * @param {string} [options.space=" "] - 用于格式化输出，space 字符串会在名值对的 ":" 后边添加。
   * @param {string} [options.newline="\n"] - 用于格式化输出, newline 字符串会用在每一个名值对或数组项末尾。
   * @param {number} [options.level=0] - 用于格式化输出, 表示的是缩进级别。
   * @param {boolean} [options.pretty=false] - 是否在序列化的时候使用额外的空格控制结构。在 write 方法中使用。
   * @param {boolean} [options.nativeJSON] - 需要被注册的监听器对象。
   * @extends {SuperMap.Format}
   */
  export class JSONFormat extends Format {
  
      constructor(options) {
          super(options);
          /**
           * @member {string} [SuperMap.Format.JSON.prototype.indent="    "]
           * @description 用于格式化输出，indent 字符串会在每次缩进的时候使用一次。
           */
          this.indent = "    ";
  
          /**
           * @member {string} [SuperMap.Format.JSON.prototype.space=" "]
           * @description 用于格式化输出，space 字符串会在名值对的 ":" 后边添加。
           */
          this.space = " ";
  
          /**
           * @member {string} [SuperMap.Format.JSON.prototype.newline="\n"]
           * @description 用于格式化输出, newline 字符串会用在每一个名值对或数组项末尾。
           */
          this.newline = "\n";
  
          /**
           * @member {integer} [SuperMap.Format.JSON.prototype.level=0] 
           * @description 用于格式化输出, 表示的是缩进级别。
           */
          this.level = 0;
  
          /**
           * @member {boolean} [SuperMap.Format.JSON.prototype.pretty=false]
           * @description 是否在序列化的时候使用额外的空格控制结构。在 write 方法中使用。
           */
          this.pretty = false;
  
          /**
           * @member {boolean} SuperMap.Format.JSON.prototype.nativeJSON 
           * @description 判断浏览器是否原生支持 JSON 格式数据。
           */
          this.nativeJSON = (function () {
              return !!(window.JSON && typeof JSON.parse === "function" && typeof JSON.stringify === "function");
          })();
  
          this.CLASS_NAME = "SuperMap.Format.JSON";
          /**
           * @member SuperMap.Format.JSON.prototype.serialize
           * @description 提供一些类型对象转 JSON 字符串的方法。
           */
          this.serialize = {
              /**
               * @function SuperMap.Format.JSON.serialize.object
               * @description 把对象转换为 JSON 字符串。
               * @param {Object} object - 可序列化的对象。
               * @returns {string} JSON 字符串。
               */
              'object': function (object) {
                  // three special objects that we want to treat differently
                  if (object == null) {
                      return "null";
                  }
                  if (object.constructor === Date) {
                      return this.serialize.date.apply(this, [object]);
                  }
                  if (object.constructor === Array) {
                      return this.serialize.array.apply(this, [object]);
                  }
                  var pieces = ['{'];
                  this.level += 1;
                  var key, keyJSON, valueJSON;
  
                  var addComma = false;
                  for (key in object) {
                      if (object.hasOwnProperty(key)) {
                          // recursive calls need to allow for sub-classing
                          keyJSON = this.write.apply(this,
                              [key, this.pretty]);
                          valueJSON = this.write.apply(this,
                              [object[key], this.pretty]);
                          if (keyJSON != null && valueJSON != null) {
                              if (addComma) {
                                  pieces.push(',');
                              }
                              pieces.push(this.writeNewline(), this.writeIndent(),
                                  keyJSON, ':', this.writeSpace(), valueJSON);
                              addComma = true;
                          }
                      }
                  }
  
                  this.level -= 1;
                  pieces.push(this.writeNewline(), this.writeIndent(), '}');
                  return pieces.join('');
              },
  
              /**
               * @function SuperMap.Format.JSON.serialize.array
               * @description 把数组转换成 JSON 字符串。
               * @param {Array} array - 可序列化的数组。
               * @returns {string} JSON 字符串。
               */
              'array': function (array) {
                  var json;
                  var pieces = ['['];
                  this.level += 1;
  
                  for (var i = 0, len = array.length; i < len; ++i) {
                      // recursive calls need to allow for sub-classing
                      json = this.write.apply(this,
                          [array[i], this.pretty]);
                      if (json != null) {
                          if (i > 0) {
                              pieces.push(',');
                          }
                          pieces.push(this.writeNewline(), this.writeIndent(), json);
                      }
                  }
  
                  this.level -= 1;
                  pieces.push(this.writeNewline(), this.writeIndent(), ']');
                  return pieces.join('');
              },
  
              /**
               * @function SuperMap.Format.JSON.serialize.string
               * @description 把字符串转换成 JSON 字符串。
               * @param {string} string - 可序列化的字符串。
               * @returns {string} JSON 字符串。
               */
              'string': function (string) {
                  // If the string contains no control characters, no quote characters, and no
                  // backslash characters, then we can simply slap some quotes around it.
                  // Otherwise we must also replace the offending characters with safe
                  // sequences.
                  var m = {
                      '\b': '\\b',
                      '\t': '\\t',
                      '\n': '\\n',
                      '\f': '\\f',
                      '\r': '\\r',
                      '"': '\\"',
                      '\\': '\\\\'
                  };
                  /*eslint-disable no-control-regex*/
                  if (/["\\\x00-\x1f]/.test(string)) {
                      return '"' + string.replace(/([\x00-\x1f\\"])/g, function (a, b) {
                          var c = m[b];
                          if (c) {
                              return c;
                          }
                          c = b.charCodeAt();
                          return '\\u00' +
                              Math.floor(c / 16).toString(16) +
                              (c % 16).toString(16);
                      }) + '"';
                  }
                  return '"' + string + '"';
              },
  
              /**
               * @function SuperMap.Format.JSON.serialize.number
               * @description 把数字转换成 JSON 字符串。
               * @param {number} number - 可序列化的数字。
               * @returns {string} JSON 字符串。
               */
              'number': function (number) {
                  return isFinite(number) ? String(number) : "null";
              },
  
              /**
               * @function SuperMap.Format.JSON.serialize.boolean
               * @description Transform a boolean into a JSON string.
               * @param {boolean} bool - The boolean to be serialized.
               * @returns {string} A JSON string representing the boolean.
               */
              'boolean': function (bool) {
                  return String(bool);
              },
  
              /**
               * @function SuperMap.Format.JSON.serialize.object
               * @description 将日期对象转换成 JSON 字符串。
               * @param {Date} date - 可序列化的日期对象。
               * @returns {string} JSON 字符串。
               */
              'date': function (date) {
                  function format(number) {
                      // Format integers to have at least two digits.
                      return (number < 10) ? '0' + number : number;
                  }
  
                  return '"' + date.getFullYear() + '-' +
                      format(date.getMonth() + 1) + '-' +
                      format(date.getDate()) + 'T' +
                      format(date.getHours()) + ':' +
                      format(date.getMinutes()) + ':' +
                      format(date.getSeconds()) + '"';
              }
          };
      }
  
      /**
       * @function SuperMap.Format.JSON.prototype.read
       * @description 将一个符合 JSON 结构的字符串进行解析。
       * @param {string} json - 符合 JSON 结构的字符串。
       * @param {function} filter - 过滤方法，最终结果的每一个键值对都会调用该过滤方法，并在对应的值的位置替换成该方法返回的值。
       * @returns {Object} 对象，数组，字符串或数字。
       */
      read(json, filter) {
          var object;
          if (this.nativeJSON) {
              try {
                  object = JSON.parse(json, filter);
              } catch (e) {
                  // Fall through if the regexp test fails.
              }
          }
  
          if (this.keepData) {
              this.data = object;
          }
  
          return object;
      }
  
      /**
       * @function SuperMap.Format.JSON.prototype.write
       * @description 序列化一个对象到一个符合 JSON 格式的字符串。
       * @param {(object|string|Array|number|boolean)} value - 需要被序列化的对象，数组，字符串，数字，布尔值。
       * @param {boolean} [pretty=false] - 是否在序列化的时候使用额外的空格控制结构。在 write 方法中使用。
       * @returns {string} 符合 JSON 格式的字符串。
       *
       */
      write(value, pretty) {
          this.pretty = !!pretty;
          var json = null;
          var type = typeof value;
          if (this.serialize[type]) {
              try {
                  json = (!this.pretty && this.nativeJSON) ?
                      JSON.stringify(value) :
                      this.serialize[type].apply(this, [value]);
              } catch (err) {
                  //SuperMap.Console.error("Trouble serializing: " + err);
              }
          }
          return json;
      }
  
      /**
       * @function SuperMap.Format.JSON.prototype.writeIndent
       * @description 根据缩进级别输出一个缩进字符串。
       * @private
       * @returns {string} 一个适当的缩进字符串。
       */
      writeIndent() {
          var pieces = [];
          if (this.pretty) {
              for (var i = 0; i < this.level; ++i) {
                  pieces.push(this.indent);
              }
          }
          return pieces.join('');
      }
  
      /**
       * @function SuperMap.Format.JSON.prototype.writeNewline
       * @description 在格式化输出模式情况下输出代表新一行的字符串。
       * @private
       * @returns {string} 代表新的一行的字符串。
       */
      writeNewline() {
          return (this.pretty) ? this.newline : '';
      }
  
      /**
       * @function SuperMap.Format.JSON.prototype.writeSpace
       * @private
       * @description 在格式化输出模式情况下输出一个代表空格的字符串。
       * @returns {string} 一个空格。
       */
      writeSpace() {
          return (this.pretty) ? this.space : '';
      }
  
  }
  
  SuperMap.Format.JSON = JSONFormat;