// Copyright (c) 2021, 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 debug symbol information stored by DDC.
//
// The data format below stores descriptions of dart code objects and their
// mapping to JS that is generated by DDC. Every field, except ids, describes
// dart.
// Note that 'localId' and 'scopeId' combine into a unique id that is used for
// object lookup and mapping between JS and dart concepts. As a result, it
// needs to be either stored or easily computed for each corresponding JS object
// created by DDC, so the debugger is able to look up dart symbol from JS ones.
//
// For example, to detect all dart variables in current scope and display
// their values, the debugger can do the following:
//
// - map current JS location to dart location using source maps
// - find all nested dart scopes that include the current dart location
// - collect all dart variables in scope
// - look up corresponding variables and their values in JS scope by their
//   JS ids
// - display their values (non-expanded)
//
// To display a JS value of variable 'v' (non-expanded)
//
// - v: <dart type name> (jsvalue.toString())
//
// Where <dart type name> is the dart type of the dart variable 'v'
// at runtime.
//
// TODO: describe displaying specific non-expanded JS instances in dart
// way, for example, lists, maps, types - is JS toString() enough?
//
// To display a value (expanded)
//
// - look up the JS runtime type of the value
// - find the dart value's runtime type by JS id value's runtime type id
// - collect all dart fields of that type, including the inherited fields
// - map dart fields to JS field ids and look up their values using object
//   ids referenced by the original displayed value.
// - display their values (non-expanded)
class SemanticVersion {
  final int major;
  final int minor;
  final int patch;
  const SemanticVersion(
    this.major,
    this.minor,
    this.patch,
  );
  static SemanticVersion parse(String version) {
    var parts = version.split('.');
    if (parts.length != 3) {
      throw FormatException('Version: $version '
          'does not follow simple semantic versioning format');
    }
    var major = int.parse(parts[0]);
    var minor = int.parse(parts[1]);
    var patch = int.parse(parts[2]);
    return SemanticVersion(major, minor, patch);
  }

  /// Text version.
  String get version => '$major.$minor.$patch';

  /// True if this version is compatible with [version].
  ///
  /// The minor and patch version changes never remove any fields that current
  /// version supports, so the reader can create current metadata version from
  /// any file created with a later reader, as long as the major version does
  /// not change.
  bool isCompatibleWith(String version) {
    var other = parse(version);
    return other.major == major && other.minor >= minor && other.patch >= patch;
  }
}

abstract class SymbolTableElement {
  Map<String, dynamic> toJson();
}

class ModuleSymbols implements SymbolTableElement {
  /// Current symbol information version.
  ///
  /// Version follows simple semantic versioning format 'major.minor.patch'
  /// See https://semver.org
  static const SemanticVersion current = SemanticVersion(0, 0, 1);

  /// Semantic version of the format.
  final String version;

  /// Module name as used in the module metadata
  final String moduleName;

  /// All dart libraries included in the module.
  ///
  /// Note here and below that imported elements are not included in
  /// the current module but can be referenced by their ids.
  final List<LibrarySymbol> libraries;

  /// All dart scripts included in the module.
  final List<Script> scripts;

  /// All dart classes included in the module.
  final List<ClassSymbol> classes;

  /// All dart function types included in the module.
  final List<FunctionTypeSymbol> functionTypes;

  /// All dart function types included in the module.
  final List<FunctionSymbol> functions;

  /// All dart scopes included in the module.
  ///
  /// Does not include scopes listed in other fields,
  /// such as libraries, classes, and functions.
  final List<ScopeSymbol> scopes;

  /// All Dart variables included in the module.
  List<VariableSymbol> variables;

  ModuleSymbols({
    String? version,
    required this.moduleName,
    List<LibrarySymbol>? libraries,
    List<Script>? scripts,
    List<ClassSymbol>? classes,
    List<FunctionTypeSymbol>? functionTypes,
    List<FunctionSymbol>? functions,
    List<ScopeSymbol>? scopes,
    List<VariableSymbol>? variables,
  })  : version = version ??= current.version,
        libraries = libraries ?? [],
        scripts = scripts ?? [],
        classes = classes ?? [],
        functionTypes = functionTypes ?? [],
        functions = functions ?? [],
        scopes = scopes ?? [],
        variables = variables ?? [];

  ModuleSymbols.fromJson(Map<String, dynamic> json)
      : version = _readAndValidateVersionFromJson(json['version']),
        moduleName = _createValue(json['moduleName']),
        libraries =
            _createObjectList(json['libraries'], LibrarySymbol.fromJson),
        scripts = _createObjectList(json['scripts'], Script.fromJson),
        classes = _createObjectList(json['classes'], ClassSymbol.fromJson),
        functionTypes = _createObjectList(
            json['functionTypes'], FunctionTypeSymbol.fromJson),
        functions =
            _createObjectList(json['functions'], FunctionSymbol.fromJson),
        scopes = _createObjectList(json['scopes'], ScopeSymbol.fromJson),
        variables =
            _createObjectList(json['variables'], VariableSymbol.fromJson);

  @override
  Map<String, dynamic> toJson() {
    final json = <String, dynamic>{
      'version': version,
      'moduleName': moduleName,
    };
    _setObjectListIfNotNullOrEmpty(json, 'libraries', libraries);
    _setObjectListIfNotNullOrEmpty(json, 'scripts', scripts);
    _setObjectListIfNotNullOrEmpty(json, 'classes', classes);
    _setObjectListIfNotNullOrEmpty(json, 'functionTypes', functionTypes);
    _setObjectListIfNotNullOrEmpty(json, 'functions', functions);
    _setObjectListIfNotNullOrEmpty(json, 'scopes', scopes);
    _setObjectListIfNotNullOrEmpty(json, 'variables', variables);
    return json;
  }

  static String _readAndValidateVersionFromJson(dynamic json) {
    if (json == null) return current.version;
    var version = _createValue<String>(json);
    if (!current.isCompatibleWith(version)) {
      throw Exception('Unsupported version $version. '
          'Current version: ${current.version}');
    }
    return version;
  }
}

class Symbol implements SymbolTableElement {
  /// Local id (such as JS name) for the symbol.
  ///
  /// Used to map from Dart objects to JS objects inside a scope.
  final String localId;

  /// Enclosing scope of the symbol.
  final String? scopeId;

  /// Source location of the symbol.
  final SourceLocation? location;

  /// Unique Id, shared with JS representation (if any).
  ///
  /// `'<scope id>|<js name>'`
  ///
  /// Where scope refers to a Library, Class, Function, or Scope.
  String get id => scopeId == null ? localId : '$scopeId|$localId';

  Symbol({required this.localId, this.scopeId, this.location});

  Symbol.fromJson(Map<String, dynamic> json)
      : localId = _createValue(json['localId']),
        scopeId = _createValue(json['scopeId']),
        location =
            _createNullableObject(json['location'], SourceLocation.fromJson);

  @override
  Map<String, dynamic> toJson() {
    final json = <String, dynamic>{
      'localId': localId,
      if (scopeId != null) 'scopeId': scopeId,
    };
    _setObjectIfNotNull(json, 'location', location);
    return json;
  }
}

abstract class TypeSymbol {
  String get id;
}

enum VariableSymbolKind { global, local, property, field, formal, none }

VariableSymbolKind parseVariableSymbolKind(String value) {
  return VariableSymbolKind.values.singleWhere((e) => value == '$e',
      orElse: () {
    throw ArgumentError('$value is not VariableSymbolKind');
  });
}

class VariableSymbol extends Symbol {
  /// Name of the variable in Dart source code.
  final String name;

  /// Symbol kind.
  final VariableSymbolKind kind;

  /// The declared type of this symbol in Dart source code.
  // TODO(nshahan) Only nullable until we design how to identify types from
  // other modules.
  final String? typeId;

  /// True if this variable const.
  final bool isConst;

  /// True if this variable final.
  final bool isFinal;

  /// True if this variable static.
  final bool isStatic;

  /// Property getter, if any.
  final String? getterId;

  /// Property setter, if any.
  final String? setterId;

  VariableSymbol({
    required this.name,
    required this.kind,
    required this.typeId,
    bool? isConst,
    bool? isFinal,
    bool? isStatic,
    this.getterId,
    this.setterId,
    required super.localId,
    required String super.scopeId,
    required SourceLocation super.location,
  })  : isConst = isConst ?? false,
        isFinal = isFinal ?? false,
        isStatic = isStatic ?? false;

  VariableSymbol.fromJson(super.json)
      : name = _createValue(json['name']),
        kind = _createValue(json['kind'],
            parse: parseVariableSymbolKind, ifNull: VariableSymbolKind.none),
        typeId = _createValue(json['typeId']),
        isConst = _createValue(json['isConst']),
        isFinal = _createValue(json['isFinal']),
        isStatic = _createValue(json['isStatic']),
        getterId = _createValue(json['getterId']),
        setterId = _createValue(json['setterId']),
        super.fromJson();

  @override
  Map<String, dynamic> toJson() => {
        ...super.toJson(),
        'name': name,
        'kind': kind.toString(),
        if (typeId != null) 'typeId': typeId,
        'isConst': isConst,
        'isFinal': isFinal,
        'isStatic': isStatic,
        if (getterId != null) 'getterId': getterId,
        if (setterId != null) 'setterId': setterId,
      };
}

class ClassSymbol extends ScopeSymbol implements TypeSymbol {
  /// The name of this class in Dart source code.
  final String name;

  /// True if this class is abstract.
  final bool isAbstract;

  /// True if this class is const.
  final bool isConst;

  /// The superclass of this class, if any.
  final String? superClassId;

  /// A list of interface types for this class.
  final List<String> interfaceIds;

  /// Mapping of type parameter Dart names to JS names.
  final Map<String, String> typeParameters;

  /// Library that contains this class.
  String get libraryId => scopeId!;

  /// Fields in this class.
  ///
  /// Including static fields, methods, and properties.
  List<String> get fieldIds => variableIds;

  /// Functions in this class.
  ///
  /// Includes all static functions, methods, getters,
  /// and setters in the current class.
  ///
  /// Does not include functions from superclasses.
  List<String> get functionIds => scopeIds;

  ClassSymbol({
    required this.name,
    bool? isAbstract,
    bool? isConst,
    this.superClassId,
    List<String>? interfaceIds,
    Map<String, String>? typeParameters,
    required super.localId,
    required String super.scopeId,
    required SourceLocation super.location,
    super.variableIds,
    super.scopeIds,
  })  : isAbstract = isAbstract ?? false,
        isConst = isConst ?? false,
        interfaceIds = interfaceIds ?? [],
        typeParameters = typeParameters ?? {};

  ClassSymbol.fromJson(super.json)
      : name = _createValue(json['name']),
        isAbstract = _createValue(json['isAbstract']),
        isConst = _createValue(json['isConst']),
        superClassId = _createValue(json['superClassId']),
        interfaceIds = _createValueList(json['interfaceIds']),
        typeParameters = _createValueMap(json['typeParameters']),
        super.fromJson();

  @override
  Map<String, dynamic> toJson() => {
        ...super.toJson(),
        'name': name,
        'isAbstract': isAbstract,
        'isConst': isConst,
        if (superClassId != null) 'superClassId': superClassId,
        if (interfaceIds.isNotEmpty) 'interfaceIds': interfaceIds,
        if (typeParameters.isNotEmpty) 'typeParameters': typeParameters,
      };
}

class FunctionTypeSymbol extends Symbol implements TypeSymbol {
  /// Mapping of dart type parameter names to JS names.
  final Map<String, String> typeParameters;

  /// Types for positional parameters for this function.
  final List<String> parameterTypeIds;

  /// Types for optional positional parameters for this function.
  final List<String> optionalParameterTypeIds;

  /// Names and types for named parameters for this function.
  final Map<String, String> namedParameterTypeIds;

  /// The return type for this function.
  final String returnTypeId;

  FunctionTypeSymbol({
    Map<String, String>? typeParameters,
    List<String>? parameterTypeIds,
    List<String>? optionalParameterTypeIds,
    Map<String, String>? namedParameterTypeIds,
    required this.returnTypeId,
    required super.localId,
    required String super.scopeId,
    required SourceLocation super.location,
  })  : typeParameters = typeParameters ?? {},
        parameterTypeIds = parameterTypeIds ?? [],
        optionalParameterTypeIds = optionalParameterTypeIds ?? [],
        namedParameterTypeIds = namedParameterTypeIds ?? {};

  FunctionTypeSymbol.fromJson(super.json)
      : parameterTypeIds = _createValueList(json['parameterTypeIds']),
        optionalParameterTypeIds =
            _createValueList(json['optionalParameterTypeIds']),
        typeParameters = _createValueMap(json['typeParameters']),
        namedParameterTypeIds = _createValueMap(json['namedParameterTypeIds']),
        returnTypeId = _createValue(json['returnTypeId']),
        super.fromJson();

  @override
  Map<String, dynamic> toJson() => {
        ...super.toJson(),
        if (typeParameters.isNotEmpty) 'typeParameters': typeParameters,
        if (parameterTypeIds.isNotEmpty) 'parameterTypeIds': parameterTypeIds,
        if (optionalParameterTypeIds.isNotEmpty)
          'optionalParameterTypeIds': optionalParameterTypeIds,
        if (namedParameterTypeIds.isNotEmpty)
          'namedParameterTypeIds': namedParameterTypeIds,
        'returnTypeId': returnTypeId,
      };
}

class FunctionSymbol extends ScopeSymbol {
  /// The name of this function.
  final String name;

  /// Unique Id, shared with JS representation (if any).
  ///
  /// Format:
  ///
  ///     '<scope id>|<js name>'
  ///
  /// Where scope refers to a Library, Class, Function, or Scope.
  /// String id;
  /// Declared type of this function.
  // TODO(nshahan) Only nullable because unused at this time.
  final String? typeId;

  /// True if this function is static.
  final bool isStatic;

  /// True if this function is const.
  final bool isConst;

  FunctionSymbol({
    required this.name,
    required this.typeId,
    bool? isStatic,
    bool? isConst,
    required super.localId,
    required String super.scopeId,
    super.variableIds,
    super.scopeIds,
    required SourceLocation super.location,
  })  : isStatic = isStatic ?? false,
        isConst = isConst ?? false;

  FunctionSymbol.fromJson(super.json)
      : name = _createValue(json['name']),
        typeId = _createValue(json['typeId']),
        isStatic = _createValue(json['isStatic']),
        isConst = _createValue(json['isConst']),
        super.fromJson();

  @override
  Map<String, dynamic> toJson() => {
        ...super.toJson(),
        'name': name,
        if (typeId != null) 'typeId': typeId,
        'isStatic': isStatic,
        'isConst': isConst,
      };
}

class LibrarySymbol extends ScopeSymbol {
  /// The name of this library.
  final String name;

  /// The uri of this library.
  final String uri;

  /// A list of the imports for this library.
  final List<LibrarySymbolDependency> dependencies;

  /// A list of the scripts which constitute this library.
  final List<String> scriptIds;

  LibrarySymbol({
    String? name,
    required this.uri,
    List<LibrarySymbolDependency>? dependencies,
    required this.scriptIds,
    super.variableIds,
    super.scopeIds,
  })  : name = name ?? '',
        dependencies = dependencies ?? [],
        super(
          localId: uri,
        );

  LibrarySymbol.fromJson(super.json)
      : name = _createValue(json['name'], ifNull: ''),
        uri = _createValue(json['uri']),
        scriptIds = _createValueList(json['scriptIds']),
        dependencies = _createObjectList(
            json['dependencies'], LibrarySymbolDependency.fromJson),
        super.fromJson();

  @override
  Map<String, dynamic> toJson() {
    final json = {
      ...super.toJson(),
      if (name.isNotEmpty) 'name': name,
      'uri': uri,
      if (scriptIds.isNotEmpty) 'scriptIds': scriptIds,
    };
    _setObjectListIfNotNullOrEmpty(json, 'dependencies', dependencies);
    return json;
  }
}

class LibrarySymbolDependency implements SymbolTableElement {
  /// True if this dependency an import, false if an export.
  final bool isImport;

  /// True if this dependency is deferred.
  final bool isDeferred;

  /// The prefix of an 'as' import, or null.
  final String? prefix;

  /// The library being imported or exported.
  final String targetId;

  LibrarySymbolDependency({
    required this.isImport,
    bool? isDeferred,
    this.prefix,
    required this.targetId,
  }) : isDeferred = isDeferred ?? false;

  LibrarySymbolDependency.fromJson(Map<String, dynamic> json)
      : isImport = _createValue(json['isImport']),
        isDeferred = _createValue(json['isDeferred']),
        prefix = _createValue(json['prefix']),
        targetId = _createValue(json['targetId']);

  @override
  Map<String, dynamic> toJson() => {
        'isImport': isImport,
        'isDeferred': isDeferred,
        if (prefix != null) 'prefix': prefix,
        'targetId': targetId,
      };
}

class Script implements SymbolTableElement {
  /// The uri from which this script was loaded.
  final String uri;

  /// Unique Id.
  ///
  /// This can be just an integer. The mapping from JS to dart script
  /// happens using the source map. The id is only used for references
  /// in other elements.
  final String localId;

  final String libraryId;

  String get id => '$libraryId|$localId';

  Script({
    required this.uri,
    required this.localId,
    required this.libraryId,
  });

  Script.fromJson(Map<String, dynamic> json)
      : uri = _createValue(json['uri']),
        localId = _createValue(json['localId']),
        libraryId = _createValue(json['libraryId']);

  @override
  Map<String, dynamic> toJson() => {
        'uri': uri,
        'localId': localId,
        'libraryId': libraryId,
      };
}

class ScopeSymbol extends Symbol {
  /// A list of the top-level variables in this scope.
  final List<String> variableIds;

  /// Enclosed scopes.
  ///
  /// Includes all top classes, functions, inner scopes.
  final List<String> scopeIds;

  ScopeSymbol({
    List<String>? variableIds,
    List<String>? scopeIds,
    required super.localId,
    super.scopeId,
    super.location,
  })  : variableIds = variableIds ?? [],
        scopeIds = scopeIds ?? [];

  ScopeSymbol.fromJson(super.json)
      : variableIds = _createValueList(json['variableIds']),
        scopeIds = _createValueList(json['scopeIds']),
        super.fromJson();

  @override
  Map<String, dynamic> toJson() => {
        ...super.toJson(),
        if (variableIds.isNotEmpty) 'variableIds': variableIds,
        if (scopeIds.isNotEmpty) 'scopeIds': scopeIds,
      };
}

class SourceLocation implements SymbolTableElement {
  /// The script containing the source location.
  final String scriptId;

  /// The first token of the location.
  final int tokenPos;

  /// The last token of the location if this is a range.
  final int? endTokenPos;

  SourceLocation({
    required this.scriptId,
    required this.tokenPos,
    this.endTokenPos,
  });

  SourceLocation.fromJson(Map<String, dynamic> json)
      : scriptId = _createValue(json['scriptId']),
        tokenPos = _createValue(json['tokenPos']),
        endTokenPos = _createValue(json['endTokenPos']);

  @override
  Map<String, dynamic> toJson() => {
        'scriptId': scriptId,
        'tokenPos': tokenPos,
        if (endTokenPos != null) 'endTokenPos': endTokenPos,
      };
}

List<T> _createObjectList<T>(
    dynamic json, T Function(Map<String, dynamic>) creator) {
  if (json == null) return <T>[];
  if (json is List) {
    return json.map((e) => _createObject(e, creator)).toList();
  }
  throw ArgumentError('Not a list: $json');
}

T _createObject<T>(dynamic json, T Function(Map<String, dynamic>) creator) {
  if (json is Map<String, dynamic>) {
    return creator(json);
  }
  throw ArgumentError('Not a map: $json');
}

T? _createNullableObject<T>(
        dynamic json, T Function(Map<String, dynamic>) creator) =>
    json == null ? null : _createObject(json, creator);

List<T> _createValueList<T>(dynamic json,
    {T? ifNull, T Function(String)? parse}) {
  if (json == null) return <T>[];
  if (json is List) {
    return json
        .map((e) => _createValue<T>(e, ifNull: ifNull, parse: parse))
        .toList();
  }
  throw ArgumentError('Not a list: $json');
}

Map<String, T> _createValueMap<T>(dynamic json) {
  if (json == null) return <String, T>{};
  return Map<String, T>.from(json as Map<String, dynamic>);
}

T _createValue<T>(dynamic json, {T? ifNull, T Function(String)? parse}) {
  if (json == null && ifNull is T) return ifNull;
  if (json is T) {
    return json;
  }
  if (json is String && parse != null) {
    return parse(json);
  }
  throw ArgumentError('Cannot parse $json as $T');
}

void _setObjectListIfNotNullOrEmpty<T extends SymbolTableElement>(
    Map<String, dynamic> json, String key, List<T>? values) {
  if (values == null || values.isEmpty) return;
  json[key] = values.map((e) => e.toJson()).toList();
}

void _setObjectIfNotNull<T extends SymbolTableElement>(
    Map<String, dynamic> json, String key, T? value) {
  if (value == null) return;
  json[key] = value.toJson();
}
