// Copyright (c) 2014, 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/protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_constants.dart';
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/protocol/protocol_internal.dart'
    show ResponseResult;
import 'package:analysis_server/src/protocol_server.dart' as protocol;
import 'package:analysis_server/src/search/element_references.dart';
import 'package:analysis_server/src/search/type_hierarchy.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
import 'package:analysis_server/src/utilities/progress.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dart/analysis/search.dart' as search;

/// Instances of the class [SearchDomainHandler] implement a [RequestHandler]
/// that handles requests in the search domain.
class SearchDomainHandler implements protocol.RequestHandler {
  /// The analysis server that is using this handler to process requests.
  final AnalysisServer server;

  /// The next search response id.
  int _nextSearchId = 0;

  /// Initialize a newly created handler to handle requests for the given
  /// [server].
  SearchDomainHandler(this.server);

  Future<void> findElementReferences(protocol.Request request) async {
    final searchEngine = server.searchEngine;
    var params =
        protocol.SearchFindElementReferencesParams.fromRequest(request);
    var file = params.file;
    // prepare element
    var element = await server.getElementAtOffset(file, params.offset);
    if (element is ImportElement) {
      element = element.prefix;
    }
    if (element is FieldFormalParameterElement) {
      element = element.field;
    }
    if (element is PropertyAccessorElement) {
      element = element.variable;
    }
    // respond
    var searchId = (_nextSearchId++).toString();
    var result = protocol.SearchFindElementReferencesResult();
    if (element != null) {
      result.id = searchId;
      var withNullability = element.library?.isNonNullableByDefault ?? false;
      result.element =
          protocol.convertElement(element, withNullability: withNullability);
    }
    _sendSearchResult(request, result);
    // search elements
    if (element != null) {
      var computer = ElementReferencesComputer(searchEngine);
      var results = await computer.compute(element, params.includePotential);
      _sendSearchNotification(searchId, true, results);
    }
  }

  Future findMemberDeclarations(protocol.Request request) async {
    final searchEngine = server.searchEngine;
    var params =
        protocol.SearchFindMemberDeclarationsParams.fromRequest(request);
    await server.onAnalysisComplete;
    // respond
    var searchId = (_nextSearchId++).toString();
    _sendSearchResult(
        request, protocol.SearchFindMemberDeclarationsResult(searchId));
    // search
    var matches = await searchEngine.searchMemberDeclarations(params.name);
    _sendSearchNotification(searchId, true, matches.map(toResult));
  }

  Future findMemberReferences(protocol.Request request) async {
    final searchEngine = server.searchEngine;
    var params = protocol.SearchFindMemberReferencesParams.fromRequest(request);
    await server.onAnalysisComplete;
    // respond
    var searchId = (_nextSearchId++).toString();
    _sendSearchResult(
        request, protocol.SearchFindMemberReferencesResult(searchId));
    // search
    var matches = await searchEngine.searchMemberReferences(params.name);
    _sendSearchNotification(searchId, true, matches.map(toResult));
  }

  Future findTopLevelDeclarations(protocol.Request request) async {
    final searchEngine = server.searchEngine;
    var params =
        protocol.SearchFindTopLevelDeclarationsParams.fromRequest(request);
    try {
      // validate the regex
      RegExp(params.pattern);
    } on FormatException catch (exception) {
      server.sendResponse(protocol.Response.invalidParameter(
          request, 'pattern', exception.message));
      return;
    }

    await server.onAnalysisComplete;
    // respond
    var searchId = (_nextSearchId++).toString();
    _sendSearchResult(
        request, protocol.SearchFindTopLevelDeclarationsResult(searchId));
    // search
    var matches = await searchEngine.searchTopLevelDeclarations(params.pattern);
    _sendSearchNotification(searchId, true, matches.map(toResult));
  }

  /// Implement the `search.getDeclarations` request.
  Future getDeclarations(protocol.Request request) async {
    var params =
        protocol.SearchGetElementDeclarationsParams.fromRequest(request);

    RegExp? regExp;
    var pattern = params.pattern;
    if (pattern != null) {
      try {
        regExp = RegExp(pattern);
      } on FormatException catch (exception) {
        server.sendResponse(protocol.Response.invalidParameter(
            request, 'pattern', exception.message));
        return;
      }
    }

    protocol.ElementKind getElementKind(search.DeclarationKind kind) {
      switch (kind) {
        case search.DeclarationKind.CLASS:
          return protocol.ElementKind.CLASS;
        case search.DeclarationKind.CLASS_TYPE_ALIAS:
          return protocol.ElementKind.CLASS_TYPE_ALIAS;
        case search.DeclarationKind.CONSTRUCTOR:
          return protocol.ElementKind.CONSTRUCTOR;
        case search.DeclarationKind.ENUM:
          return protocol.ElementKind.ENUM;
        case search.DeclarationKind.ENUM_CONSTANT:
          return protocol.ElementKind.ENUM_CONSTANT;
        case search.DeclarationKind.FIELD:
          return protocol.ElementKind.FIELD;
        case search.DeclarationKind.FUNCTION:
          return protocol.ElementKind.FUNCTION;
        case search.DeclarationKind.FUNCTION_TYPE_ALIAS:
          return protocol.ElementKind.FUNCTION_TYPE_ALIAS;
        case search.DeclarationKind.GETTER:
          return protocol.ElementKind.GETTER;
        case search.DeclarationKind.METHOD:
          return protocol.ElementKind.METHOD;
        case search.DeclarationKind.MIXIN:
          return protocol.ElementKind.MIXIN;
        case search.DeclarationKind.SETTER:
          return protocol.ElementKind.SETTER;
        case search.DeclarationKind.TYPE_ALIAS:
          return protocol.ElementKind.TYPE_ALIAS;
        case search.DeclarationKind.VARIABLE:
          return protocol.ElementKind.TOP_LEVEL_VARIABLE;
        default:
          return protocol.ElementKind.CLASS;
      }
    }

    if (!server.options.featureSet.completion) {
      server.sendResponse(Response.unsupportedFeature(
          request.id, 'Completion is not enabled.'));
      return;
    }

    var workspaceSymbols = search.WorkspaceSymbols();
    var analysisDrivers = server.driverMap.values.toList();
    for (var analysisDriver in analysisDrivers) {
      await analysisDriver.search.declarations(
          workspaceSymbols, regExp, params.maxResults,
          onlyForFile: params.file);
    }

    var declarations = workspaceSymbols.declarations;
    var elementDeclarations = declarations.map((declaration) {
      return protocol.ElementDeclaration(
          declaration.name,
          getElementKind(declaration.kind),
          declaration.fileIndex,
          declaration.offset,
          declaration.line,
          declaration.column,
          declaration.codeOffset,
          declaration.codeLength,
          className: declaration.className,
          mixinName: declaration.mixinName,
          parameters: declaration.parameters);
    }).toList();

    server.sendResponse(protocol.SearchGetElementDeclarationsResult(
            elementDeclarations, workspaceSymbols.files)
        .toResponse(request.id));
  }

  /// Implement the `search.getTypeHierarchy` request.
  Future getTypeHierarchy(protocol.Request request) async {
    final searchEngine = server.searchEngine;
    var params = protocol.SearchGetTypeHierarchyParams.fromRequest(request);
    var file = params.file;
    // prepare element
    var element = await server.getElementAtOffset(file, params.offset);
    if (element == null) {
      _sendTypeHierarchyNull(request);
      return;
    }
    // maybe supertype hierarchy only
    if (params.superOnly == true) {
      var computer = TypeHierarchyComputer(searchEngine, element);
      var items = computer.computeSuper();
      var response =
          protocol.SearchGetTypeHierarchyResult(hierarchyItems: items)
              .toResponse(request.id);
      server.sendResponse(response);
      return;
    }
    // prepare type hierarchy
    var computer = TypeHierarchyComputer(searchEngine, element);
    var items = await computer.compute();
    var response = protocol.SearchGetTypeHierarchyResult(hierarchyItems: items)
        .toResponse(request.id);
    server.sendResponse(response);
  }

  @override
  protocol.Response? handleRequest(
      protocol.Request request, CancellationToken cancellationToken) {
    try {
      var requestName = request.method;
      if (requestName == SEARCH_REQUEST_FIND_ELEMENT_REFERENCES) {
        findElementReferences(request);
        return protocol.Response.DELAYED_RESPONSE;
      } else if (requestName == SEARCH_REQUEST_FIND_MEMBER_DECLARATIONS) {
        findMemberDeclarations(request);
        return protocol.Response.DELAYED_RESPONSE;
      } else if (requestName == SEARCH_REQUEST_FIND_MEMBER_REFERENCES) {
        findMemberReferences(request);
        return protocol.Response.DELAYED_RESPONSE;
      } else if (requestName == SEARCH_REQUEST_FIND_TOP_LEVEL_DECLARATIONS) {
        findTopLevelDeclarations(request);
        return protocol.Response.DELAYED_RESPONSE;
      } else if (requestName == SEARCH_REQUEST_GET_ELEMENT_DECLARATIONS) {
        getDeclarations(request);
        return protocol.Response.DELAYED_RESPONSE;
      } else if (requestName == SEARCH_REQUEST_GET_TYPE_HIERARCHY) {
        getTypeHierarchy(request);
        return protocol.Response.DELAYED_RESPONSE;
      }
    } on protocol.RequestFailure catch (exception) {
      return exception.response;
    }
    return null;
  }

  void _sendSearchNotification(
      String searchId, bool isLast, Iterable<protocol.SearchResult> results) {
    server.sendNotification(
        protocol.SearchResultsParams(searchId, results.toList(), isLast)
            .toNotification());
  }

  /// Send a search response with the given [result] to the given [request].
  void _sendSearchResult(protocol.Request request, ResponseResult result) {
    var response = result.toResponse(request.id);
    server.sendResponse(response);
  }

  void _sendTypeHierarchyNull(protocol.Request request) {
    var response =
        protocol.SearchGetTypeHierarchyResult().toResponse(request.id);
    server.sendResponse(response);
  }

  static protocol.SearchResult toResult(SearchMatch match) {
    return protocol.newSearchResult_fromMatch(match);
  }
}
