// 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();
}
