// 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;

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

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

  ErrorOr<void> handle(DidChangeTextDocumentParams params) {
    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);

  Method get handlesMessage => Method.textDocument_didClose;

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

  ErrorOr<void> handle(DidCloseTextDocumentParams params) {
    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;

  TextDocumentOpenHandler(LspAnalysisServer server, this.updateAnalysisRoots)
      : super(server);

  Method get handlesMessage => Method.textDocument_didOpen;

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

  ErrorOr<void> handle(DidOpenTextDocumentParams params) {
    final doc = params.textDocument;
    final path = pathOfDocItem(doc);
    return path.mapResult((path) {
      server.addPriorityFile(path);
      // We don't get a VersionedTextDocumentIdentifier with a didOpen but we
      // do get the necessary info to create one.
      server.documentVersions[path] = new 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.');
          }
        }
      }

      return success();
    });
  }

  DateTime lastSentAnalyzeOpenFilesWarnings;
}

/// 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;
}
