// Copyright (c) 2019, 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:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/lsp/constants.dart';
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
import 'package:analysis_server/src/lsp/mapping.dart';
import 'package:analysis_server/src/services/refactoring/refactoring.dart';

class PrepareRenameHandler
    extends MessageHandler<TextDocumentPositionParams, RangeAndPlaceholder> {
  PrepareRenameHandler(LspAnalysisServer server) : super(server);
  Method get handlesMessage => Method.textDocument_prepareRename;

  @override
  TextDocumentPositionParams convertParams(Map<String, dynamic> json) =>
      TextDocumentPositionParams.fromJson(json);

  @override
  Future<ErrorOr<RangeAndPlaceholder>> handle(
      TextDocumentPositionParams params) async {
    final pos = params.position;
    final path = pathOfDoc(params.textDocument);
    final unit = await path.mapResult(requireUnit);
    final offset = await unit.mapResult((unit) => toOffset(unit.lineInfo, pos));

    return offset.mapResult((offset) async {
      final node = await server.getNodeAtOffset(path.result, offset);
      final element = server.getElementOfNode(node);
      if (node == null || element == null) {
        return success(null);
      }

      final refactorDetails =
          RenameRefactoring.getElementToRename(node, element);
      final refactoring = new RenameRefactoring(server.refactoringWorkspace,
          unit.result.session, refactorDetails.element);

      // Check the rename is valid here.
      final initStatus = await refactoring.checkInitialConditions();
      if (initStatus.hasFatalError) {
        return error(
            ServerErrorCodes.RenameNotValid, initStatus.problem.message, null);
      }

      return success(new RangeAndPlaceholder(
        toRange(
          unit.result.lineInfo,
          // If the offset is set to -1 it means there is no location for the
          // old name. However since we must provide a range for LSP, we'll use
          // a 0-character span at the originally requested location to ensure
          // it's valid.
          refactorDetails.offset == -1 ? offset : refactorDetails.offset,
          refactorDetails.length,
        ),
        refactoring.oldName,
      ));
    });
  }
}

class RenameHandler extends MessageHandler<RenameParams, WorkspaceEdit> {
  RenameHandler(LspAnalysisServer server) : super(server);

  Method get handlesMessage => Method.textDocument_rename;

  @override
  RenameParams convertParams(Map<String, dynamic> json) =>
      RenameParams.fromJson(json);

  @override
  Future<ErrorOr<WorkspaceEdit>> handle(RenameParams params) async {
    final pos = params.position;
    final path = pathOfDoc(params.textDocument);
    // If the client provided us a version doc identifier, we'll use it to ensure
    // we're not computing a rename for an old document. If not, we'll just assume
    // the version the server had at the time of recieving the request is valid
    // and then use it to verify the document hadn't changed again before we
    // send the edits.
    final docIdentifier = await path.mapResult((path) => success(
        params.textDocument is VersionedTextDocumentIdentifier
            ? params.textDocument
            : server.getVersionedDocumentIdentifier(path)));
    final unit = await path.mapResult(requireUnit);
    final offset = await unit.mapResult((unit) => toOffset(unit.lineInfo, pos));

    return offset.mapResult((offset) async {
      final node = await server.getNodeAtOffset(path.result, offset);
      final element = server.getElementOfNode(node);
      if (node == null || element == null) {
        return success(null);
      }

      final refactorDetails =
          RenameRefactoring.getElementToRename(node, element);
      final refactoring = new RenameRefactoring(server.refactoringWorkspace,
          unit.result.session, refactorDetails.element);

      // TODO(dantup): Consider using window/showMessageRequest to prompt
      // the user to see if they'd like to proceed with a rename if there
      // are non-fatal errors or warnings. For now we will reject all errors
      // (fatal and not) as this seems like the most logical behaviour when
      // without a prompt.

      // Check the rename is valid here.
      final initStatus = await refactoring.checkInitialConditions();
      if (initStatus.hasError) {
        return error(
            ServerErrorCodes.RenameNotValid, initStatus.problem.message, null);
      }

      // Check the name is valid.
      refactoring.newName = params.newName;
      final optionsStatus = refactoring.checkNewName();
      if (optionsStatus.hasError) {
        return error(ServerErrorCodes.RenameNotValid,
            optionsStatus.problem.message, null);
      }

      // Final validation.
      final finalStatus = await refactoring.checkFinalConditions();
      if (finalStatus.hasError) {
        return error(
            ServerErrorCodes.RenameNotValid, finalStatus.problem.message, null);
      }

      // Compute the actual change.
      final change = await refactoring.createChange();

      // Before we send anything back, ensure the original file didn't change
      // while we were computing changes.
      if (server.getVersionedDocumentIdentifier(path.result) !=
          docIdentifier.result) {
        return error(ErrorCodes.ContentModified,
            'Document was modified while rename was being computed', null);
      }

      final workspaceEdit = createWorkspaceEdit(server, change);
      return success(workspaceEdit);
    });
  }
}
