// 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 =
        applyEdits(oldContents, params.contentChanges, failureIsCritical: true);
    return newContents.mapResult((newcontents) {
      server.documentVersions[path] = params.textDocument;
      server.updateOverlay(path, newContents.result);
      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.updateOverlay(path, null);

      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.updateOverlay(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();
    });
  }
}
