// 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/src/generated/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.name.length;
    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]));
    }
  }
}
