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

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

  /// Whether to filter all treeshaken elements.
  final bool filterTreeshaken;
  final Map<Info, Id> ids = HashMap<Info, Id>();
  final Set<String> usedIds = <String>{};

  AllInfoToJsonConverter(
      {this.isBackwardCompatible = false, this.filterTreeshaken = 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");

    String name;
    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.
      name = info.code.first.text ?? '';
    } else {
      name = longName(info, useLibraryUri: true, forId: true);
    }

    Id id = Id(info.kind, name);
    // longName isn't guaranteed to create unique serializedIds for some info
    // constructs (such as closures), so we disambiguate here.
    int count = 0;
    while (!usedIds.add(id.serializedId)) {
      id = Id(info.kind, '$name%${count++}');
    }

    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) {
      if (info is BasicInfo) {
        if (filterTreeshaken &&
            info.treeShakenStatus != TreeShakenStatus.Live) {
          continue;
        }
      }
      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
        ], 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)
      });
  }

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

  List<String> _toSortedSerializedIds(
          Iterable<Info> infos, Id Function(Info) getId) =>
      infos
          .where((i) =>
              !filterTreeshaken || i.treeShakenStatus == TreeShakenStatus.Live)
          .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, bool filterTreeshaken = false})
      : encoder = AllInfoToJsonConverter(
            isBackwardCompatible: isBackwardCompatible,
            filterTreeshaken: filterTreeshaken);
}

class Id {
  final InfoKind kind;
  final String id;

  Id(this.kind, this.id);

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