// Copyright (c) 2016, 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.

// @dart = 2.7

/// Decode a lax JSON encoded text, that is, JSON with Dart-like comments and
/// trailing commas.
///
/// This is used together with `load.dart` and `save.dart` to allow for an easy
/// editing of a human-readable source-map file.

library lazon;

decode(String text) {
  return new _Decoder(text)._decode();
}

class _Decoder {
  static final int LF = '\n'.codeUnits.single;
  static final int CR = '\r'.codeUnits.single;
  static final int BACKSPACE = '\b'.codeUnits.single;
  static final int FORMFEED = '\f'.codeUnits.single;
  static final int TAB = '\t'.codeUnits.single;
  static final int SPACE = ' '.codeUnits.single;
  static final int SLASH = '/'.codeUnits.single;
  static final int STAR = '*'.codeUnits.single;
  static final int QUOTE = '"'.codeUnits.single;
  static final int BACKSLASH = '\\'.codeUnits.single;
  static final int COMMA = ','.codeUnits.single;
  static final int COLON = ':'.codeUnits.single;
  static final int LEFT_BRACE = '{'.codeUnits.single;
  static final int RIGHT_BRACE = '}'.codeUnits.single;
  static final int LEFT_BRACKET = '['.codeUnits.single;
  static final int RIGHT_BRACKET = ']'.codeUnits.single;
  static final int T = 't'.codeUnits.single;
  static final List<int> TRUE = 'true'.codeUnits;
  static final int F = 'f'.codeUnits.single;
  static final List<int> FALSE = 'false'.codeUnits;
  static final int N = 'n'.codeUnits.single;
  static final List<int> NULL = 'null'.codeUnits;
  static final int B = 'b'.codeUnits.single;
  static final int R = 'r'.codeUnits.single;
  static final int U = 'u'.codeUnits.single;

  final List<int> codeUnits;
  final int length;
  int position = 0;

  _Decoder(String text)
      : codeUnits = text.codeUnits,
        length = text.length;

  _decode() {
    var result = _decodeValue();
    _trimWhitespace();
    if (position != codeUnits.length) {
      throw new ArgumentError("Unexpected trailing text: "
          "'${new String.fromCharCodes(codeUnits, position)}'.");
    }
    return result;
  }

  _decodeValue() {
    var result;
    _trimWhitespace();
    if (position < codeUnits.length) {
      int codeUnit = codeUnits[position];
      if (codeUnit == QUOTE) {
        result = _decodeString();
      } else if (codeUnit == LEFT_BRACE) {
        result = _decodeMap();
      } else if (codeUnit == LEFT_BRACKET) {
        result = _decodeList();
      } else if (codeUnit == T) {
        result = _decodeTrue();
      } else if (codeUnit == F) {
        result = _decodeFalse();
      } else if (codeUnit == N) {
        result = _decodeNull();
      } else {
        result = _decodeNumber();
      }
    } else {
      throw new ArgumentError("No value found in text: "
          "'${new String.fromCharCodes(codeUnits, 0)}'.");
    }
    return result;
  }

  void _trimWhitespace() {
    OUTER:
    while (position < codeUnits.length) {
      int codeUnit = codeUnits[position];
      if (codeUnit == SLASH) {
        if (position + 1 < codeUnits.length) {
          int nextCodeUnit = codeUnits[position + 1];
          if (nextCodeUnit == SLASH) {
            position += 2;
            while (position < codeUnits.length) {
              codeUnit = codeUnits[position];
              if (codeUnit == LF || codeUnit == CR) {
                continue OUTER;
              }
              position++;
            }
          } else if (nextCodeUnit == STAR) {
            position += 2;
            while (position < codeUnits.length) {
              codeUnit = codeUnits[position];
              if (codeUnit == STAR &&
                  position + 1 < codeUnits.length &&
                  codeUnits[position + 1] == SLASH) {
                position += 2;
                continue OUTER;
              }
              position++;
            }
          }
        }
        break;
      } else if (codeUnit == LF ||
          codeUnit == CR ||
          codeUnit == TAB ||
          codeUnit == SPACE) {
        position++;
      } else {
        break;
      }
    }
  }

  String _decodeString() {
    int codeUnit = codeUnits[position];
    if (codeUnit != QUOTE) {
      _fail();
    }
    position++;
    List<int> charCodes = <int>[];
    while (position < length) {
      codeUnit = codeUnits[position];
      if (codeUnit == QUOTE) {
        break;
      } else if (codeUnit == BACKSLASH) {
        if (position + 1 >= length) {
          _fail();
        }
        codeUnit = codeUnits[++position];
        if (codeUnit == B) {
          codeUnit = BACKSPACE;
        } else if (codeUnit == F) {
          codeUnit = FORMFEED;
        } else if (codeUnit == N) {
          codeUnit = LF;
        } else if (codeUnit == R) {
          codeUnit = CR;
        } else if (codeUnit == T) {
          codeUnit = TAB;
        } else if (codeUnit == U) {
          throw new UnsupportedError('unicode escapes');
        } else if (codeUnit == QUOTE ||
            codeUnit == SLASH ||
            codeUnit == BACKSLASH) {
          // Ok.
        } else {
          _fail();
        }
      }
      charCodes.add(codeUnit);
      position++;
    }
    if (codeUnit != QUOTE) {
      _fail();
    }
    position++;
    return new String.fromCharCodes(charCodes);
  }

  Map _decodeMap() {
    int codeUnit = codeUnits[position];
    if (codeUnit != LEFT_BRACE) {
      _fail();
    }
    position++;
    _trimWhitespace();
    Map result = {};
    while (position < length) {
      codeUnit = codeUnits[position];
      if (codeUnit == RIGHT_BRACE) {
        break;
      }
      String key = _decodeString();
      _trimWhitespace();
      if (position < length) {
        codeUnit = codeUnits[position];
        if (codeUnit == COLON) {
          position++;
          _trimWhitespace();
        } else {
          _fail();
        }
      } else {
        _fail();
      }
      var value = _decodeValue();
      result[key] = value;
      _trimWhitespace();
      if (position < length) {
        codeUnit = codeUnits[position];
        if (codeUnit == COMMA) {
          position++;
          _trimWhitespace();
          continue;
        } else {
          break;
        }
      }
    }

    if (codeUnit != RIGHT_BRACE) {
      _fail();
    }
    position++;
    return result;
  }

  List _decodeList() {
    int codeUnit = codeUnits[position];
    if (codeUnit != LEFT_BRACKET) {
      _fail();
    }
    position++;
    _trimWhitespace();
    List result = [];
    while (position < length) {
      codeUnit = codeUnits[position];
      if (codeUnit == RIGHT_BRACKET) {
        break;
      }
      result.add(_decodeValue());
      _trimWhitespace();
      if (position < length) {
        codeUnit = codeUnits[position];
        if (codeUnit == COMMA) {
          position++;
          _trimWhitespace();
          continue;
        } else {
          break;
        }
      }
    }

    if (codeUnit != RIGHT_BRACKET) {
      _fail();
    }
    position++;
    return result;
  }

  bool _decodeTrue() {
    match(TRUE);
    return true;
  }

  bool _decodeFalse() {
    match(FALSE);
    return false;
  }

  Null _decodeNull() {
    match(NULL);
    return null;
  }

  void match(List<int> codes) {
    if (position + codes.length > length) {
      _fail();
    }
    for (int i = 0; i < codes.length; i++) {
      if (codes[i] != codeUnits[position + i]) {
        _fail();
      }
    }
    position += codes.length;
  }

  num _decodeNumber() {
    throw new UnsupportedError('_decodeNumber');
  }

  void _fail() {
    throw new ArgumentError("Unexpected value: "
        "'${new String.fromCharCodes(codeUnits, position)}'.");
  }
}
