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

// @dart = 2.9

import 'dart:convert' show utf8;

import 'dart:io'
    show Directory, File, FileSystemEntity, exitCode, stdin, stdout;

import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;

import 'package:_fe_analyzer_shared/src/scanner/token.dart'
    show CommentToken, Token;

import 'package:front_end/src/api_prototype/compiler_options.dart' as api
    show CompilerOptions, DiagnosticMessage;

import 'package:front_end/src/api_prototype/file_system.dart' as api
    show FileSystem;

import 'package:front_end/src/base/processed_options.dart'
    show ProcessedOptions;

import 'package:front_end/src/compute_platform_binaries_location.dart'
    show computePlatformBinariesLocation;

import 'package:front_end/src/fasta/compiler_context.dart' show CompilerContext;

import 'package:front_end/src/fasta/dill/dill_target.dart' show DillTarget;

import 'package:front_end/src/fasta/incremental_compiler.dart'
    show IncrementalCompiler, IncrementalKernelTarget;

import 'package:front_end/src/fasta/kernel/kernel_target.dart'
    show KernelTarget;

import 'package:front_end/src/fasta/source/source_library_builder.dart'
    show SourceLibraryBuilder;

import 'package:front_end/src/fasta/source/source_loader.dart'
    show SourceLoader;

import 'package:front_end/src/fasta/uri_translator.dart' show UriTranslator;

import 'package:kernel/ast.dart';

import 'package:kernel/target/targets.dart' show TargetFlags;

import "package:vm/target/vm.dart" show VmTarget;

import "utils/io_utils.dart" show computeRepoDirUri;

final Uri repoDir = computeRepoDirUri();

Set<Uri> libUris = {};

Component component;

Future<void> main(List<String> args) async {
  api.CompilerOptions compilerOptions = getOptions();

  Uri dotPackagesUri = repoDir.resolve(".packages");
  if (!new File.fromUri(dotPackagesUri).existsSync()) {
    throw "Couldn't find .packages";
  }
  compilerOptions.packagesFileUri = dotPackagesUri;

  ProcessedOptions options = new ProcessedOptions(options: compilerOptions);

  libUris.add(repoDir.resolve("pkg/_fe_analyzer_shared/lib/src/parser"));
  libUris.add(repoDir.resolve("pkg/_fe_analyzer_shared/lib/src/scanner"));
  for (Uri uri in libUris) {
    List<FileSystemEntity> entities =
        new Directory.fromUri(uri).listSync(recursive: true);
    for (FileSystemEntity entity in entities) {
      if (entity is File && entity.path.endsWith(".dart")) {
        options.inputs.add(entity.uri);
      }
    }
  }
  CompilerContext context = new CompilerContext(options);
  IncrementalCompiler incrementalCompiler =
      new TestIncrementalCompiler(context);
  component = await incrementalCompiler.computeDelta();

  for (Library library in component.libraries) {
    if (library.importUri.scheme == "dart") continue;
    // This isn't perfect because of parts, but (for now) it'll do.
    for (Uri uri in libUris) {
      if (library.fileUri.toString().startsWith(uri.toString())) {
        library.accept(new InvocationVisitor());
        break;
      }
    }
  }

  if (args.isNotEmpty && args[0] == "--interactive") {
    List<Uri> editsPerformed = [];
    for (Uri uri in edits.keys) {
      print("\n\n\n");
      if (edits[uri] != null && edits[uri].isNotEmpty) {
        String update;
        while (update != "y" &&
            update != "yes" &&
            update != "n" &&
            update != "no") {
          print("Do you want to update $uri? (y/n)");
          update = stdin.readLineSync();
        }
        if (update != "y" && update != "yes") continue;

        List<Edit> theseEdits = edits[uri];
        theseEdits.sort((a, b) => a.offset - b.offset);
        String content = utf8.decode(component.uriToSource[uri].source,
            allowMalformed: true);
        StringBuffer sb = new StringBuffer();
        int latest = 0;
        for (Edit edit in theseEdits) {
          sb.write(content.substring(latest, edit.offset));
          sb.write(edit.insertData);
          latest = edit.offset;
        }
        sb.write(content.substring(latest, content.length));
        new File.fromUri(uri).writeAsStringSync(sb.toString());
        editsPerformed.add(uri);
      }
    }
    if (editsPerformed.isNotEmpty) {
      print("\n\nYou should now probably run something like\n\n");
      stdout.write(r"tools/sdks/dart-sdk/bin/dartfmt -w");
      for (Uri uri in editsPerformed) {
        File f = new File.fromUri(uri);
        Directory relative = new Directory.fromUri(Uri.base.resolve("."));
        if (!f.path.startsWith(relative.path)) {
          throw "${f.path} vs ${relative.path}";
        }
        String relativePath = f.path.substring(relative.path.length);
        stdout.write(" ${relativePath}");
      }
      stdout.write("\n\n");
    }
  }

  if (edits.isNotEmpty) {
    exitCode = 1;
  }

  int totalSuggestedEdits = edits.values
      .fold(0, (previousValue, element) => previousValue + element.length);
  print("Done. Suggested ${totalSuggestedEdits} edits "
      "in ${edits.length} files.");
}

int errorCount = 0;

api.CompilerOptions getOptions() {
  // Compile sdk because when this is run from a lint it uses the checked-in sdk
  // and we might not have a suitable compiled platform.dill file.
  Uri sdkRoot = computePlatformBinariesLocation(forceBuildDir: true);
  api.CompilerOptions options = new api.CompilerOptions()
    ..sdkRoot = sdkRoot
    ..compileSdk = true
    ..target = new VmTarget(new TargetFlags())
    ..librariesSpecificationUri = repoDir.resolve("sdk/lib/libraries.json")
    ..omitPlatform = true
    ..onDiagnostic = (api.DiagnosticMessage message) {
      if (message.severity == Severity.error) {
        print(message.plainTextFormatted.join('\n'));
        errorCount++;
      }
    }
    ..environmentDefines = const {};
  return options;
}

class InvocationVisitor extends RecursiveVisitor {
  void visitProcedure(Procedure node) {
    if (node.isNoSuchMethodForwarder) return;
    super.visitProcedure(node);
  }

  void visitMethodInvocation(MethodInvocation node) {
    super.visitMethodInvocation(node);
    if (node.interfaceTargetReference?.node != null) {
      note(node.interfaceTargetReference?.node, node.arguments, node);
    }
  }

  void visitSuperMethodInvocation(SuperMethodInvocation node) {
    super.visitSuperMethodInvocation(node);
    note(node.interfaceTargetReference.node, node.arguments, node);
  }

  void visitStaticInvocation(StaticInvocation node) {
    super.visitStaticInvocation(node);
    note(node.targetReference.node, node.arguments, node);
  }

  void visitConstructorInvocation(ConstructorInvocation node) {
    super.visitConstructorInvocation(node);
    note(node.targetReference.node, node.arguments, node);
  }

  void note(
      NamedNode node, Arguments arguments, InvocationExpression invocation) {
    List<VariableDeclaration> positionalParameters;
    if (node is Procedure) {
      positionalParameters = node.function.positionalParameters;
    } else if (node is Constructor) {
      positionalParameters = node.function.positionalParameters;
    } else {
      throw "Unexpected node: ${node.runtimeType}";
    }

    for (int i = 0; i < arguments.positional.length; i++) {
      bool wantComment = false;
      if (arguments.positional[i] is NullLiteral ||
          arguments.positional[i] is BoolLiteral ||
          arguments.positional[i] is IntLiteral) {
        wantComment = true;
      } else if (arguments.positional[i] is MapLiteral) {
        MapLiteral literal = arguments.positional[i];
        if (literal.entries.isEmpty) wantComment = true;
      } else if (arguments.positional[i] is ListLiteral) {
        ListLiteral literal = arguments.positional[i];
        if (literal.expressions.isEmpty) wantComment = true;
      } else if (arguments.positional[i] is MethodInvocation) {
        MethodInvocation methodInvocation = arguments.positional[i];
        if (methodInvocation.receiver is NullLiteral ||
            methodInvocation.receiver is IntLiteral ||
            methodInvocation.receiver is BoolLiteral) {
          wantComment = true;
        }
      }
      if (wantComment) {
        check(arguments.positional[i], i, positionalParameters[i], node,
            "/* ${positionalParameters[i].name} = */");
      }
    }
  }
}

Map<Uri, Token> cache = {};

void check(
    Expression argumentExpression,
    int parameterNumber,
    VariableDeclaration parameter,
    NamedNode targetNode,
    String expectedComment) {
  if (targetNode is Procedure && targetNode.kind == ProcedureKind.Operator) {
    // Operator calls doesn't look like 'regular' method calls.
    return;
  }
  if (argumentExpression.fileOffset == -1) return;
  Location location = argumentExpression.location;
  Token token = cache[location.file];
  while (token.offset != argumentExpression.fileOffset) {
    token = token.next;
    if (token.isEof) {
      throw "Couldn't find token for $argumentExpression "
          "(${argumentExpression.fileOffset}).";
    }
  }
  bool foundComment = false;
  CommentToken commentToken = token.precedingComments;
  while (commentToken != null) {
    if (commentToken.lexeme == expectedComment) {
      // Exact match.
      foundComment = true;
      break;
    }
    if (commentToken.lexeme.replaceAll(" ", "") ==
        expectedComment.replaceAll(" ", "")) {
      // Close enough.
      foundComment = true;
      break;
    }
    commentToken = commentToken.next;
  }
  if (foundComment) {
    return;
  }
  Location calculatedLocation =
      component.getLocation(location.file, token.offset);
  print("Please add comment $expectedComment at "
      "${token.offset} => "
      "${calculatedLocation}");
  edits[location.file] ??= [];
  edits[location.file].add(new Edit(token.offset, expectedComment));
}

Map<Uri, List<Edit>> edits = {};

class Edit {
  final int offset;
  final String insertData;
  Edit(this.offset, this.insertData);
}

class TestIncrementalCompiler extends IncrementalCompiler {
  TestIncrementalCompiler(CompilerContext context) : super(context);

  IncrementalKernelTarget createIncrementalKernelTarget(
      api.FileSystem fileSystem,
      bool includeComments,
      DillTarget dillTarget,
      UriTranslator uriTranslator) {
    return new TestIncrementalKernelTarget(
        fileSystem, /* includeComments = */ true, dillTarget, uriTranslator);
  }
}

class TestIncrementalKernelTarget extends IncrementalKernelTarget {
  TestIncrementalKernelTarget(api.FileSystem fileSystem, bool includeComments,
      DillTarget dillTarget, UriTranslator uriTranslator)
      : super(fileSystem, includeComments, dillTarget, uriTranslator);

  SourceLoader createLoader() =>
      new TestSourceLoader(fileSystem, includeComments, this);

  void runBuildTransformations() {
    // Don't do any transformations!
  }
}

class TestSourceLoader extends SourceLoader {
  TestSourceLoader(
      api.FileSystem fileSystem, bool includeComments, KernelTarget target)
      : super(fileSystem, includeComments, target);

  Future<Token> tokenize(SourceLibraryBuilder library,
      {bool suppressLexicalErrors: false}) async {
    Token result = await super
        .tokenize(library, suppressLexicalErrors: suppressLexicalErrors);
    cache[library.fileUri] = result;
    return result;
  }
}
