// 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> {
  /// Whether analysis roots are based on open files and should be updated.
  bool updateAnalysisRoots;

  TextDocumentCloseHandler(LspAnalysisServer server, this.updateAnalysisRoots)
      : 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);

      if (updateAnalysisRoots) {
        // If there are no other open files in this context, we can remove it
        // from the analysis roots.
        final contextFolder = server.contextManager.getContextFolderFor(path);
        var hasOtherFilesInContext = false;
        for (var otherDocPath in server.documentVersions.keys) {
          if (server.contextManager.getContextFolderFor(otherDocPath) ==
              contextFolder) {
            hasOtherFilesInContext = true;
            break;
          }
        }
        if (!hasOtherFilesInContext) {
          final projectFolder =
              _findProjectFolder(server.resourceProvider, path);
          server.updateAnalysisRoots([], [projectFolder]);
        }
      }

      return success();
    });
  }
}

class TextDocumentOpenHandler
    extends MessageHandler<DidOpenTextDocumentParams, void> {
  /// Whether analysis roots are based on open files and should be updated.
  bool updateAnalysisRoots;

  DateTime lastSentAnalyzeOpenFilesWarnings;

  TextDocumentOpenHandler(LspAnalysisServer server, this.updateAnalysisRoots)
      : 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(
        params.textDocument.version,
        params.textDocument.uri,
      );
      server.onOverlayCreated(path, doc.text);

      final driver = server.contextManager.getDriverFor(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);

      // If there was no current driver for this file, then we may need to add
      // its project folder as an analysis root.
      if (updateAnalysisRoots && driver == null) {
        final projectFolder = _findProjectFolder(server.resourceProvider, path);
        if (projectFolder != null) {
          server.updateAnalysisRoots([projectFolder], []);
        } else {
          // There was no pubspec - ideally we should add just the file
          // here but we don't currently support that.
          // https://github.com/dart-lang/sdk/issues/32256

          // Send a warning to the user, but only if we haven't already in the
          // last 60 seconds.
          if (lastSentAnalyzeOpenFilesWarnings == null ||
              (DateTime.now()
                      .difference(lastSentAnalyzeOpenFilesWarnings)
                      .inSeconds >
                  60)) {
            lastSentAnalyzeOpenFilesWarnings = DateTime.now();
            server.showMessageToUser(
                MessageType.Warning,
                'When using onlyAnalyzeProjectsWithOpenFiles, files opened that '
                'are not contained within project folders containing pubspec.yaml, '
                '.packages or BUILD files will not be analyzed.');
          }
        }
      }

      server.addPriorityFile(path);

      return success();
    });
  }
}
