// Copyright (c) 2018, 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:async';

import 'package:analysis_server/src/services/completion/completion_core.dart';
import 'package:analysis_server/src/services/completion/completion_performance.dart';
import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
import 'package:analysis_server/src/utilities/null_string_sink.dart';
import 'package:analyzer/dart/analysis/analysis_context.dart';
import 'package:analyzer/dart/analysis/analysis_context_collection.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/file_system/overlay_file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';

/**
 * A runner that can request code completion at the location of each identifier
 * in a Dart file.
 */
class CompletionRunner {
  /**
   * The sink to which output is to be written.
   */
  final StringSink output;

  /**
   * A flag indicating whether to produce output about missing suggestions.
   */
  final bool printMissing;

  /**
   * A flag indicating whether to produce timing information.
   */
  final bool timing;

  /**
   * A flag indicating whether to use the CFE when running the tests.
   */
  final bool useCFE;

  /**
   * A flag indicating whether to produce verbose output.
   */
  final bool verbose;

  /**
   * A flag indicating whether we should delete each identifier before
   * attempting to complete at that offset.
   */
  bool deleteBeforeCompletion = false;

  /**
   * Initialize a newly created completion runner.
   */
  CompletionRunner(
      {StringSink output,
      bool printMissing,
      bool timing,
      bool useCFE,
      bool verbose})
      : this.output = output ?? new NullStringSink(),
        this.printMissing = printMissing ?? false,
        this.timing = timing ?? false,
        this.useCFE = useCFE ?? false,
        this.verbose = verbose ?? false;

  /**
   * Test the completion engine at the locations of each of the identifiers in
   * each of the files in the given [analysisRoot].
   */
  Future<void> runAll(String analysisRoot) async {
    OverlayResourceProvider resourceProvider =
        new OverlayResourceProvider(PhysicalResourceProvider.INSTANCE);
    AnalysisContextCollection collection = new AnalysisContextCollection(
        includedPaths: <String>[analysisRoot],
        resourceProvider: resourceProvider,
        useCFE: useCFE); // ignore: deprecated_member_use
    DartCompletionManager contributor = new DartCompletionManager();
    CompletionPerformance performance = new CompletionPerformance();
    int stamp = 1;

    int fileCount = 0;
    int identifierCount = 0;
    int missingCount = 0;

    // Consider getting individual timings so that we can also report the
    // longest and shortest times, or even a distribution.
    Stopwatch timer = new Stopwatch();

    for (AnalysisContext context in collection.contexts) {
      for (String path in context.contextRoot.analyzedFiles()) {
        fileCount++;
        output.write('.');
        ResolveResult result =
            await context.currentSession.getResolvedAst(path);
        String content = result.content;
        LineInfo lineInfo = result.lineInfo;
        List<SimpleIdentifier> identifiers = _identifiersIn(result.unit);

        for (SimpleIdentifier identifier in identifiers) {
          identifierCount++;
          int offset = identifier.offset;
          if (deleteBeforeCompletion) {
            String modifiedContent = content.substring(0, offset) +
                content.substring(identifier.end);
            resourceProvider.setOverlay(path,
                content: modifiedContent, modificationStamp: stamp++);
            result = await context.currentSession.getResolvedAst(path);
          }

          timer.start();
          CompletionRequestImpl request =
              new CompletionRequestImpl(result, offset, performance);
          List<CompletionSuggestion> suggestions =
              await contributor.computeSuggestions(request);
          timer.stop();

          if (!identifier.inDeclarationContext() &&
              !_isNamedExpressionName(identifier)) {
            if (!_hasSuggestion(suggestions, identifier.name)) {
              missingCount++;
              if (printMissing) {
                CharacterLocation location = lineInfo.getLocation(offset);
                output.writeln('Missing suggestion of "${identifier.name}" at '
                    '$path:${location.lineNumber}:${location.columnNumber}');
                if (verbose) {
                  _printSuggestions(suggestions);
                }
              }
            }
          }
        }
        if (deleteBeforeCompletion) {
          resourceProvider.removeOverlay(path);
        }
      }
    }
    output.writeln();
    if (printMissing) {
      output.writeln();
    }
    if (identifierCount == 0) {
      output.writeln('No identifiers found in $fileCount files');
    } else {
      int percent = (missingCount * 100 / identifierCount).round();
      output.writeln('$percent% missing suggestions '
          '($missingCount of $identifierCount in $fileCount files)');
    }
    if (timing && identifierCount > 0) {
      int time = timer.elapsedMilliseconds;
      int averageTime = (time / identifierCount).round();
      output.writeln('completion took $time ms, '
          'which is an average of $averageTime ms per completion');
    }
  }

  /**
   * Return `true` if the given list of [suggestions] includes a suggestion for
   * the given [identifier].
   */
  bool _hasSuggestion(
      List<CompletionSuggestion> suggestions, String identifier) {
    for (CompletionSuggestion suggestion in suggestions) {
      if (suggestion.completion == identifier) {
        return true;
      }
    }
    return false;
  }

  /**
   * Return a list containing information about the identifiers in the given
   * compilation [unit].
   */
  List<SimpleIdentifier> _identifiersIn(CompilationUnit unit) {
    IdentifierCollector visitor = new IdentifierCollector();
    unit.accept(visitor);
    return visitor.identifiers;
  }

  /**
   * Return `true` if the given [identifier] is being used as the name of a
   * named expression.
   */
  bool _isNamedExpressionName(SimpleIdentifier identifier) {
    AstNode parent = identifier.parent;
    return parent is NamedExpression && parent.name == identifier;
  }

  /**
   * Print information about the given [suggestions].
   */
  void _printSuggestions(List<CompletionSuggestion> suggestions) {
    if (suggestions.length == 0) {
      output.writeln('  No suggestions');
      return;
    }
    output.writeln('  Suggestions:');
    for (CompletionSuggestion suggestion in suggestions) {
      output.writeln('    ${suggestion.completion}');
    }
  }
}

/**
 * A visitor that will collect simple identifiers in the AST being visited.
 */
class IdentifierCollector extends RecursiveAstVisitor<void> {
  /**
   * The simple identifiers that were collected.
   */
  final List<SimpleIdentifier> identifiers = <SimpleIdentifier>[];

  @override
  visitSimpleIdentifier(SimpleIdentifier node) {
    identifiers.add(node);
  }
}
