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

import 'dart:io' as io;

import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
import 'package:analyzer/dart/analysis/context_root.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/diagnostic/diagnostic.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:analyzer/src/utilities/extensions/flutter.dart';
import 'package:args/args.dart';

/// Compute and print information about flutter packages.
Future<void> main(List<String> args) async {
  var parser = createArgParser();
  var result = parser.parse(args);

  if (validArguments(parser, result)) {
    var out = io.stdout;
    var rootPath = result.rest[0];
    out.writeln('Analyzing root: "$rootPath"');

    var computer = FlutterMetricsComputer();
    var stopwatch = Stopwatch()..start();
    await computer.compute(rootPath);
    stopwatch.stop();
    var duration = Duration(milliseconds: stopwatch.elapsedMilliseconds);
    out.writeln();
    out.writeln('Analysis performed in $duration');
    computer.writeResults(out);
    await out.flush();
  }
  io.exit(0);
}

/// Create a parser that can be used to parse the command-line arguments.
ArgParser createArgParser() {
  var parser = ArgParser();
  parser.addOption('help', abbr: 'h', help: 'Print this help message.');
  return parser;
}

/// Print usage information for this tool.
void printUsage(ArgParser parser, {String? error}) {
  if (error != null) {
    print(error);
    print('');
  }
  print('usage: dart flutter_metrics.dart [options] packagePath');
  print('');
  print('Compute and print information about flutter packages.');
  print('');
  print(parser.usage);
}

/// Return `true` if the command-line arguments (represented by the [result] and
/// parsed by the [parser]) are valid.
bool validArguments(ArgParser parser, ArgResults result) {
  if (result.wasParsed('help')) {
    printUsage(parser);
    return false;
  } else if (result.rest.length != 1) {
    printUsage(parser, error: 'No directory path specified.');
    return false;
  }
  var rootPath = result.rest[0];
  if (!io.Directory(rootPath).existsSync()) {
    printUsage(parser, error: 'The directory "$rootPath" does not exist.');
    return false;
  }
  return true;
}

/// An object that records the data as it is being computed.
class FlutterData {
  /// The total number of widget creation expressions found.
  int totalWidgetCount = 0;

  /// A table mapping the name of a widget class to the number of times in
  /// which an instance of that class is created.
  Map<String, int> widgetCounts = {};

  /// A table mapping the name of a widget class and the name of the parent
  /// widget to the number of times the widget was created as a child of the
  /// parent.
  Map<String, Map<String, int>> parentData = {};

  /// A table mapping the name of the parent widget and the name of a widget
  /// class to the number of times the parent had a widget of the given kind.
  Map<String, Map<String, int>> childData = {};

  /// Initialize a newly created set of data to be empty.
  FlutterData();

  /// Record that an instance of the [childWidget] was created. If the instance
  /// creation expression is an argument in another widget constructor
  /// invocation, then the [parentWidget] is the name of the enclosing class.
  void recordWidgetCreation(String childWidget, String? parentWidget) {
    totalWidgetCount++;
    widgetCounts[childWidget] = (widgetCounts[childWidget] ?? 0) + 1;

    if (parentWidget != null) {
      var parentMap = parentData.putIfAbsent(childWidget, () => {});
      parentMap[parentWidget] = (parentMap[parentWidget] ?? 0) + 1;

      var childMap = childData.putIfAbsent(parentWidget, () => {});
      childMap[childWidget] = (childMap[childWidget] ?? 0) + 1;
    }
  }
}

/// An object that visits a compilation unit in order to record the data being
/// collected.
class FlutterDataCollector extends RecursiveAstVisitor<void> {
  /// The data being collected.
  final FlutterData data;

  /// The name of the most deeply widget class whose constructor invocation we
  /// are within.
  String? parentWidget;

  /// Initialize a newly created collector to add data points to the given
  /// [data].
  FlutterDataCollector(this.data);

  @override
  void visitInstanceCreationExpression(InstanceCreationExpression node) {
    var previousParentWidget = parentWidget;
    if (node.isWidgetCreation) {
      var element = node.constructorName.element;
      if (element == null) {
        throw StateError(
          'Unresolved constructor name: ${node.constructorName}',
        );
      }
      var childWidget = element.enclosingElement.name3!;
      var library = element.library2;
      if (!library.uri.toString().startsWith('package:flutter/')) {
        childWidget = 'user-defined';
      }
      data.recordWidgetCreation(childWidget, parentWidget);
      parentWidget = childWidget;
    }
    super.visitInstanceCreationExpression(node);
    parentWidget = previousParentWidget;
  }
}

/// An object used to compute metrics for a single file or directory.
class FlutterMetricsComputer {
  /// The data that was computed.
  final FlutterData data = FlutterData();

  /// Initialize a newly created metrics computer that can compute the metrics
  /// in one or more files and directories.
  FlutterMetricsComputer();

  /// Compute the metrics for the file(s) in the [rootPath].
  Future<void> compute(String rootPath) async {
    var collection = AnalysisContextCollection(
      includedPaths: [rootPath],
      resourceProvider: PhysicalResourceProvider.INSTANCE,
    );
    var collector = FlutterDataCollector(data);
    for (var context in collection.contexts) {
      await _computeInContext(context.contextRoot, collector);
    }
  }

  /// Write a report of the metrics that were computed to the [sink].
  void writeResults(StringSink sink) {
    _writeWidgetCounts(sink);
    _writeChildData(sink);
    _writeParentData(sink);
  }

  /// Compute the metrics for the files in the context [root], creating a
  /// separate context collection to prevent accumulating memory. The metrics
  /// should be captured in the [collector].
  Future<void> _computeInContext(
    ContextRoot root,
    FlutterDataCollector collector,
  ) async {
    // Create a new collection to avoid consuming large quantities of memory.
    var collection = AnalysisContextCollection(
      includedPaths: root.includedPaths.toList(),
      excludedPaths: root.excludedPaths.toList(),
      resourceProvider: PhysicalResourceProvider.INSTANCE,
    );
    var context = collection.contexts[0];
    var pathContext = context.contextRoot.resourceProvider.pathContext;
    for (var filePath in context.contextRoot.analyzedFiles()) {
      if (file_paths.isDart(pathContext, filePath)) {
        try {
          var resolvedUnitResult = await context.currentSession.getResolvedUnit(
            filePath,
          );
          //
          // Check for errors that cause the file to be skipped.
          //
          if (resolvedUnitResult is! ResolvedUnitResult) {
            print('');
            print('File $filePath skipped because it could not be analyzed.');
            continue;
          } else if (hasError(resolvedUnitResult)) {
            print('');
            print('File $filePath skipped due to errors:');
            for (var error in resolvedUnitResult.errors) {
              print('  ${error.toString()}');
            }
            continue;
          }

          resolvedUnitResult.unit.accept(collector);
        } catch (exception, stackTrace) {
          print('');
          print('Exception caught analyzing: "$filePath"');
          print(exception);
          print(stackTrace);
        }
      }
    }
  }

  /// Compute and format a percentage for the fraction [value] / [total].
  String _formatPercent(int value, int total) {
    var percent = ((value / total) * 100).toStringAsFixed(1);
    if (percent.length == 3) {
      percent = '  $percent';
    } else if (percent.length == 4) {
      percent = ' $percent';
    }
    return percent;
  }

  /// Write the child data to the [sink].
  void _writeChildData(StringSink sink) {
    sink.writeln();
    sink.writeln('The number of times a widget had a given child.');
    _writeStructureData(sink, data.childData);
  }

  /// Write the parent data to the [sink].
  void _writeParentData(StringSink sink) {
    sink.writeln();
    sink.writeln('The number of times a widget had a given parent.');
    _writeStructureData(sink, data.parentData);
  }

  /// Write the structure data in the [structureMap] to the [sink].
  void _writeStructureData(
    StringSink sink,
    Map<String, Map<String, int>> structureMap,
  ) {
    var outerEntries = structureMap.entries.toList();
    outerEntries.sort((first, second) => first.key.compareTo(second.key));
    for (var outerEntry in outerEntries) {
      var outerKey = outerEntry.key;
      sink.writeln(outerKey);
      var innerMap = outerEntry.value;
      var entries = innerMap.entries.toList();
      entries.sort((first, second) => second.value.compareTo(first.value));
      var total = entries.fold<int>(
        0,
        (previousValue, entry) => previousValue + entry.value,
      );
      for (var entry in entries) {
        var percent = _formatPercent(entry.value, total);
        sink.writeln('  $percent%: ${entry.key} (${entry.value})');
      }
    }
  }

  /// Write the widget count data to the [sink].
  void _writeWidgetCounts(StringSink sink) {
    sink.writeln();
    sink.writeln('Widget classes by frequency of instantiation');

    var total = data.totalWidgetCount;
    var entries = data.widgetCounts.entries.toList();
    entries.sort((first, second) => second.value.compareTo(first.value));
    for (var entry in entries) {
      var percent = _formatPercent(entry.value, total);
      sink.writeln('  $percent%: ${entry.key} (${entry.value})');
    }
  }

  /// Return `true` if the [result] contains an error.
  static bool hasError(ResolvedUnitResult result) {
    for (var error in result.errors) {
      if (error.severity == Severity.error) {
        return true;
      }
    }
    return false;
  }
}
