// 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 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/context_manager.dart'
    show ContextManagerImpl;
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/lsp/source_edits.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:path/path.dart' show dirname, join;

/// Finds the nearest ancestor to [filePath] that contains a pubspec/.packages/build file.
String _findProjectFolder(ResourceProvider resourceProvider, String filePath) {
  // TODO(dantup): Is there something we can reuse for this?
  var folder = dirname(filePath);
  while (folder != dirname(folder)) {
    final pubspec =
        resourceProvider.getFile(join(folder, ContextManagerImpl.PUBSPEC_NAME));
    final packages = resourceProvider
        .getFile(join(folder, ContextManagerImpl.PACKAGE_SPEC_NAME));
    final build = resourceProvider.getFile(join(folder, 'BUILD'));

    if (pubspec.exists || packages.exists || build.exists) {
      return folder;
    }
    folder = dirname(folder);
  }
  return null;
}

class TextDocumentChangeHandler
    extends MessageHandler<DidChangeTextDocumentParams, void> {
  TextDocumentChangeHandler(LspAnalysisServer server) : super(server);
  @override
  Method get handlesMessage => Method.textDocument_didChange;

  @override
  LspJsonHandler<DidChangeTextDocumentParams> get jsonHandler =>
      DidChangeTextDocumentParams.jsonHandler;

  @override
  ErrorOr<void> handle(
      DidChangeTextDocumentParams params, CancellationToken token) {
    final path = pathOfDoc(params.textDocument);
    return path.mapResult((path) => _changeFile(path, params));
  }

  ErrorOr<void> _changeFile(String path, DidChangeTextDocumentParams params) {
    String oldContents;
    if (server.resourceProvider.hasOverlay(path)) {
      oldContents = server.resourceProvider.getFile(path).readAsStringSync();
    }
    // If we didn't have the file contents, the server and client are out of sync
    // and this is a serious failure.
    if (oldContents == null) {
      return error(
        ServerErrorCodes.ClientServerInconsistentState,
        'Unable to edit document because the file was not previously opened: $path',
        null,
      );
    }
    final newContents = applyAndConvertEditsToServer(
        oldContents, params.contentChanges,
        failureIsCritical: true);
    return newContents.mapResult((result) {
      server.documentVersions[path] = params.textDocument;
      server.onOverlayUpdated(path, result.last, newContent: result.first);
      return success();
    });
  }
}

class TextDocumentCloseHandler
    extends MessageHandler<DidCloseTextDocumentParams, void> {
  TextDocumentCloseHandler(LspAnalysisServer server) : super(server);

  @override
  Method get handlesMessage => Method.textDocument_didClose;

  @override
  LspJsonHandler<DidCloseTextDocumentParams> get jsonHandler =>
      DidCloseTextDocumentParams.jsonHandler;

  @override
  ErrorOr<void> handle(
      DidCloseTextDocumentParams params, CancellationToken token) {
    final path = pathOfDoc(params.textDocument);
    return path.mapResult((path) {
      server.removePriorityFile(path);
      server.documentVersions.remove(path);
      server.onOverlayDestroyed(path);
      server.removeTemporaryAnalysisRoot(path);

      return success();
    });
  }
}

class TextDocumentOpenHandler
    extends MessageHandler<DidOpenTextDocumentParams, void> {
  TextDocumentOpenHandler(LspAnalysisServer server) : super(server);

  @override
  Method get handlesMessage => Method.textDocument_didOpen;

  @override
  LspJsonHandler<DidOpenTextDocumentParams> get jsonHandler =>
      DidOpenTextDocumentParams.jsonHandler;

  @override
  ErrorOr<void> handle(
      DidOpenTextDocumentParams params, CancellationToken token) {
    final doc = params.textDocument;
    final path = pathOfDocItem(doc);
    return path.mapResult((path) {
      // We don't get a VersionedTextDocumentIdentifier with a didOpen but we
      // do get the necessary info to create one.
      server.documentVersions[path] = VersionedTextDocumentIdentifier(
        version: params.textDocument.version,
        uri: params.textDocument.uri,
      );
      server.onOverlayCreated(path, doc.text);

      final driver = server.getAnalysisDriver(path);
      // If the file did not exist, and is "overlay only", it still should be
      // analyzed. Add it to driver to which it should have been added.

      driver?.addFile(path);

      // Figure out the best analysis root for this file and register it as a temporary
      // analysis root. We need to register it even if we found a driver, so that if
      // the driver existed only because of another open file, it will not be removed
      // when that file is closed.
      final analysisRoot = driver?.contextRoot?.root ??
          _findProjectFolder(server.resourceProvider, path) ??
          dirname(path);
      if (analysisRoot != null) {
        server.addTemporaryAnalysisRoot(path, analysisRoot);
      }

      server.addPriorityFile(path);

      return success();
    });
  }
}
