// 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.

/// 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 _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 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 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 UnsupportedError('unicode escapes');
        } else if (codeUnit == QUOTE ||
            codeUnit == SLASH ||
            codeUnit == BACKSLASH) {
          // Ok.
        } else {
          _fail();
        }
      }
      charCodes.add(codeUnit);
      position++;
    }
    if (codeUnit != QUOTE) {
      _fail();
    }
    position++;
    return 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 UnsupportedError('_decodeNumber');
  }

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