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

/// Converters and codecs for converting between JSON and [Info] classes.
import 'dart:collection';
import 'dart:convert';

import 'package:collection/collection.dart';

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

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

// 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) {
      CodeInfo src = registry[k];
      assert(src != null);
      for (var dep in deps) {
        var target = registry[dep['id']];
        assert(target != null);
        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) {
    OutputUnitInfo result = parseId(json['id']);
    result
      ..filename = json['filename']
      ..name = json['name']
      ..size = json['size'];
    result.imports
        .addAll((json['imports'] as List).map((s) => s as String) ?? const []);
    return result;
  }

  LibraryInfo parseLibrary(Map json) {
    LibraryInfo result = parseId(json['id']);
    result
      ..name = json['name']
      ..uri = Uri.parse(json['canonicalUri'])
      ..outputUnit = parseId(json['outputUnit'])
      ..size = json['size'];
    for (var child in json['children'].map(parseId)) {
      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 {
        assert(child is TypedefInfo);
        result.typedefs.add(child);
      }
    }
    return result;
  }

  ClassInfo parseClass(Map json) {
    ClassInfo result = parseId(json['id']);
    result
      ..name = json['name']
      ..parent = parseId(json['parent'])
      ..outputUnit = parseId(json['outputUnit'])
      ..size = json['size']
      ..isAbstract = json['modifiers']['abstract'] == true;
    assert(result is ClassInfo);
    for (var child in json['children'].map(parseId)) {
      if (child is FunctionInfo) {
        result.functions.add(child);
      } else {
        assert(child is FieldInfo);
        result.fields.add(child);
      }
    }
    return result;
  }

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

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

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

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

  ProgramInfo parseProgram(Map json) {
    var programInfo = ProgramInfo()
      ..entrypoint = parseId(json['entrypoint'])
      ..size = json['size']
      ..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'];

    // TODO(het): Revert this when the dart2js with the new codec is in stable
    var compilationDuration = json['compilationDuration'];
    if (compilationDuration is String) {
      programInfo.compilationDuration = _parseDuration(compilationDuration);
    } else {
      assert(compilationDuration is int);
      programInfo.compilationDuration =
          Duration(microseconds: compilationDuration);
    }

    var toJsonDuration = json['toJsonDuration'];
    if (toJsonDuration is String) {
      programInfo.toJsonDuration = _parseDuration(toJsonDuration);
    } else {
      assert(toJsonDuration is int);
      programInfo.toJsonDuration = Duration(microseconds: toJsonDuration);
    }

    var dumpInfoDuration = json['dumpInfoDuration'];
    if (dumpInfoDuration is String) {
      programInfo.dumpInfoDuration = _parseDuration(dumpInfoDuration);
    } else {
      assert(dumpInfoDuration is int);
      programInfo.dumpInfoDuration = Duration(microseconds: dumpInfoDuration);
    }

    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) {
    FunctionInfo result = parseId(json['id']);
    return result
      ..name = json['name']
      ..parent = parseId(json['parent'])
      ..coverageId = json['coverageId']
      ..outputUnit = parseId(json['outputUnit'])
      ..size = json['size']
      ..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))
          .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) {
    ClosureInfo result = parseId(json['id']);
    return result
      ..name = json['name']
      ..parent = parseId(json['parent'])
      ..outputUnit = parseId(json['outputUnit'])
      ..size = json['size']
      ..function = parseId(json['function']);
  }

  Info parseId(id) {
    String serializedId = id;
    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();
      }
      assert(false);
      return null;
    });
  }

  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 Set<int> usedIds = <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.parent != null,
        "$info");

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

    while (!usedIds.add(id)) {
      id++;
    }
    serializedId = Id(info.kind, '$id');
    return ids[info] = serializedId;
  }

  @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, '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) => a['id'].compareTo(b['id']));
    }

    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 {
      'elements': elements,
      'holding': jsonHolding,
      'dependencies': jsonDependencies,
      'outputUnits': info.outputUnits.map((u) => u.accept(this)).toList(),
      'dump_version': isBackwardCompatible ? 5 : info.version,
      'deferredFiles': info.deferredFiles,
      'dump_minor_version': isBackwardCompatible ? 1 : info.minorVersion,
      'program': info.program.accept(this)
    };
  }

  @override
  Map visitProgram(ProgramInfo info) {
    return {
      'entrypoint': idFor(info.entrypoint).serializedId,
      'size': info.size,
      '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
            ].expand((i) => i),
            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].expand((i) => i), 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,
        // 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
  visitTypedef(TypedefInfo info) => _visitBasicInfo(info)..['type'] = info.type;

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

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