// 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);
    final unit = result?.unit;
    if (result?.state == ResultState.VALID && unit != null) {
      final computer = DartUnitHighlightsComputer(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 toSourceRangeNullable(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);
}
