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

// ignore_for_file: avoid_dynamic_calls

/// Converters and codecs for converting between JSON and [Info] classes.
library;

import 'dart:collection';
import 'dart:convert';

import 'package:collection/collection.dart';

import 'info.dart';
import 'src/util.dart';

// TODO(sigmund): add unit tests.
class JsonToAllInfoConverter extends Converter<Map<String, dynamic>, AllInfo> {
  // Using `MashMap` here because it's faster than the default `LinkedHashMap`.
  final Map<String, Info> registry = HashMap<String, Info>();

  @override
  AllInfo convert(Map<String, dynamic> input) {
    registry.clear();

    var result = AllInfo();
    var elements = input['elements'];
    // TODO(srawlins): Since only the Map values are being extracted below,
    // replace `as` with `cast` when `cast` becomes available in Dart 2.0:
    //
    //     .addAll(elements['library'].values.cast<Map>().map(parseLibrary));
    result.libraries.addAll(
      (elements['library'] as Map).values.map((l) => parseLibrary(l)),
    );
    result.classes.addAll(
      (elements['class'] as Map).values.map((c) => parseClass(c)),
    );
    result.classTypes.addAll(
      (elements['classType'] as Map).values.map((c) => parseClassType(c)),
    );
    result.functions.addAll(
      (elements['function'] as Map).values.map((f) => parseFunction(f)),
    );

    // TODO(het): Revert this when the dart2js with the new codec is in stable
    if (elements['closure'] != null) {
      result.closures.addAll(
        (elements['closure'] as Map).values.map((c) => parseClosure(c)),
      );
    }
    result.fields.addAll(
      (elements['field'] as Map).values.map((f) => parseField(f)),
    );
    result.typedefs.addAll(
      (elements['typedef'] as Map).values.map((t) => parseTypedef(t)),
    );
    result.constants.addAll(
      (elements['constant'] as Map).values.map((c) => parseConstant(c)),
    );

    input['holding'].forEach((k, deps) {
      final src = registry[k] as CodeInfo;
      for (var dep in deps) {
        final target = registry[dep['id']]!;
        src.uses.add(DependencyInfo(target, dep['mask']));
      }
    });

    input['dependencies']?.forEach((String k, dependencies) {
      List<String> deps = dependencies;
      result.dependencies[registry[k]!] = deps
          .map((d) => registry[d]!)
          .toList();
    });

    result.outputUnits.addAll(
      (input['outputUnits'] as List).map((o) => parseOutputUnit(o)),
    );

    result.program = parseProgram(input['program']);

    if (input['deferredFiles'] != null) {
      final deferredFilesMap = (input['deferredFiles'] as Map)
          .cast<String, Map<String, dynamic>>();
      for (final library in deferredFilesMap.values) {
        if (library['imports'] != null) {
          // The importMap needs to be typed as <String, List<String>>, but the
          // json parser produces <String, dynamic>.
          final importMap = library['imports'] as Map<String, dynamic>;
          importMap.forEach((prefix, files) {
            importMap[prefix] = (files as List<dynamic>).cast<String>();
          });
          library['imports'] = importMap.cast<String, List<String>>();
        }
      }
      result.deferredFiles = deferredFilesMap;
    }

    // todo: version, etc
    return result;
  }

  OutputUnitInfo parseOutputUnit(Map json) {
    final result = parseId(json['id']) as OutputUnitInfo;
    result
      ..filename = json['filename']
      ..name = json['name']
      ..size = json['size'];
    result.imports.addAll((json['imports'] as List).map((s) => s as String));
    return result;
  }

  LibraryInfo parseLibrary(Map json) {
    final result = parseId(json['id']) as LibraryInfo;
    result
      ..name = json['name']
      ..uri = Uri.parse(json['canonicalUri'])
      ..outputUnit = parseId(json['outputUnit']) as OutputUnitInfo?
      ..size = json['size'];
    for (var child in json['children'].map((id) => parseId(id))) {
      if (child is FunctionInfo) {
        result.topLevelFunctions.add(child);
      } else if (child is FieldInfo) {
        result.topLevelVariables.add(child);
      } else if (child is ClassInfo) {
        result.classes.add(child);
      } else if (child is ClassTypeInfo) {
        result.classTypes.add(child);
      } else if (child is TypedefInfo) {
        result.typedefs.add(child);
      } else {
        throw StateError('Invalid LibraryInfo child: $child');
      }
    }
    return result;
  }

  ClassInfo parseClass(Map json) {
    final result = parseId(json['id']) as ClassInfo;
    result
      ..name = json['name']
      ..parent = parseId(json['parent'])
      ..outputUnit = parseId(json['outputUnit']) as OutputUnitInfo?
      ..size = json['size']
      ..isAbstract = json['modifiers']['abstract'] == true;
    for (var child in json['children'].map((id) => parseId(id))) {
      if (child is FunctionInfo) {
        result.functions.add(child);
      } else if (child is FieldInfo) {
        result.fields.add(child);
      } else {
        throw StateError('Invalid ClassInfo child: $child');
      }
    }
    result.supers.addAll(
      json['supers'].map<ClassInfo>((id) => parseId(id) as ClassInfo),
    );
    return result;
  }

  ClassTypeInfo parseClassType(Map json) {
    final result = parseId(json['id']) as ClassTypeInfo;
    result
      ..name = json['name']
      ..parent = parseId(json['parent'])
      ..outputUnit = parseId(json['outputUnit']) as OutputUnitInfo?
      ..size = json['size'];
    return result;
  }

  FieldInfo parseField(Map json) {
    final result = parseId(json['id']) as FieldInfo;
    return result
      ..name = json['name']
      ..parent = parseId(json['parent'])
      ..coverageId = json['coverageId']
      ..outputUnit = parseId(json['outputUnit']) as OutputUnitInfo?
      ..size = json['size']
      ..type = json['type']
      ..inferredType = json['inferredType']
      ..code = parseCode(json['code'])
      ..isConst = json['const'] ?? false
      ..initializer = parseId(json['initializer']) as ConstantInfo?
      ..closures = (json['children'] as List)
          .map<ClosureInfo>((c) => parseId(c) as ClosureInfo)
          .toList();
  }

  ConstantInfo parseConstant(Map json) {
    final result = parseId(json['id']) as ConstantInfo;
    return result
      ..name = json['name']
      ..code = parseCode(json['code'])
      ..size = json['size']
      ..outputUnit = parseId(json['outputUnit']) as OutputUnitInfo?;
  }

  TypedefInfo parseTypedef(Map json) {
    final result = parseId(json['id']) as TypedefInfo;
    return result
      ..name = json['name']
      ..parent = parseId(json['parent'])
      ..type = json['type']
      ..size = 0;
  }

  ProgramInfo parseProgram(Map json) {
    // TODO(het): Revert this when the dart2js with the new codec is in stable
    final compilationDuration = json['compilationDuration'];
    final compilationDurationParsed = compilationDuration is String
        ? _parseDuration(compilationDuration)
        : Duration(microseconds: compilationDuration as int);

    final toJsonDuration = json['toJsonDuration'];
    final toJsonDurationParsed = toJsonDuration is String
        ? _parseDuration(toJsonDuration)
        : Duration(microseconds: toJsonDuration as int);

    final dumpInfoDuration = json['dumpInfoDuration'];
    final dumpInfoDurationParsed = dumpInfoDuration is String
        ? _parseDuration(dumpInfoDuration)
        : Duration(microseconds: dumpInfoDuration as int);

    final programInfo = ProgramInfo(
      entrypoint: parseId(json['entrypoint']) as FunctionInfo,
      size: json['size'],
      ramUsage: json['ramUsage'],
      compilationMoment: DateTime.parse(json['compilationMoment']),
      dart2jsVersion: json['dart2jsVersion'],
      noSuchMethodEnabled: json['noSuchMethodEnabled'],
      isRuntimeTypeUsed: json['isRuntimeTypeUsed'],
      isIsolateInUse: json['isIsolateInUse'],
      isFunctionApplyUsed: json['isFunctionApplyUsed'],
      isMirrorsUsed: json['isMirrorsUsed'],
      minified: json['minified'],
      compilationDuration: compilationDurationParsed,
      toJsonDuration: toJsonDurationParsed,
      dumpInfoDuration: dumpInfoDurationParsed,
    );

    return programInfo;
  }

  /// Parse a string formatted as "XX:YY:ZZ.ZZZZZ" into a [Duration].
  Duration _parseDuration(String duration) {
    if (!duration.contains(':')) {
      return Duration(milliseconds: int.parse(duration));
    }
    var parts = duration.split(':');
    var hours = double.parse(parts[0]);
    var minutes = double.parse(parts[1]);
    var seconds = double.parse(parts[2]);
    const secondsInMillis = 1000;
    const minutesInMillis = 60 * secondsInMillis;
    const hoursInMillis = 60 * minutesInMillis;
    var totalMillis =
        secondsInMillis * seconds +
        minutesInMillis * minutes +
        hoursInMillis * hours;
    return Duration(milliseconds: totalMillis.round());
  }

  FunctionInfo parseFunction(Map json) {
    final result = parseId(json['id']) as FunctionInfo;
    return result
      ..name = json['name']
      ..parent = parseId(json['parent'])
      ..coverageId = json['coverageId']
      ..outputUnit = parseId(json['outputUnit']) as OutputUnitInfo?
      ..size = json['size']
      ..functionKind = json['functionKind']
      ..type = json['type']
      ..returnType = json['returnType']
      ..inferredReturnType = json['inferredReturnType']
      ..parameters = (json['parameters'] as List)
          .map((p) => parseParameter(p))
          .toList()
      ..code = parseCode(json['code'])
      ..sideEffects = json['sideEffects']
      ..inlinedCount = json['inlinedCount']
      ..modifiers = parseModifiers(Map<String, bool>.from(json['modifiers']))
      ..closures = (json['children'] as List)
          .map<ClosureInfo>((c) => parseId(c) as ClosureInfo)
          .toList();
  }

  ParameterInfo parseParameter(Map json) =>
      ParameterInfo(json['name'], json['type'], json['declaredType']);

  FunctionModifiers parseModifiers(Map<String, bool> json) {
    return FunctionModifiers(
      isStatic: json['static'] == true,
      isConst: json['const'] == true,
      isFactory: json['factory'] == true,
      isExternal: json['external'] == true,
    );
  }

  ClosureInfo parseClosure(Map json) {
    final result = parseId(json['id']) as ClosureInfo;
    return result
      ..name = json['name']
      ..parent = parseId(json['parent'])
      ..outputUnit = parseId(json['outputUnit']) as OutputUnitInfo?
      ..size = json['size']
      ..function = parseId(json['function']) as FunctionInfo;
  }

  Info? parseId(String? serializedId) {
    if (serializedId == null) {
      return null;
    }
    return registry.putIfAbsent(serializedId, () {
      if (serializedId.startsWith('function/')) {
        return FunctionInfo.internal();
      } else if (serializedId.startsWith('closure/')) {
        return ClosureInfo.internal();
      } else if (serializedId.startsWith('library/')) {
        return LibraryInfo.internal();
      } else if (serializedId.startsWith('class/')) {
        return ClassInfo.internal();
      } else if (serializedId.startsWith('classType/')) {
        return ClassTypeInfo.internal();
      } else if (serializedId.startsWith('field/')) {
        return FieldInfo.internal();
      } else if (serializedId.startsWith('constant/')) {
        return ConstantInfo.internal();
      } else if (serializedId.startsWith('typedef/')) {
        return TypedefInfo.internal();
      } else if (serializedId.startsWith('outputUnit/')) {
        return OutputUnitInfo.internal();
      }
      throw StateError('Invalid serialized ID found: $serializedId');
    });
  }

  List<CodeSpan> parseCode(dynamic json) {
    // backwards compatibility with format 5.1:
    if (json is String) {
      return [CodeSpan(start: null, end: null, text: json)];
    }

    if (json is List) {
      return json.map((dynamic value) {
        Map<String, dynamic> jsonCode = value;
        return CodeSpan(
          start: jsonCode['start'],
          end: jsonCode['end'],
          text: jsonCode['text'],
        );
      }).toList();
    }

    return [];
  }
}

class AllInfoToJsonConverter extends Converter<AllInfo, Map>
    implements InfoVisitor<Map> {
  /// Whether to generate json compatible with format 5.1
  final bool isBackwardCompatible;

  final Map<Info, Id> ids = HashMap<Info, Id>();
  final Map<String, int> idCounter = <String, int>{};

  AllInfoToJsonConverter({this.isBackwardCompatible = false});

  Id idFor(Info info) {
    var serializedId = ids[info];
    if (serializedId != null) return serializedId;

    assert(
      info is LibraryInfo ||
          info is ConstantInfo ||
          info is OutputUnitInfo ||
          info is ClassInfo ||
          info.parent != null,
      "$info",
    );

    String name;
    if (info is ConstantInfo) {
      // No name and no parent, so `longName` isn't helpful
      assert(info.name.isEmpty);
      assert(info.parent == null);
      // Instead, use the content of the code.
      name = info.code.first.text ?? '';
    } else {
      name = longName(info, useLibraryUri: true, forId: true);
    }

    // longName isn't guaranteed to create unique serializedIds for some info
    // constructs (such as closures), so we disambiguate here.
    Id id = Id(info.kind, name);
    final count = idCounter.update(
      id.serializedId,
      (v) => v + 1,
      ifAbsent: () => 0,
    );
    if (count > 0) {
      id = Id(info.kind, '$name%${count - 1}');
    }
    return ids[info] = id;
  }

  @override
  Map convert(AllInfo input) => input.accept(this);

  Map _visitList(List<Info> infos) {
    // Using SplayTree to maintain a consistent order of keys
    var map = SplayTreeMap<String, Map>(compareNatural);
    for (var info in infos) {
      map[idFor(info).id] = info.accept(this);
    }
    return map;
  }

  Map _visitAllInfoElements(AllInfo info) {
    var jsonLibraries = _visitList(info.libraries);
    var jsonClasses = _visitList(info.classes);
    var jsonClassTypes = _visitList(info.classTypes);
    var jsonFunctions = _visitList(info.functions);
    var jsonTypedefs = _visitList(info.typedefs);
    var jsonFields = _visitList(info.fields);
    var jsonConstants = _visitList(info.constants);
    var jsonClosures = _visitList(info.closures);
    return {
      'library': jsonLibraries,
      'class': jsonClasses,
      'classType': jsonClassTypes,
      'function': jsonFunctions,
      'typedef': jsonTypedefs,
      'field': jsonFields,
      'constant': jsonConstants,
      'closure': jsonClosures,
    };
  }

  Map visitDependencyInfo(DependencyInfo info) =>
      _createFromDepInfo(info).toJson();

  _InfoClass _createFromDepInfo(DependencyInfo info) =>
      _InfoClass._(idFor(info.target).serializedId, info.mask);

  Map _visitAllInfoHolding(AllInfo allInfo) {
    var map = SplayTreeMap<String, List<Map<String, dynamic>>>(compareNatural);
    void helper(CodeInfo info) {
      if (info.uses.isEmpty) return;
      map[idFor(info).serializedId] = SplayTreeSet.of(
        info.uses.map(_createFromDepInfo),
      ).map((e) => e.toJson()).toList();
    }

    allInfo.functions.forEach(helper);
    allInfo.fields.forEach(helper);
    return map;
  }

  Map _visitAllInfoDependencies(AllInfo allInfo) {
    var map = SplayTreeMap<String, List>(compareNatural);
    allInfo.dependencies.forEach((k, v) {
      map[idFor(k).serializedId] = _toSortedSerializedIds(v, idFor);
    });
    return map;
  }

  @override
  Map visitAll(AllInfo info) {
    var elements = _visitAllInfoElements(info);
    var jsonHolding = _visitAllInfoHolding(info);
    var jsonDependencies = _visitAllInfoDependencies(info);
    return {
      'dump_version': isBackwardCompatible ? 5 : info.version,
      'dump_minor_version': isBackwardCompatible ? 1 : info.minorVersion,
      'program': info.program!.accept(this),
      'elements': elements,
      'holding': jsonHolding,
      'dependencies': jsonDependencies,
      'outputUnits': info.outputUnits.map((u) => u.accept(this)).toList(),
      'deferredFiles': info.deferredFiles,
    };
  }

  @override
  Map visitProgram(ProgramInfo info) {
    return {
      'entrypoint': idFor(info.entrypoint).serializedId,
      'size': info.size,
      'ramUsage': info.ramUsage,
      'dart2jsVersion': info.dart2jsVersion,
      'compilationMoment': '${info.compilationMoment}',
      'compilationDuration': info.compilationDuration.inMicroseconds,
      'toJsonDuration': info.toJsonDuration.inMicroseconds,
      'dumpInfoDuration': info.dumpInfoDuration.inMicroseconds,
      'noSuchMethodEnabled': info.noSuchMethodEnabled,
      'isRuntimeTypeUsed': info.isRuntimeTypeUsed,
      'isIsolateInUse': info.isIsolateInUse,
      'isFunctionApplyUsed': info.isFunctionApplyUsed,
      'isMirrorsUsed': info.isMirrorsUsed,
      'minified': info.minified,
    };
  }

  Map _visitBasicInfo(BasicInfo info) {
    var res = {
      'id': idFor(info).serializedId,
      'kind': kindToString(info.kind),
      'name': info.name,
      'size': info.size,
    };
    // TODO(sigmund): Omit this also when outputUnit.id == 0 (most code is in
    // the main output unit by default).
    if (info.outputUnit != null) {
      res['outputUnit'] = idFor(info.outputUnit!).serializedId;
    }
    if (info.coverageId != null) res['coverageId'] = info.coverageId;
    if (info.parent != null) res['parent'] = idFor(info.parent!).serializedId;
    return res;
  }

  @override
  Map visitLibrary(LibraryInfo info) {
    return _visitBasicInfo(info)..addAll(<String, Object>{
      'children': _toSortedSerializedIds([
        ...info.topLevelFunctions,
        ...info.topLevelVariables,
        ...info.classes,
        ...info.classTypes,
        ...info.typedefs,
      ], idFor),
      'canonicalUri': '${info.uri}',
    });
  }

  @override
  Map visitClass(ClassInfo info) {
    return _visitBasicInfo(info)..addAll(<String, Object>{
      // TODO(sigmund): change format, include only when abstract is true.
      'modifiers': {'abstract': info.isAbstract},
      'children': _toSortedSerializedIds([
        ...info.fields,
        ...info.functions,
      ], idFor),
      'supers': _toSortedSerializedIds(info.supers, idFor),
    });
  }

  @override
  Map visitClassType(ClassTypeInfo info) {
    return _visitBasicInfo(info);
  }

  @override
  Map visitField(FieldInfo info) {
    var result = _visitBasicInfo(info)
      ..addAll(<String, Object>{
        'children': _toSortedSerializedIds(info.closures, idFor),
        'inferredType': info.inferredType,
        'code': _serializeCode(info.code),
        'type': info.type,
      });
    if (info.isConst) {
      result['const'] = true;
      if (info.initializer != null) {
        result['initializer'] = idFor(info.initializer!).serializedId;
      }
    }
    return result;
  }

  @override
  Map visitConstant(ConstantInfo info) =>
      _visitBasicInfo(info)
        ..addAll(<String, Object>{'code': _serializeCode(info.code)});

  // TODO(sigmund): exclude false values (requires bumping the format version):
  //     var res = <String, bool>{};
  //     if (isStatic) res['static'] = true;
  //     if (isConst) res['const'] = true;
  //     if (isFactory) res['factory'] = true;
  //     if (isExternal) res['external'] = true;
  //     return res;
  Map _visitFunctionModifiers(FunctionModifiers mods) => {
    'static': mods.isStatic,
    'const': mods.isConst,
    'factory': mods.isFactory,
    'external': mods.isExternal,
  };

  Map _visitParameterInfo(ParameterInfo info) => {
    'name': info.name,
    'type': info.type,
    'declaredType': info.declaredType,
  };

  @override
  Map visitFunction(FunctionInfo info) {
    return _visitBasicInfo(info)..addAll(<String, Object?>{
      'children': _toSortedSerializedIds(info.closures, idFor),
      'modifiers': _visitFunctionModifiers(info.modifiers),
      'returnType': info.returnType,
      'inferredReturnType': info.inferredReturnType,
      'parameters': info.parameters.map((p) => _visitParameterInfo(p)).toList(),
      'sideEffects': info.sideEffects,
      'inlinedCount': info.inlinedCount,
      'code': _serializeCode(info.code),
      'type': info.type,
      'functionKind': info.functionKind,
      // Note: version 3.2 of dump-info serializes `uses` in a section called
      // `holding` at the top-level.
    });
  }

  @override
  Map visitClosure(ClosureInfo info) {
    return _visitBasicInfo(info)
      ..addAll(<String, Object>{'function': idFor(info.function).serializedId});
  }

  @override
  Map visitTypedef(TypedefInfo info) =>
      _visitBasicInfo(info)..['type'] = info.type;

  @override
  Map visitOutput(OutputUnitInfo info) => _visitBasicInfo(info)
    ..['filename'] = info.filename
    ..['imports'] = info.imports;

  Object _serializeCode(List<CodeSpan> code) {
    if (isBackwardCompatible) {
      return code.map((c) => c.text).join('\n');
    }
    return code
        .map<Object>((c) => {'start': c.start, 'end': c.end, 'text': c.text})
        .toList();
  }

  List<String> _toSortedSerializedIds(
    Iterable<Info> infos,
    Id Function(Info) getId,
  ) => infos.map((i) => getId(i).serializedId).toList()..sort(compareNatural);
}

class AllInfoJsonCodec extends Codec<AllInfo, Map> {
  @override
  final Converter<AllInfo, Map> encoder;
  @override
  final Converter<Map, AllInfo> decoder = JsonToAllInfoConverter();

  AllInfoJsonCodec({bool isBackwardCompatible = false})
    : encoder = AllInfoToJsonConverter(
        isBackwardCompatible: isBackwardCompatible,
      );
}

class Id {
  final InfoKind kind;
  final String id;

  Id(this.kind, this.id);

  String get serializedId => '${kindToString(kind)}/$id';
}

/// Represents the serialization information of [DependencyInfo] with equality
/// and comparison implemented.
final class _InfoClass implements Comparable<_InfoClass> {
  final String id;
  final String? mask;

  _InfoClass._(this.id, this.mask);

  Map<String, dynamic> toJson() => {'id': id, if (mask != null) 'mask': mask};

  @override
  int compareTo(_InfoClass other) {
    final value = id.compareTo(other.id);
    if (value != 0) {
      return value;
    }

    final myMask = mask, otherMask = other.mask;

    if (myMask == null) {
      return otherMask == null ? 0 : 1;
    }
    if (otherMask == null) {
      return -1;
    }

    return myMask.compareTo(otherMask);
  }
}
