// 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 analysis.type_hierarhy;

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

import 'package:analysis_server/src/computer/element.dart' show
    engineElementToJson;
import 'package:analysis_services/constants.dart';
import 'package:analysis_services/json.dart';
import 'package:analysis_services/search/hierarchy.dart';
import 'package:analysis_services/search/search_engine.dart';
import 'package:analyzer/src/generated/element.dart';

/**
 * A computer for a type hierarchy of an [Element].
 */
class TypeHierarchyComputer {
  final SearchEngine _searchEngine;

  ElementKind _pivotKind;
  String _pivotName;

  final List<TypeHierarchyItem> _items = <TypeHierarchyItem>[];
  final Map<Element, TypeHierarchyItem> _elementItemMap =
      new HashMap<Element, TypeHierarchyItem>();

  TypeHierarchyComputer(this._searchEngine);

  /**
   * Returns the computed type hierarchy, maybe `null`.
   */
  Future<List<TypeHierarchyItem>> compute(Element element) {
    _pivotKind = element.kind;
    _pivotName = element.name;
    if (element is ExecutableElement &&
        element.enclosingElement is ClassElement) {
      element = element.enclosingElement;
    }
    if (element is ClassElement) {
      InterfaceType type = element.type;
      _createSuperItem(type);
      return _createSubclasses(_items[0], type).then((_) {
        return new Future.value(_items);
      });
    }
    return new Future.value([]);
  }

  Future _createSubclasses(TypeHierarchyItem item, InterfaceType type) {
    var future = getDirectSubClasses(_searchEngine, type.element);
    return future.then((Set<ClassElement> subElements) {
      List<TypeHierarchyItem> subItems = <TypeHierarchyItem>[];
      for (ClassElement subElement in subElements) {
        // check for recursion
        TypeHierarchyItem subItem = _elementItemMap[subElement];
        if (subItem != null) {
          int id = _items.indexOf(subItem);
          subItem.subclasses.add(id);
          continue;
        }
        // create a subclass item
        ExecutableElement subMemberElement = _findMemberElement(subElement);
        subItem = new TypeHierarchyItem(
            _items.length,
            subElement,
            subMemberElement,
            null,
            item.id,
            <int>[],
            <int>[]);
        // remember
        _elementItemMap[subElement] = subItem;
        _items.add(subItem);
        // add to hierarchy
        item.subclasses.add(subItem.id);
        subItems.add(subItem);
      }
      // compute subclasses of subclasses
      return Future.forEach(subItems, (TypeHierarchyItem subItem) {
        InterfaceType subType = subItem.classElement.type;
        return _createSubclasses(subItem, subType);
      });
    });
  }

  int _createSuperItem(InterfaceType type) {
    // check for recursion
    TypeHierarchyItem item = _elementItemMap[type.element];
    if (item != null) {
      return _items.indexOf(item);
    }
    // create an empty item now
    {
      String displayName = null;
      if (type.typeArguments.isNotEmpty) {
        displayName = type.toString();
      }
      ClassElement classElement = type.element;
      ExecutableElement memberElement = _findMemberElement(classElement);
      item = new TypeHierarchyItem(
          _items.length,
          classElement,
          memberElement,
          displayName,
          null,
          <int>[],
          <int>[]);
      _elementItemMap[classElement] = item;
      _items.add(item);
    }
    // superclass
    {
      InterfaceType superType = type.superclass;
      if (superType != null) {
        item.superclass = _createSuperItem(superType);
      }
    }
    // mixins
    type.mixins.forEach((InterfaceType type) {
      int id = _createSuperItem(type);
      item.mixins.add(id);
    });
    // interfaces
    type.interfaces.forEach((InterfaceType type) {
      int id = _createSuperItem(type);
      item.interfaces.add(id);
    });
    // done
    return item.id;
  }

  ExecutableElement _findMemberElement(ClassElement classElement) {
    if (_pivotKind == ElementKind.METHOD) {
      return classElement.getMethod(_pivotName);
    }
    if (_pivotKind == ElementKind.GETTER) {
      return classElement.getGetter(_pivotName);
    }
    if (_pivotKind == ElementKind.SETTER) {
      return classElement.getSetter(_pivotName);
    }
    return null;
  }
}


class TypeHierarchyItem implements HasToJson {
  final int id;
  final ClassElement classElement;
  final Element memberElement;
  final String displayName;
  int superclass;
  final List<int> mixins;
  final List<int> interfaces;
  final List<int> subclasses = <int>[];

  TypeHierarchyItem(this.id, this.classElement, this.memberElement,
      this.displayName, this.superclass, this.mixins, this.interfaces);

  Map<String, Object> toJson() {
    Map<String, Object> json = {};
    json[CLASS_ELEMENT] = engineElementToJson(classElement);
    if (memberElement != null) {
      json[MEMBER_ELEMENT] = engineElementToJson(memberElement);
    }
    if (displayName != null) {
      json[DISPLAY_NAME] = displayName;
    }
    if (superclass != null) {
      json[SUPERCLASS] = objectToJson(superclass);
    }
    json[INTERFACES] = objectToJson(interfaces);
    json[MIXINS] = objectToJson(mixins);
    json[SUBCLASSES] = objectToJson(subclasses);
    return json;
  }
}
