// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

part of dart.convert;

/**
 * Error thrown by JSON serialization if an object cannot be serialized.
 *
 * The [unsupportedObject] field holds that object that failed to be serialized.
 *
 * If an object isn't directly serializable, the serializer calls the 'toJson'
 * method on the object. If that call fails, the error will be stored in the
 * [cause] field. If the call returns an object that isn't directly
 * serializable, the [cause] is be null.
 */
class JsonUnsupportedObjectError extends Error {
  /** The object that could not be serialized. */
  final unsupportedObject;
  /** The exception thrown when trying to convert the object. */
  final cause;

  JsonUnsupportedObjectError(this.unsupportedObject, { this.cause });

  String toString() {
    if (cause != null) {
      return "Converting object to an encodable object failed.";
    } else {
      return "Converting object did not return an encodable object.";
    }
  }
}


/**
 * Reports that an object could not be stringified due to cyclic references.
 *
 * An object that references itself cannot be serialized by [stringify].
 * When the cycle is detected, a [JsonCyclicError] is thrown.
 */
class JsonCyclicError extends JsonUnsupportedObjectError {
  /** The first object that was detected as part of a cycle. */
  JsonCyclicError(Object object): super(object);
  String toString() => "Cyclic error in JSON stringify";
}


/**
 * An instance of the default implementation of the [JsonCodec].
 *
 * This instance provides a convenient access to the most common JSON
 * use cases.
 *
 * Examples:
 *
 *     var encoded = JSON.encode([1, 2, { "a": null }]);
 *     var decoded = JSON.decode('["foo", { "bar": 499 }]');
 */
const JsonCodec JSON = const JsonCodec();

typedef _Reviver(var key, var value);
typedef _ToEncodable(var o);


/**
 * A [JsonCodec] encodes JSON objects to strings and decodes strings to
 * JSON objects.
 */
class JsonCodec extends Codec<Object, String> {
  final _Reviver _reviver;
  final _ToEncodable _toEncodable;

  /**
   * Creates a `JsonCodec` with the given reviver and encoding function.
   *
   * The [reviver] function is called during decoding. It is invoked
   * once for each object or list property that has been parsed.
   * The `key` argument is either the
   * integer list index for a list property, the string map key for object
   * properties, or `null` for the final result.
   *
   * If [reviver] is omitted, it defaults to returning the value argument.
   *
   * The [toEncodable] function is used during encoding. It is invoked for
   * values that are not directly encodable to a JSON1toE
   * string (a value that is not a number, boolean, string, null, list or a map
   * with string keys). The function must return an object that is directly
   * encodable. The elements of a returned list and values of a returned map
   * do not need be directly encodable, and if they aren't, `toEncodable` will
   * be used on them as well.
   * Please notice that it is possible to cause an infinite recursive
   * regress in this way, by effectively creating an infinite data structure
   * through repeated call to `toEncodable`.
   *
   * If [toEncodable] is omitted, it defaults to a function that returns the
   * result of calling `.toJson()` on the unencodable object.
   */
  const JsonCodec({reviver(var key, var value), toEncodable(var object)})
      : _reviver = reviver,
        _toEncodable = toEncodable;

  /**
   * Creates a `JsonCodec` with the given reviver.
   *
   * The [reviver] function is called once for each object or list property
   * that has been parsed during decoding. The `key` argument is either the
   * integer list index for a list property, the string map key for object
   * properties, or `null` for the final result.
   */
  JsonCodec.withReviver(reviver(var key, var value)) : this(reviver: reviver);

  /**
   * Parses the string and returns the resulting Json object.
   *
   * The optional [reviver] function is called once for each object or list
   * property that has been parsed during decoding. The `key` argument is either
   * the integer list index for a list property, the string map key for object
   * properties, or `null` for the final result.
   *
   * The default [reviver] (when not provided) is the identity function.
   */
  dynamic decode(String source, {reviver(var key, var value)}) {
    if (reviver == null) reviver = _reviver;
    if (reviver == null) return decoder.convert(source);
    return new JsonDecoder(reviver).convert(source);
  }

  /**
   * Converts [value] to a JSON string.
   *
   * If value contains objects that are not directly encodable to a JSON
   * string (a value that is not a number, boolean, string, null, list or a map
   * with string keys), the [toEncodable] function is used to convert it to an
   * object that must be directly encodable.
   *
   * If [toEncodable] is omitted, it defaults to a function that returns the
   * result of calling `.toJson()` on the unencodable object.
   */
  String encode(Object value, {toEncodable(var object)}) {
    if (toEncodable == null) toEncodable = _toEncodable;
    if (toEncodable == null) return encoder.convert(value);
    return new JsonEncoder(toEncodable).convert(value);
  }

  JsonEncoder get encoder {
    if (_toEncodable == null) return const JsonEncoder();
    return new JsonEncoder(_toEncodable);
  }

  JsonDecoder get decoder {
    if (_reviver == null) return const JsonDecoder();
    return new JsonDecoder(_reviver);
  }
}

/**
 * This class converts JSON objects to strings.
 */
class JsonEncoder extends Converter<Object, String> {
  /**
   * The string used for indention.
   *
   * When generating multi-line output, this string is inserted once at the
   * beginning of each indented line for each level of indentation.
   *
   * If `null`, the output is encoded as a single line.
   */
  final String indent;

  final _toEncodableFunction;

  /**
   * Creates a JSON encoder.
   *
   * The JSON encoder handles numbers, strings, booleans, null, lists and
   * maps directly.
   *
   * Any other object is attempted converted by [toEncodable] to an
   * object that is of one of the convertible types.
   *
   * If [toEncodable] is omitted, it defaults to calling `.toJson()` on
   * the object.
   */
  const JsonEncoder([Object toEncodable(Object nonSerializable)])
      : this.indent = null,
        this._toEncodableFunction = toEncodable;

  /**
   * Creates a JSON encoder that creates multi-line JSON.
   *
   * The encoding of elements of lists and maps are indented and put on separate
   * lines. The [indent] string is prepended to these elements, once for each
   * level of indentation.
   *
   * If [indent] is `null`, the output is encoded as a single line.
   *
   * The JSON encoder handles numbers, strings, booleans, null, lists and
   * maps directly.
   *
   * Any other object is attempted converted by [toEncodable] to an
   * object that is of one of the convertible types.
   *
   * If [toEncodable] is omitted, it defaults to calling `.toJson()` on
   * the object.
   */
  const JsonEncoder.withIndent(this.indent,
      [Object toEncodable(Object nonSerializable)])
      : this._toEncodableFunction = toEncodable;

  /**
   * Converts [object] to a JSON [String].
   *
   * Directly serializable values are [num], [String], [bool], and [Null], as
   * well as some [List] and [Map] values.
   * For [List], the elements must all be serializable.
   * For [Map], the keys must be [String] and the values must be serializable.
   *
   * If a value is any other type is attempted serialized, the conversion
   * function provided in the constructor is invoked with the object as argument
   * and the result, which must be a directly serializable value,
   * is serialized instead of the original value.
   *
   * If the conversion throws, or returns a value that is not directly
   * serializable, a [JsonUnsupportedObjectError] exception is thrown.
   * If the call throws, the error is caught and stored in the
   * [JsonUnsupportedObjectError]'s [:cause:] field.
   *
   * If a [List] or [Map] contains a reference to itself, directly or through
   * other lists or maps, it cannot be serialized and a [JsonCyclicError] is
   * thrown.
   *
   * [object] should not change during serialization.
   *
   * If an object is serialized more than once, [convert] may cache the text
   * for it. In other words, if the content of an object changes after it is
   * first serialized, the new values may not be reflected in the result.
   */
  String convert(Object object) =>
      _JsonStringifier.stringify(object, _toEncodableFunction, indent);

  /**
   * Starts a chunked conversion.
   *
   * The converter works more efficiently if the given [sink] is a
   * [StringConversionSink].
   *
   * Returns a chunked-conversion sink that accepts at most one object. It is
   * an error to invoke `add` more than once on the returned sink.
   */
  ChunkedConversionSink<Object> startChunkedConversion(Sink<String> sink) {
    if (sink is! StringConversionSink) {
      sink = new StringConversionSink.from(sink);
    }
    return new _JsonEncoderSink(sink, _toEncodableFunction, indent);
  }

  // Override the base-classes bind, to provide a better type.
  Stream<String> bind(Stream<Object> stream) => super.bind(stream);
}

/**
 * Implements the chunked conversion from object to its JSON representation.
 *
 * The sink only accepts one value, but will produce output in a chunked way.
 */
class _JsonEncoderSink extends ChunkedConversionSink<Object> {
  final String _indent;
  final Function _toEncodableFunction;
  final StringConversionSink _sink;
  bool _isDone = false;

  _JsonEncoderSink(this._sink, this._toEncodableFunction, this._indent);

  /**
   * Encodes the given object [o].
   *
   * It is an error to invoke this method more than once on any instance. While
   * this makes the input effectly non-chunked the output will be generated in
   * a chunked way.
   */
  void add(Object o) {
    if (_isDone) {
      throw new StateError("Only one call to add allowed");
    }
    _isDone = true;
    ClosableStringSink stringSink = _sink.asStringSink();
    _JsonStringifier.printOn(o, stringSink, _toEncodableFunction, _indent);
    stringSink.close();
  }

  void close() { /* do nothing */ }
}

/**
 * This class parses JSON strings and builds the corresponding objects.
 */
class JsonDecoder extends Converter<String, Object> {
  final _Reviver _reviver;
  /**
   * Constructs a new JsonDecoder.
   *
   * The [reviver] may be `null`.
   */
  const JsonDecoder([reviver(var key, var value)]) : this._reviver = reviver;

  /**
   * Converts the given JSON-string [input] to its corresponding object.
   *
   * Parsed JSON values are of the types [num], [String], [bool], [Null],
   * [List]s of parsed JSON values or [Map]s from [String] to parsed
   * JSON values.
   *
   * If `this` was initialized with a reviver, then the parsing operation
   * invokes the reviver on every object or list property that has been parsed.
   * The arguments are the property name ([String]) or list index ([int]), and
   * the value is the parsed value. The return value of the reviver is used as
   * the value of that property instead the parsed value.
   *
   * Throws [FormatException] if the input is not valid JSON text.
   */
  dynamic convert(String input) => _parseJson(input, _reviver);

  /**
   * Starts a conversion from a chunked JSON string to its corresponding
   * object.
   *
   * The output [sink] receives exactly one decoded element through `add`.
   */
  external StringConversionSink startChunkedConversion(Sink<Object> sink);

  // Override the base-classes bind, to provide a better type.
  Stream<Object> bind(Stream<String> stream) => super.bind(stream);
}

// Internal optimized JSON parsing implementation.
external _parseJson(String source, reviver(key, value));


// Implementation of encoder/stringifier.

Object _defaultToEncodable(object) => object.toJson();

class _JsonStringifier {
  // Character code constants.
  static const int BACKSPACE       = 0x08;
  static const int TAB             = 0x09;
  static const int NEWLINE         = 0x0a;
  static const int CARRIAGE_RETURN = 0x0d;
  static const int FORM_FEED       = 0x0c;
  static const int QUOTE           = 0x22;
  static const int CHAR_0          = 0x30;
  static const int BACKSLASH       = 0x5c;
  static const int CHAR_b          = 0x62;
  static const int CHAR_f          = 0x66;
  static const int CHAR_n          = 0x6e;
  static const int CHAR_r          = 0x72;
  static const int CHAR_t          = 0x74;
  static const int CHAR_u          = 0x75;

  final Function _toEncodable;
  final StringSink _sink;
  final List _seen;

  factory _JsonStringifier(StringSink sink, Function toEncodable,
      String indent) {
    if (indent == null) return new _JsonStringifier._(sink, toEncodable);
    return new _JsonStringifierPretty(sink, toEncodable, indent);
  }

  _JsonStringifier._(this._sink, this._toEncodable)
      : this._seen = new List();

  static String stringify(object, toEncodable(object), String indent) {
    if (toEncodable == null) toEncodable = _defaultToEncodable;
    StringBuffer output = new StringBuffer();
    printOn(object, output, toEncodable, indent);
    return output.toString();
  }

  static void printOn(object, StringSink output, toEncodable(object),
      String indent) {
    new _JsonStringifier(output, toEncodable, indent).stringifyValue(object);
  }

  static String numberToString(num x) {
    return x.toString();
  }

  // ('0' + x) or ('a' + x - 10)
  static int hexDigit(int x) => x < 10 ? 48 + x : 87 + x;

  void escape(String s) {
    int offset = 0;
    final int length = s.length;
    for (int i = 0; i < length; i++) {
      int charCode = s.codeUnitAt(i);
      if (charCode > BACKSLASH) continue;
      if (charCode < 32) {
        if (i > offset) _sink.write(s.substring(offset, i));
        offset = i + 1;
        _sink.writeCharCode(BACKSLASH);
        switch (charCode) {
        case BACKSPACE:
          _sink.writeCharCode(CHAR_b);
          break;
        case TAB:
          _sink.writeCharCode(CHAR_t);
          break;
        case NEWLINE:
          _sink.writeCharCode(CHAR_n);
          break;
        case FORM_FEED:
          _sink.writeCharCode(CHAR_f);
          break;
        case CARRIAGE_RETURN:
          _sink.writeCharCode(CHAR_r);
          break;
        default:
          _sink.writeCharCode(CHAR_u);
          _sink.writeCharCode(CHAR_0);
          _sink.writeCharCode(CHAR_0);
          _sink.writeCharCode(hexDigit((charCode >> 4) & 0xf));
          _sink.writeCharCode(hexDigit(charCode & 0xf));
          break;
        }
      } else if (charCode == QUOTE || charCode == BACKSLASH) {
        if (i > offset) _sink.write(s.substring(offset, i));
        offset = i + 1;
        _sink.writeCharCode(BACKSLASH);
        _sink.writeCharCode(charCode);
      }
    }
    if (offset == 0) {
      _sink.write(s);
    } else if (offset < length) {
      _sink.write(s.substring(offset, length));
    }
  }

  void checkCycle(object) {
    for (int i = 0; i < _seen.length; i++) {
      if (identical(object, _seen[i])) {
        throw new JsonCyclicError(object);
      }
    }
    _seen.add(object);
  }

  void stringifyValue(object) {
    // Tries stringifying object directly. If it's not a simple value, List or
    // Map, call toJson() to get a custom representation and try serializing
    // that.
    if (!stringifyJsonValue(object)) {
      checkCycle(object);
      try {
        var customJson = _toEncodable(object);
        if (!stringifyJsonValue(customJson)) {
          throw new JsonUnsupportedObjectError(object);
        }
        _removeSeen(object);
      } catch (e) {
        throw new JsonUnsupportedObjectError(object, cause: e);
      }
    }
  }

  /**
   * Serializes a [num], [String], [bool], [Null], [List] or [Map] value.
   *
   * Returns true if the value is one of these types, and false if not.
   * If a value is both a [List] and a [Map], it's serialized as a [List].
   */
  bool stringifyJsonValue(object) {
    if (object is num) {
      if (!object.isFinite) return false;
      _sink.write(numberToString(object));
      return true;
    } else if (identical(object, true)) {
      _sink.write('true');
      return true;
    } else if (identical(object, false)) {
      _sink.write('false');
       return true;
    } else if (object == null) {
      _sink.write('null');
      return true;
    } else if (object is String) {
      _sink.write('"');
      escape(object);
      _sink.write('"');
      return true;
    } else if (object is List) {
      checkCycle(object);
      List a = object;
      _sink.write('[');
      if (a.length > 0) {
        stringifyValue(a[0]);
        for (int i = 1; i < a.length; i++) {
          _sink.write(',');
          stringifyValue(a[i]);
        }
      }
      _sink.write(']');
      _removeSeen(object);
      return true;
    } else if (object is Map) {
      checkCycle(object);
      Map<String, Object> m = object;
      _sink.write('{');
      String separator = '"';
      m.forEach((String key, value) {
        _sink.write(separator);
        separator = ',"';
        escape(key);
        _sink.write('":');
        stringifyValue(value);
      });
      _sink.write('}');
      _removeSeen(object);
      return true;
    } else {
      return false;
    }
  }

  void _removeSeen(object) {
    assert(!_seen.isEmpty);
    assert(identical(_seen.last, object));
    _seen.removeLast();
  }
}

/**
 * A subclass of [_JsonStringifier] which indents the contents of [List] and
 * [Map] objects using the specified indent value.
 */
class _JsonStringifierPretty extends _JsonStringifier {
  final String _indent;

  int _indentLevel = 0;

  _JsonStringifierPretty(_sink, _toEncodable, this._indent)
      : super._(_sink, _toEncodable);

  void _write([String value = '']) {
    _sink.write(_indent * _indentLevel);
    _sink.write(value);
  }

  /**
   * Serializes a [num], [String], [bool], [Null], [List] or [Map] value.
   *
   * Returns true if the value is one of these types, and false if not.
   * If a value is both a [List] and a [Map], it's serialized as a [List].
   */
  bool stringifyJsonValue(final object) {
    if (object is List) {
      checkCycle(object);
      List a = object;
      if (a.isEmpty) {
        _sink.write('[]');
      } else {
        _sink.writeln('[');
        _indentLevel++;
        _write();
        stringifyValue(a[0]);
        for (int i = 1; i < a.length; i++) {
          _sink.writeln(',');
          _write();
          stringifyValue(a[i]);
        }
        _sink.writeln();
        _indentLevel--;
        _write(']');
      }
      _seen.remove(object);
      return true;
    } else if (object is Map) {
      checkCycle(object);
      Map<String, Object> m = object;
      if (m.isEmpty) {
        _sink.write('{}');
      } else {
        _sink.write('{');
        _sink.writeln();
        _indentLevel++;
        bool first = true;
        m.forEach((String key, Object value) {
          if (!first) {
            _sink.writeln(',');
          }
          _write('"');
          escape(key);
          _sink.write('": ');
          stringifyValue(value);
          first = false;
        });
        _sink.writeln();
        _indentLevel--;
        _write('}');
      }
      _seen.remove(object);
      return true;
    }
    return super.stringifyJsonValue(object);
  }
}
