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

// @dart = 2.9

import 'package:analysis_server/src/protocol_server.dart'
    show SearchResult, newSearchResult_fromMatch;
import 'package:analysis_server/src/services/search/hierarchy.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
import 'package:analyzer/dart/element/element.dart';

/// A computer for `search.findElementReferences` request results.
class ElementReferencesComputer {
  final SearchEngine searchEngine;

  ElementReferencesComputer(this.searchEngine);

  /// Computes [SearchResult]s for [element] references.
  Future<List<SearchResult>> compute(
      Element element, bool withPotential) async {
    var results = <SearchResult>[];

    // Add element references.
    results.addAll(await _findElementsReferences(element));

    // Add potential references.
    if (withPotential && _isMemberElement(element)) {
      var name = element.displayName;
      var matches = await searchEngine.searchMemberReferences(name);
      matches = SearchMatch.withNotNullElement(matches);
      results.addAll(matches.where((match) => !match.isResolved).map(toResult));
    }

    return results;
  }

  /// Returns a [Future] completing with a [List] of references to [element] or
  /// to the corresponding hierarchy [Element]s.
  Future<List<SearchResult>> _findElementsReferences(Element element) async {
    var allResults = <SearchResult>[];
    var refElements = await _getRefElements(element);
    for (var refElement in refElements) {
      var elementResults = await _findSingleElementReferences(refElement);
      allResults.addAll(elementResults);
    }
    return allResults;
  }

  /// Returns a [Future] completing with a [List] of references to [element].
  Future<List<SearchResult>> _findSingleElementReferences(
      Element element) async {
    var matches = await searchEngine.searchReferences(element);
    matches = SearchMatch.withNotNullElement(matches);
    return matches.map(toResult).toList();
  }

  /// Returns a [Future] completing with [Element]s to search references to.
  ///
  /// If a [ClassMemberElement] or a named [ParameterElement] is given, each
  /// corresponding [Element] in the hierarchy is returned.
  ///
  /// Otherwise, only references to [element] should be searched.
  Future<Iterable<Element>> _getRefElements(Element element) {
    if (element is ParameterElement && element.isNamed) {
      return getHierarchyNamedParameters(searchEngine, element);
    }
    if (element is ClassMemberElement) {
      return getHierarchyMembers(searchEngine, element);
    }
    return Future.value([element]);
  }

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

  static bool _isMemberElement(Element element) {
    if (element is ConstructorElement) {
      return false;
    }
    return element.enclosingElement is ClassElement;
  }
}
