// 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 services.hierarchy;

import 'dart:async';
import 'dart:collection';

import 'package:analysis_server/src/services/search/element_visitors.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';

/**
 * Returns direct children of [parent].
 */
List<Element> getChildren(Element parent, [String name]) {
  List<Element> children = <Element>[];
  visitChildren(parent, (Element element) {
    if (name == null || element.displayName == name) {
      children.add(element);
    }
  });
  return children;
}

/**
 * Returns direct non-synthetic children of the given [ClassElement].
 *
 * Includes: fields, accessors and methods.
 * Excludes: constructors and synthetic elements.
 */
List<Element> getClassMembers(ClassElement clazz, [String name]) {
  List<Element> members = <Element>[];
  visitChildren(clazz, (Element element) {
    if (element.isSynthetic) {
      return;
    }
    if (element is ConstructorElement) {
      return;
    }
    if (name != null && element.displayName != name) {
      return;
    }
    if (element is ExecutableElement) {
      members.add(element);
    }
    if (element is FieldElement) {
      members.add(element);
    }
  });
  return members;
}

/**
 * Returns a [Set] with direct subclasses of [seed].
 */
Future<Set<ClassElement>> getDirectSubClasses(
    SearchEngine searchEngine, ClassElement seed) {
  return searchEngine.searchSubtypes(seed).then((List<SearchMatch> matches) {
    Set<ClassElement> subClasses = new HashSet<ClassElement>();
    for (SearchMatch match in matches) {
      ClassElement subClass = match.element;
      subClasses.add(subClass);
    }
    return subClasses;
  });
}

/**
 * @return all implementations of the given {@link ClassMemberElement} is its superclasses and
 *         their subclasses.
 */
Future<Set<ClassMemberElement>> getHierarchyMembers(
    SearchEngine searchEngine, ClassMemberElement member) {
  Set<ClassMemberElement> result = new HashSet<ClassMemberElement>();
  // constructor
  if (member is ConstructorElement) {
    result.add(member);
    return new Future.value(result);
  }
  // method, field, etc
  String name = member.displayName;
  ClassElement memberClass = member.enclosingElement;
  List<Future> futures = <Future>[];
  Set<ClassElement> searchClasses = getSuperClasses(memberClass);
  searchClasses.add(memberClass);
  for (ClassElement superClass in searchClasses) {
    // ignore if super- class does not declare member
    if (getClassMembers(superClass, name).isEmpty) {
      continue;
    }
    // check all sub- classes
    var subClassFuture = getSubClasses(searchEngine, superClass);
    var membersFuture = subClassFuture.then((Set<ClassElement> subClasses) {
      subClasses.add(superClass);
      for (ClassElement subClass in subClasses) {
        List<Element> subClassMembers = getChildren(subClass, name);
        for (Element member in subClassMembers) {
          if (member is ClassMemberElement) {
            result.add(member);
          }
        }
      }
    });
    futures.add(membersFuture);
  }
  return Future.wait(futures).then((_) {
    return result;
  });
}

/**
 * Returns non-synthetic members of the given [ClassElement] and its super
 * classes.
 *
 * Includes: fields, accessors and methods.
 * Excludes: constructors and synthetic elements.
 */
List<Element> getMembers(ClassElement clazz) {
  List<Element> members = <Element>[];
  members.addAll(getClassMembers(clazz));
  Set<ClassElement> superClasses = getSuperClasses(clazz);
  for (ClassElement superClass in superClasses) {
    members.addAll(getClassMembers(superClass));
  }
  return members;
}

/**
 * Returns a [Set] with all direct and indirect subclasses of [seed].
 */
Future<Set<ClassElement>> getSubClasses(
    SearchEngine searchEngine, ClassElement seed) {
  return searchEngine.searchAllSubtypes(seed).then((List<SearchMatch> matches) {
    Set<ClassElement> ancestors = new HashSet<ClassElement>();
    for (SearchMatch match in matches) {
      ClassElement ancestor = match.element;
      ancestors.add(ancestor);
    }
    return ancestors;
  });
}

/**
 * Returns a [Set] with all direct and indirect superclasses of [seed].
 */
Set<ClassElement> getSuperClasses(ClassElement seed) {
  Set<ClassElement> result = new HashSet<ClassElement>();
  // prepare queue
  List<ClassElement> queue = new List<ClassElement>();
  queue.add(seed);
  // process queue
  while (!queue.isEmpty) {
    ClassElement current = queue.removeLast();
    // add if not checked already
    if (!result.add(current)) {
      continue;
    }
    // append supertype
    {
      InterfaceType superType = current.supertype;
      if (superType != null) {
        queue.add(superType.element);
      }
    }
    // append interfaces
    for (InterfaceType intf in current.interfaces) {
      queue.add(intf.element);
    }
  }
  // we don't need "seed" itself
  result.remove(seed);
  return result;
}

/**
 * If the given [element] is a synthetic [PropertyAccessorElement] returns
 * its variable, otherwise returns [element].
 */
Element getSyntheticAccessorVariable(Element element) {
  if (element is PropertyAccessorElement) {
    if (element.isSynthetic) {
      return element.variable;
    }
  }
  return element;
}
