// 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 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/source/line_info.dart';

import '../scrape.dart';

/// Wire up [visitor] to [scrape] the given [path] containing [source] with
/// [info].
///
/// This is a top-level function instead of an instance method so that we can
/// hide it and not export it from scrape's public API. Only [Scrape] itself
/// should call this. We bind separately instead of passing these through the
/// [ScrapeVisitor] constructor so that subclasses of [ScrapeVisitor] don't
/// need to define a pass-through constructor.
void bindVisitor(ScrapeVisitor visitor, Scrape scrape, String path,
    String source, LineInfo info) {
  visitor._scrape = scrape;
  visitor._path = path;
  visitor._source = source;
  visitor.lineInfo = info;
}

/// Base Visitor class with some utility functionality.
class ScrapeVisitor extends RecursiveAstVisitor<void> {
  // These are initialized by [bindVisitor()].
  late final Scrape _scrape;
  late final String _path;
  late final String _source;
  late final LineInfo lineInfo;

  /// How many levels deep the visitor is currently nested inside build methods.
  int _inFlutterBuildMethods = 0;

  String get path => _path;

  // TODO(rnystrom): Remove this in favor of using surveyor for these kinds of
  // analyses.
  /// Whether the visitor is currently inside Flutter's "build" method,
  /// either directly or nested inside some other function inside one.
  ///
  /// This is only an approximate guess. It assumes a method is a "build"-like
  /// method if it returns "Widget", or has a parameter list that starts with
  /// "BuildContext context".
  bool get isInFlutterBuildMethod => _inFlutterBuildMethods > 0;

  bool _isBuildMethod(
      TypeAnnotation? returnType, FormalParameterList? parameters) {
    var parameterString = parameters.toString();

    if (returnType.toString() == 'void') return false;
    if (parameterString.startsWith('(BuildContext context')) return true;
    if (returnType.toString() == 'Widget') return true;

    return false;
  }

  /// Add an occurrence of [item] to [histogram].
  void record(String histogram, Object item) {
    _scrape.record(histogram, item);
  }

  /// Write [message] to stdout, clearing the current line if needed.
  void log(Object message) {
    _scrape.log(message);
  }

  /// Print a nice representation of [node].
  void printNode(AstNode node) {
    log(nodeToString(node));
  }

  /// Generate a nice string representation of [node] include file path and
  /// line information.
  String nodeToString(AstNode node) {
    var startLine = lineInfo.getLocation(node.offset).lineNumber;
    var endLine = lineInfo.getLocation(node.end).lineNumber;

    startLine = startLine.clamp(0, lineInfo.lineCount - 1);
    endLine = endLine.clamp(0, lineInfo.lineCount - 1);

    var buffer = StringBuffer();
    buffer.writeln('// $path:$startLine');
    for (var line = startLine; line <= endLine; line++) {
      // Note that getLocation() returns 1-based lines, but getOffsetOfLine()
      // expects 0-based.
      var offset = lineInfo.getOffsetOfLine(line - 1);
      // -1 to not include the newline.
      var end = lineInfo.getOffsetOfLine(line) - 1;

      buffer.writeln(_source.substring(offset, end));
    }

    return buffer.toString();
  }

  /// Get the line number of the code at [offset].
  int getLine(int offset) => lineInfo.getLocation(offset).lineNumber;

  /// Override this to execute custom code before visiting a Flutter build
  /// method.
  void beforeVisitBuildMethod(Declaration node) {}

  /// Override this to execute custom code after visiting a Flutter build
  /// method.
  void afterVisitBuildMethod(Declaration node) {}

  @override
  void visitMethodDeclaration(MethodDeclaration node) {
    var isBuild = _isBuildMethod(node.returnType, node.parameters);
    if (isBuild) _inFlutterBuildMethods++;

    try {
      if (isBuild) beforeVisitBuildMethod(node);
      super.visitMethodDeclaration(node);
      if (isBuild) afterVisitBuildMethod(node);
    } finally {
      if (isBuild) _inFlutterBuildMethods--;
    }
  }

  @override
  void visitFunctionDeclaration(FunctionDeclaration node) {
    var isBuild =
        _isBuildMethod(node.returnType, node.functionExpression.parameters);
    if (isBuild) _inFlutterBuildMethods++;

    try {
      if (isBuild) beforeVisitBuildMethod(node);
      super.visitFunctionDeclaration(node);
      if (isBuild) afterVisitBuildMethod(node);
    } finally {
      if (isBuild) _inFlutterBuildMethods--;
    }
  }
}
