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

  Method get handlesMessage => Method.textDocument_didClose;

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

  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;

  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, 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] = 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.');
          }
        }
      }

      server.addPriorityFile(path);

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