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

library search.element_references;

import 'dart:async';

import 'package:analysis_server/src/collections.dart';
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';
import 'package:analyzer/src/generated/source.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) {
    var futureGroup = new _ConcatFutureGroup<SearchResult>();
    // find element references
    futureGroup.add(_findElementsReferences(element));
    // add potential references
    if (withPotential && _isMemberElement(element)) {
      String name = element.displayName;
      var matchesFuture = searchEngine.searchMemberReferences(name);
      var resultsFuture = matchesFuture.then((List<SearchMatch> matches) {
        return matches.where((match) => !match.isResolved).map(toResult);
      });
      futureGroup.add(resultsFuture);
    }
    // merge results
    return futureGroup.future;
  }

  /**
   * Returns a [Future] completing with a [List] of references to [element] or
   * to the corresponding hierarchy [Element]s.
   */
  Future<List<SearchResult>> _findElementsReferences(Element element) {
    return _getRefElements(element).then((Iterable<Element> refElements) {
      var futureGroup = new _ConcatFutureGroup<SearchResult>();
      for (Element refElement in refElements) {
        // add declaration
        if (_isDeclarationInteresting(refElement)) {
          SearchResult searchResult = _newDeclarationResult(refElement);
          futureGroup.add(searchResult);
        }
        // do search
        futureGroup.add(_findSingleElementReferences(refElement));
      }
      return futureGroup.future;
    });
  }

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

  /**
   * Returns a [Future] completing with [Element]s to search references to.
   *
   * If a [ClassMemberElement] 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 ClassMemberElement) {
      return getHierarchyMembers(searchEngine, element);
    }
    return new Future.value([element]);
  }

  SearchResult _newDeclarationResult(Element refElement) {
    int nameOffset = refElement.nameOffset;
    int nameLength = refElement.nameLength;
    SearchMatch searchMatch = new SearchMatch(MatchKind.DECLARATION, refElement,
        new SourceRange(nameOffset, nameLength), true, false);
    return newSearchResult_fromMatch(searchMatch);
  }

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

  static bool _isDeclarationInteresting(Element element) {
    if (element is LabelElement) {
      return true;
    }
    if (element is LocalVariableElement) {
      return true;
    }
    if (element is ParameterElement) {
      return true;
    }
    if (element is PrefixElement) {
      return true;
    }
    if (element is PropertyInducingElement) {
      return !element.isSynthetic;
    }
    return false;
  }

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

/**
 * A collection of [Future]s that concats [List] results of added [Future]s into
 * a single [List].
 */
class _ConcatFutureGroup<E> {
  final List<Future<List<E>>> _futures = <Future<List<E>>>[];

  Future<List<E>> get future {
    return Future.wait(_futures).then(concatToList);
  }

  /**
   * Adds a [Future] or an [E] value to results.
   */
  void add(value) {
    if (value is Future) {
      _futures.add(value);
    } else {
      _futures.add(new Future.value(<E>[value]));
    }
  }
}
