// 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.
part of dart2js_info.info;

// TODO(sigmund): add unit tests.
class JsonToAllInfoConverter extends Converter<Map<String, dynamic>, AllInfo> {
  Map<String, Info> registry = <String, Info>{};

  AllInfo convert(Map<String, dynamic> json) {
    registry.clear();

    var result = new AllInfo();
    var elements = json['elements'];
    result.libraries
        .addAll((elements['library'] as Map).values.map(parseLibrary));
    result.classes.addAll((elements['class'] as Map).values.map(parseClass));
    result.functions
        .addAll((elements['function'] as Map).values.map(parseFunction));
    result.closures
        .addAll((elements['closure'] as Map).values.map(parseClosure));
    result.fields.addAll((elements['field'] as Map).values.map(parseField));
    result.typedefs
        .addAll((elements['typedef'] as Map).values.map(parseTypedef));
    result.constants
        .addAll((elements['constant'] as Map).values.map(parseConstant));

    var idMap = <String, Info>{};
    for (var f in result.functions) {
      idMap[f.serializedId] = f;
    }
    for (var f in result.fields) {
      idMap[f.serializedId] = f;
    }

    json['holding'].forEach((k, deps) {
      var src = idMap[k];
      assert(src != null);
      for (var dep in deps) {
        var target = idMap[dep['id']];
        assert(target != null);
        (src as CodeInfo).uses.add(new DependencyInfo(target, dep['mask']));
      }
    });

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

    result.outputUnits
        .addAll((json['outputUnits'] as List).map(parseOutputUnit));

    result.program = parseProgram(json['program']);
    // todo: version, etc
    return result;
  }

  OutputUnitInfo parseOutputUnit(Map json) {
    OutputUnitInfo result = parseId(json['id']);
    result
      ..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 {
        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;
  }

  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 = json['code']
      ..isConst = json['const'] ?? false
      ..initializer = parseId(json['initializer'])
      ..closures = (json['children'] as List).map(parseId).toList();
  }

  ConstantInfo parseConstant(Map json) {
    ConstantInfo result = parseId(json['id']);
    return result
      ..code = 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) => new ProgramInfo()
    ..entrypoint = parseId(json['entrypoint'])
    ..size = json['size']
    ..dart2jsVersion = json['dart2jsVersion']
    ..compilationMoment = DateTime.parse(json['compilationMoment'])
    ..compilationDuration =
        new Duration(microseconds: json['compilationDuration'])
    ..toJsonDuration = new Duration(microseconds: json['toJsonDuration'])
    ..dumpInfoDuration = new Duration(microseconds: json['dumpInfoDuration'])
    ..noSuchMethodEnabled = json['noSuchMethodEnabled']
    ..minified = json['minified'];

  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(parseParameter).toList()
      ..code = json['code']
      ..sideEffects = json['sideEffects']
      ..modifiers =
          parseModifiers(new Map<String, bool>.from(json['modifiers']))
      ..closures = (json['children'] as List).map(parseId).toList()
      ..measurements = parseMeasurements(json['measurements']);
  }

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

  Measurements parseMeasurements(Map json) {
    if (json == null) return null;
    var uri = json['sourceFile'];
    var res = new Measurements(uri == null ? null : Uri.parse(uri));
    for (var key in json.keys) {
      var value = json[key];
      if (value == null) continue;
      if (key == 'entries') {
        value.forEach((metricName, entries) {
          var metric = new Metric.fromName(metricName);
          for (var i = 0; i < entries.length; i += 2) {
            res.record(metric, entries[i], entries[i + 1]);
          }
        });
      } else {
        res.counters[new Metric.fromName(key)] = value;
      }
    }
    return res;
  }

  FunctionModifiers parseModifiers(Map<String, bool> json) {
    return new 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(String serializedId) => registry.putIfAbsent(serializedId, () {
        if (serializedId == null) {
          return null;
        } else if (serializedId.startsWith('function/')) {
          return new FunctionInfo._(serializedId);
        } else if (serializedId.startsWith('closure/')) {
          return new ClosureInfo._(serializedId);
        } else if (serializedId.startsWith('library/')) {
          return new LibraryInfo._(serializedId);
        } else if (serializedId.startsWith('class/')) {
          return new ClassInfo._(serializedId);
        } else if (serializedId.startsWith('field/')) {
          return new FieldInfo._(serializedId);
        } else if (serializedId.startsWith('constant/')) {
          return new ConstantInfo._(serializedId);
        } else if (serializedId.startsWith('typedef/')) {
          return new TypedefInfo._(serializedId);
        } else if (serializedId.startsWith('outputUnit/')) {
          return new OutputUnitInfo._(serializedId);
        }
        assert(false);
      });
}

class AllInfoToJsonConverter extends Converter<AllInfo, Map>
    implements InfoVisitor<Map> {
  Map convert(AllInfo info) => info.accept(this);

  Map _visitList(List<Info> infos) {
    var map = <String, Map>{};
    for (var info in infos) {
      map['${info.id}'] = info.accept(this);
    }
    return map;
  }

  Map _visitAllInfoElements(AllInfo info) {
    var jsonLibraries = _visitList(info.libraries);
    var jsonClasses = _visitList(info.classes);
    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,
      'function': jsonFunctions,
      'typedef': jsonTypedefs,
      'field': jsonFields,
      'constant': jsonConstants,
      'closure': jsonClosures,
    };
  }

  Map _visitDependencyInfo(DependencyInfo info) =>
      {'id': info.target.serializedId, 'mask': info.mask};

  Map _visitAllInfoHolding(AllInfo allInfo) {
    var map = <String, List>{};
    void helper(CodeInfo info) {
      if (info.uses.isEmpty) return;
      map[info.serializedId] =
          info.uses.map((u) => _visitDependencyInfo(u)).toList();
    }

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

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

  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': info.version,
      'deferredFiles': info.deferredFiles,
      'dump_minor_version': '${info.minorVersion}',
      'program': info.program.accept(this)
    };
  }

  Map visitProgram(ProgramInfo info) {
    return {
      'entrypoint': 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,
      'minified': info.minified,
    };
  }

  Map _visitBasicInfo(BasicInfo info) {
    var res = {
      'id': 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'] = info.outputUnit.serializedId;
    }
    if (info.coverageId != null) res['coverageId'] = info.coverageId;
    if (info.parent != null) res['parent'] = info.parent.serializedId;
    return res;
  }

  Map visitLibrary(LibraryInfo info) {
    return _visitBasicInfo(info)
      ..addAll({
        'children': []
          ..addAll(info.topLevelFunctions.map((f) => f.serializedId))
          ..addAll(info.topLevelVariables.map((v) => v.serializedId))
          ..addAll(info.classes.map((c) => c.serializedId))
          ..addAll(info.typedefs.map((t) => t.serializedId)),
        'canonicalUri': '${info.uri}',
      });
  }

  Map visitClass(ClassInfo info) {
    return _visitBasicInfo(info)
      ..addAll({
        // TODO(sigmund): change format, include only when abstract is true.
        'modifiers': {'abstract': info.isAbstract},
        'children': []
          ..addAll(info.fields.map((f) => f.serializedId))
          ..addAll(info.functions.map((m) => m.serializedId))
      });
  }

  Map visitField(FieldInfo info) {
    var result = _visitBasicInfo(info)
      ..addAll({
        'children': info.closures.map((i) => i.serializedId).toList(),
        'inferredType': info.inferredType,
        'code': info.code,
        'type': info.type,
      });
    if (info.isConst) {
      result['const'] = true;
      if (info.initializer != null) {
        result['initializer'] = info.initializer.serializedId;
      }
    }
    return result;
  }

  Map visitConstant(ConstantInfo info) =>
      _visitBasicInfo(info)..addAll({'code': 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};

  String _visitMetric(Metric metric) => metric.name;

  Map _visitMeasurements(Measurements measurements) {
    if (measurements == null) return null;
    var jsonEntries = <String, List<int>>{};
    measurements.entries.forEach((metric, values) {
      jsonEntries[_visitMetric(metric)] =
          values.expand((e) => [e.begin, e.end]).toList();
    });
    var json = <String, dynamic>{'entries': jsonEntries};
    // TODO(sigmund): encode uri as an offset of the URIs available in the parts
    // of the library info.
    if (measurements.uri != null) json['sourceFile'] = '${measurements.uri}';
    if (measurements.counters[Metric.functions] != null) {
      json[_visitMetric(Metric.functions)] =
          measurements.counters[Metric.functions];
    }
    if (measurements.counters[Metric.reachableFunctions] != null) {
      json[_visitMetric(Metric.reachableFunctions)] =
          measurements.counters[Metric.reachableFunctions];
    }
    return json;
  }

  Map visitFunction(FunctionInfo info) {
    return _visitBasicInfo(info)
      ..addAll({
        'children': info.closures.map((i) => i.serializedId).toList(),
        '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': info.code,
        'type': info.type,
        'measurements': _visitMeasurements(info.measurements),
        // Note: version 3.2 of dump-info serializes `uses` in a section called
        // `holding` at the top-level.
      });
  }

  Map visitClosure(ClosureInfo info) {
    return _visitBasicInfo(info)
      ..addAll({'function': info.function.serializedId});
  }

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

  visitOutput(OutputUnitInfo info) =>
      _visitBasicInfo(info)..['imports'] = info.imports;
}

class AllInfoJsonCodec extends Codec<AllInfo, Map> {
  final Converter<AllInfo, Map> encoder = new AllInfoToJsonConverter();
  final Converter<Map, AllInfo> decoder = new JsonToAllInfoConverter();
}
