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

// @dart = 2.10

import "dart:convert";
import "dart:io";
import "package:kernel/kernel.dart";

main(List<String> args) async {
  // Ensure right args are passed.
  if (args.length < 1) {
    print("usage: ${Platform.script} a.dill");
  }

  // Parse .dill and extract component.
  var dill = args[0];
  var component = loadComponentFromBinary(dill);
  var visitor = MetricsVisitor(["dart:html"]);

  // Visit component.
  component.accept(visitor);

  // Save data to file.
  visitor.saveDataToFile("dart2html_metrics.json");
}

/// Visits classes in libraries specified by `libraryFilter`
/// and aggregates metrics by class.
class MetricsVisitor extends RecursiveVisitor {
  String currentClass;
  List<String> libraryFilter;
  Map<String, ClassMetrics> classInfo = {};

  MetricsVisitor([filter]) {
    libraryFilter = filter ?? [];
  }

  @override
  void visitComponent(Component node) {
    super.visitComponent(node);
    _processData();
  }

  @override
  void visitLibrary(Library node) {
    // Check if this is a library we want to visit.
    var visit = libraryFilter.isNotEmpty
        ? libraryFilter
            .contains("${node.importUri.scheme}:${node.importUri.path}")
        : true;

    if (visit) {
      super.visitLibrary(node);
    }
  }

  @override
  void visitProcedure(Procedure node) {
    classInfo[currentClass].methods.add(ClassMetricsMethod(
        node.name.text,
        node.containsSuperCalls,
        node.isInstanceMember,
        node.isExternal,
        node.isAbstract,
        node.kind.toString()));
  }

  @override
  void visitClass(Class node) {
    // Don't want to add duplicate info.
    // When mixed, anonymous mixin class generated so we want to ignore.
    if (!node.isAnonymousMixin) {
      currentClass = node.name;
      var metrics = ClassMetrics();

      // Check if class contains native members.
      if (node.annotations.any(_isNativeMarkerAnnotation)) {
        metrics.containsNativeMember = true;
      }

      // Check if Mixed.
      if (node.superclass?.isAnonymousMixin ?? false) {
        metrics.mixed = true;
        metrics.mixins = _filterMixins(node.superclass.demangledName);
      }

      // Add parents.
      if (node.superclass != null) {
        var unmangledParent = _getParent(node.superclass);
        metrics.parent = unmangledParent;
      }

      // Check for implemented classes.
      if (node.implementedTypes.length > 0) {
        var implementedTypes =
            node.implementedTypes.map((type) => type.className.asClass.name);
        metrics.implementedTypes = implementedTypes.toList();
      }

      classInfo[currentClass] = metrics;

      super.visitClass(node);
    }
  }

  // Returns List of parsed mixins from superclass name.
  List<String> _filterMixins(String superWithMixins) {
    var start = superWithMixins.indexOf("with") + 4;
    var mixins = superWithMixins.substring(start);
    mixins = mixins.replaceAll(" ", "");

    return mixins.split(",");
  }

  // Recursively searches superclasses, filtering anonymous mixins,
  // and returns parent class name.
  String _getParent(Class node) {
    if (node.isAnonymousMixin) {
      return _getParent(node.superclass);
    }

    return node.name;
  }

  // Returns true if a class Annotation is Native.
  bool _isNativeMarkerAnnotation(Expression annotation) {
    if (annotation is ConstructorInvocation) {
      var type = annotation.constructedType;
      if (type.classNode.name == "Native") {
        return true;
      }
    }
    return false;
  }

  // Passes through the aggregated data and processes,
  // adding child classes and overridden methods from parent.
  void _processData() {
    classInfo.keys.forEach((className) {
      var parentName = classInfo[className].parent;
      if (classInfo[parentName] != null) {
        classInfo[parentName].inheritedBy.add(className);

        var notOverridden = <String>[];
        var parentMethods = classInfo[parentName].methods.map((m) => m.name);
        var classMethods = classInfo[className].methods.map((m) => m.name);

        parentMethods.forEach((method) =>
            {if (!classMethods.contains(method)) notOverridden.add(method)});

        // Update Method Info.
        classInfo[className].notOverriddenMethods = notOverridden;
      }
    });
  }

  // Saves the data to file.
  void saveDataToFile(String filename) {
    var formatted = jsonFormat(classInfo);

    File(filename).writeAsStringSync(formatted);
  }

  // Converts the passed Map to a pretty print JSON string.
  String jsonFormat(Map<String, ClassMetrics> info) {
    JsonEncoder encoder = new JsonEncoder.withIndent("  ");
    return encoder.convert(info);
  }
}

/// Tracks info compiled for a class.
class ClassMetrics {
  List<ClassMetricsMethod> methods;
  List<String> mixins;
  List<String> implementedTypes;
  List<String> notOverriddenMethods;
  List<String> inheritedBy;
  String parent;
  bool mixed;
  bool containsNativeMember;

  ClassMetrics(
      {this.mixed = false,
      this.containsNativeMember = false,
      this.parent,
      methods,
      mixins,
      notOverridden,
      implementedTypes,
      inheritedBy}) {
    this.methods = methods ?? [];
    this.mixins = mixins ?? [];
    this.notOverriddenMethods = notOverridden ?? [];
    this.implementedTypes = implementedTypes ?? [];
    this.inheritedBy = inheritedBy ?? [];
  }

  bool get invokesSuper {
    if (methods.isNotEmpty) {
      return methods.any((e) => e.invokesSuper);
    }

    return false;
  }

  Map<String, dynamic> toJson() {
    return {
      "invokesSuper": invokesSuper,
      "methods": methods,
      "mixed": mixed,
      "mixins": mixins,
      "parent": parent,
      "inheritedBy": inheritedBy,
      "containsNativeMember": containsNativeMember,
      "notOverriddenMethods": notOverriddenMethods,
      "implementedTypes": implementedTypes
    };
  }
}

/// Tracks info related to a specific method.
class ClassMetricsMethod {
  String name;
  String methodKind;
  bool invokesSuper;
  bool isInstanceMember;
  bool isExternal;
  bool isAbstract;

  ClassMetricsMethod(this.name,
      [this.invokesSuper = false,
      this.isInstanceMember = false,
      this.isExternal = false,
      this.isAbstract = false,
      this.methodKind = ""]);

  Map<String, dynamic> toJson() {
    return {
      "name": name,
      "invokesSuper": invokesSuper,
      "isInstanceMember": isInstanceMember,
      "isExternal": isExternal,
      "isAbstract": isAbstract,
      "methodKind": methodKind
    };
  }
}
