// Copyright (c) 2020, 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 'dart:async';

import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/computer/computer_highlights.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/semantic_tokens/encoder.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/source/source_range.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';

abstract class AbstractSemanticTokensHandler<T>
    extends MessageHandler<T, SemanticTokens>
    with LspPluginRequestHandlerMixin {
  AbstractSemanticTokensHandler(LspAnalysisServer server) : super(server);

  List<List<HighlightRegion>> getPluginResults(String path) {
    final notificationManager = server.notificationManager;
    return notificationManager.highlights.getResults(path);
  }

  Future<List<SemanticTokenInfo>> getServerResult(
      String path, SourceRange range) async {
    final result = await server.getResolvedUnit(path);
    if (result?.state == ResultState.VALID) {
      final computer = DartUnitHighlightsComputer(result.unit, range: range);
      return computer.computeSemanticTokens();
    }
    return [];
  }

  Iterable<SemanticTokenInfo> _filter(
      Iterable<SemanticTokenInfo> tokens, SourceRange range) {
    if (range == null) {
      return tokens;
    }

    return tokens.where((token) =>
        !(token.offset + token.length < range.offset ||
            token.offset > range.end));
  }

  Future<ErrorOr<SemanticTokens>> _handleImpl(
      TextDocumentIdentifier textDocument, CancellationToken token,
      {Range range}) async {
    final path = pathOfDoc(textDocument);

    return path.mapResult((path) async {
      final lineInfo = server.getLineInfo(path);
      // If there is no lineInfo, the request cannot be translated from LSP
      // line/col to server offset/length.
      if (lineInfo == null) {
        return success(null);
      }

      return toSourceRange(lineInfo, range).mapResult((range) async {
        final serverTokens = await getServerResult(path, range);
        final pluginHighlightRegions =
            getPluginResults(path).expand((results) => results).toList();

        if (token.isCancellationRequested) {
          return cancelled();
        }

        final encoder = SemanticTokenEncoder();
        Iterable<SemanticTokenInfo> pluginTokens =
            encoder.convertHighlightToTokens(pluginHighlightRegions);

        // Plugin tokens are not filtered at source, so need to be filtered here.
        pluginTokens = _filter(pluginTokens, range);

        Iterable<SemanticTokenInfo> tokens = [...serverTokens, ...pluginTokens];

        // Capabilities exist for supporting multiline/overlapping tokens. These
        // could be used if any clients take it up (VS Code does not).
        // - clientCapabilities?.multilineTokenSupport
        // - clientCapabilities?.overlappingTokenSupport
        final allowMultilineTokens = false;
        final allowOverlappingTokens = false;

        // Some of the translation operations and the final encoding require
        // the tokens to be sorted. Do it once here to avoid each method needing
        // to do it itself (resulting in multiple sorts).
        tokens = tokens.toList()
          ..sort(SemanticTokenInfo.offsetLengthPrioritySort);

        if (!allowOverlappingTokens) {
          tokens = encoder.splitOverlappingTokens(tokens);
        }

        if (!allowMultilineTokens) {
          tokens = tokens
              .expand((token) => encoder.splitMultilineTokens(token, lineInfo));

          // Tokens may need re-filtering after being split up as there may
          // now be tokens outside of the range.
          tokens = _filter(tokens, range);
        }

        final semanticTokens = encoder.encodeTokens(tokens.toList(), lineInfo);

        return success(semanticTokens);
      });
    });
  }
}

class SemanticTokensFullHandler
    extends AbstractSemanticTokensHandler<SemanticTokensParams> {
  SemanticTokensFullHandler(LspAnalysisServer server) : super(server);

  @override
  Method get handlesMessage => Method.textDocument_semanticTokens_full;

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

  @override
  Future<ErrorOr<SemanticTokens>> handle(
          SemanticTokensParams params, CancellationToken token) =>
      _handleImpl(params.textDocument, token);
}

class SemanticTokensRangeHandler
    extends AbstractSemanticTokensHandler<SemanticTokensRangeParams> {
  SemanticTokensRangeHandler(LspAnalysisServer server) : super(server);

  @override
  Method get handlesMessage => Method.textDocument_semanticTokens_range;

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

  @override
  Future<ErrorOr<SemanticTokens>> handle(
          SemanticTokensRangeParams params, CancellationToken token) =>
      _handleImpl(params.textDocument, token, range: params.range);
}
