// 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) => {
        'id': idFor(info.target).serializedId,
        if (info.mask != null) 'mask': info.mask,
      };

  Map _visitAllInfoHolding(AllInfo allInfo) {
    var map = SplayTreeMap<String, List>(compareNatural);
    void helper(CodeInfo info) {
      if (info.uses.isEmpty) return;
      map[idFor(info).serializedId] =
          info.uses.map(visitDependencyInfo).toList()
            ..sort((a, b) {
              final value = a['id'].compareTo(b['id']);
              if (value != 0) return value;
              final aMask = a['mask'] as String?;
              final bMask = b['mask'] as String?;
              if (aMask == null) {
                return bMask == null ? 0 : 1;
              }
              if (bMask == null) {
                return -1;
              }
              return aMask.compareTo(bMask);
            });
    }

    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';
}
