// 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/protocol_server.dart'
    show
        CompletionSuggestion,
        RuntimeCompletionExpression,
        RuntimeCompletionVariable,
        SourceEdit;
import 'package:analysis_server/src/provisional/completion/completion_core.dart';
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:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';

class RuntimeCompletionComputer {
  final ResourceProvider resourceProvider;
  final FileContentOverlay fileContentOverlay;
  final AnalysisDriver analysisDriver;

  final String code;
  final int offset;

  final String contextFile;
  final int contextOffset;

  final List<RuntimeCompletionVariable> variables;
  final List<RuntimeCompletionExpression> expressions;

  AnalysisSession session;
  _Context context;

  RuntimeCompletionComputer(
      this.resourceProvider,
      this.fileContentOverlay,
      this.analysisDriver,
      this.code,
      this.offset,
      this.contextFile,
      this.contextOffset,
      this.variables,
      this.expressions);

  Future<RuntimeCompletionResult> compute() async {
    var pathContext = resourceProvider.pathContext;
    var contextDir = pathContext.dirname(contextFile);
    var targetPath = pathContext.join(contextDir, '_runtimeCompletion.dart');

    // TODO(scheglov) Use variables.
    await _initContext();

    String baseTargetCode = r'''
library _runtimeCompletion;
''';
    fileContentOverlay[targetPath] = baseTargetCode;

    const codeMarker = '__code__';

    // Build the target code that provides the same context.
    var changeBuilder = new DartChangeBuilder(session);
    int nextImportPrefixIndex = 0;
    await changeBuilder.addFileEdit(targetPath, (builder) {
      builder.addInsertion(baseTargetCode.length, (builder) {
        builder.writeln('main() {');
        // Write all visible local declarations.
        for (var local in context.locals.values) {
          builder.writeLocalVariableDeclaration(local.name, type: local.type);
          builder.writeln();
        }

        // Write the marker to insert the code being completed.
        builder.write(codeMarker);

        // Finalize main().
        builder.writeln(';');
        builder.writeln('}');
      });
    }, importPrefixGenerator: (uri) => '__prefix${nextImportPrefixIndex++}');

    // Compute the target code.
    List<SourceEdit> targetEdits = changeBuilder.sourceChange.edits[0].edits;
    String targetCode = SourceEdit.applySequence(baseTargetCode, targetEdits);

    // Insert the code being completed.
    int targetOffset = targetCode.indexOf(codeMarker) + offset;
    targetCode = targetCode.replaceAll(codeMarker, code);

    // Resolve the constructed target file.
    AnalysisResult targetResult;
    try {
      fileContentOverlay[targetPath] = targetCode;
      analysisDriver.changeFile(targetPath);
      targetResult = await analysisDriver.getResult(targetPath);
    } finally {
      fileContentOverlay[targetPath] = null;
      analysisDriver.changeFile(targetPath);
    }

    CompletionContributor contributor = new DartCompletionManager();
    CompletionRequestImpl request = new CompletionRequestImpl(
      targetResult,
      targetOffset,
      new CompletionPerformance(),
    );
    var suggestions = await contributor.computeSuggestions(request);

    // TODO(scheglov) Add support for expressions.
    var expressions = <RuntimeCompletionExpression>[];
    return new RuntimeCompletionResult(expressions, suggestions);
  }

  Future<void> _initContext() async {
    var contextResult = await analysisDriver.getResult(contextFile);
    session = contextResult.session;
    context = new _Context(contextResult.unit, contextOffset);
  }
}

/// The result of performing runtime completion.
class RuntimeCompletionResult {
  final List<RuntimeCompletionExpression> expressions;
  final List<CompletionSuggestion> suggestions;

  RuntimeCompletionResult(this.expressions, this.suggestions);
}

/// The context in which completion is performed.
class _Context {
  final int contextOffset;

  ClassElement enclosingClass;
  Map<String, VariableElement> locals = {};

  _Context(CompilationUnit unit, this.contextOffset) {
    var node = new NodeLocator2(contextOffset).searchWithin(unit);

    var enclosingClass = node.getAncestor((n) => n is ClassDeclaration);
    if (enclosingClass is ClassDeclaration) {
      this.enclosingClass = enclosingClass.element;
    }

    _appendLocals(node);
  }

  void _appendLocals(AstNode node) {
    if (node is Block) {
      for (var statement in node.statements) {
        if (statement.offset > contextOffset) {
          break;
        }
        if (statement is VariableDeclarationStatement) {
          _appendVariables(statement.variables);
        }
      }
    } else if (node is ClassDeclaration) {
      // TODO(scheglov) implement, maybe not locals anymore
      return;
    } else if (node is CompilationUnit) {
      return;
    } else if (node is ConstructorDeclaration) {
      _appendParameters(node.parameters);
    } else if (node is FunctionDeclaration) {
      _appendParameters(node.functionExpression.parameters);
    } else if (node is FunctionExpression) {
      _appendParameters(node.parameters);
    } else if (node is ForEachStatement) {
      LocalVariableElement element = node.loopVariable?.element;
      if (element != null) {
        locals[element.name] ??= element;
      }
    } else if (node is ForStatement) {
      _appendVariables(node.variables);
    } else if (node is MethodDeclaration) {
      _appendParameters(node.parameters);
    }
    _appendLocals(node.parent);
  }

  void _appendParameters(FormalParameterList parameters) {
    if (parameters != null) {
      for (var parameter in parameters.parameters) {
        VariableElement element = parameter.element;
        locals[element.name] ??= element;
      }
    }
  }

  void _appendVariables(VariableDeclarationList variables) {
    if (variables != null) {
      for (var variable in variables.variables) {
        VariableElement element = variable.element;
        locals[element.name] ??= element;
      }
    }
  }
}
