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

import 'dart:collection';

import 'package:analysis_server/src/protocol_server.dart'
    show TypeHierarchyItem, convertElement;
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/dart/element/type.dart';

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

  final Element _pivotElement;
  final LibraryElement _pivotLibrary;
  final ElementKind _pivotKind;
  final String? _pivotName;
  late bool _pivotFieldFinal;
  ClassElement? _pivotClass;

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

  TypeHierarchyComputer(this._searchEngine, this._pivotElement)
      : _pivotLibrary = _pivotElement.library!,
        _pivotKind = _pivotElement.kind,
        _pivotName = _pivotElement.name {
    // try to find enclosing ClassElement
    Element? element = _pivotElement;
    if (_pivotElement is FieldElement) {
      _pivotFieldFinal = (_pivotElement as FieldElement).isFinal;
      element = _pivotElement.enclosingElement;
    }
    if (_pivotElement is ExecutableElement) {
      element = _pivotElement.enclosingElement;
    }
    if (element is ClassElement) {
      _pivotClass = element;
    }
  }

  bool get _isNonNullableByDefault => _pivotLibrary.isNonNullableByDefault;

  /// Returns the computed type hierarchy, maybe `null`.
  Future<List<TypeHierarchyItem>?> compute() async {
    var pivotClass = _pivotClass;
    if (pivotClass != null) {
      _createSuperItem(pivotClass, null);
      await _createSubclasses(_items[0], 0, pivotClass);
      return _items;
    }
    return null;
  }

  /// Returns the computed super type only type hierarchy, maybe `null`.
  List<TypeHierarchyItem>? computeSuper() {
    var pivotClass = _pivotClass;
    if (pivotClass != null) {
      _createSuperItem(pivotClass, null);
      return _items;
    }
    return null;
  }

  Future _createSubclasses(
      TypeHierarchyItem item, int itemId, ClassElement classElement) async {
    var subElements = await getDirectSubClasses(_searchEngine, classElement);
    var subItemIds = <int>[];
    for (var subElement in subElements) {
      // check for recursion
      var subItem = _elementItemMap[subElement];
      if (subItem != null) {
        var id = _items.indexOf(subItem);
        item.subclasses.add(id);
        continue;
      }
      // create a subclass item
      var subMemberElement = _findMemberElement(subElement);
      subItem = TypeHierarchyItem(
          convertElement(subElement, withNullability: _isNonNullableByDefault),
          memberElement: subMemberElement != null
              ? convertElement(subMemberElement,
                  withNullability: _isNonNullableByDefault)
              : null,
          superclass: itemId);
      var subItemId = _items.length;
      // remember
      _elementItemMap[subElement] = subItem;
      _items.add(subItem);
      _itemClassElements.add(subElement);
      // add to hierarchy
      item.subclasses.add(subItemId);
      subItemIds.add(subItemId);
    }
    // compute subclasses of subclasses
    for (var subItemId in subItemIds) {
      var subItem = _items[subItemId];
      var subItemElement = _itemClassElements[subItemId];
      await _createSubclasses(subItem, subItemId, subItemElement);
    }
  }

  int _createSuperItem(
      ClassElement classElement, List<DartType>? typeArguments) {
    // check for recursion
    var cachedItem = _elementItemMap[classElement];
    if (cachedItem != null) {
      return _items.indexOf(cachedItem);
    }
    // create an empty item now
    TypeHierarchyItem item;
    int itemId;
    {
      String? displayName;
      if (typeArguments != null && typeArguments.isNotEmpty) {
        var typeArgumentsStr = typeArguments
            .map((type) =>
                type.getDisplayString(withNullability: _isNonNullableByDefault))
            .join(', ');
        displayName = classElement.displayName + '<' + typeArgumentsStr + '>';
      }
      var memberElement = _findMemberElement(classElement);
      item = TypeHierarchyItem(
          convertElement(classElement,
              withNullability: _isNonNullableByDefault),
          displayName: displayName,
          memberElement: memberElement != null
              ? convertElement(memberElement,
                  withNullability: _isNonNullableByDefault)
              : null);
      _elementItemMap[classElement] = item;
      itemId = _items.length;
      _items.add(item);
      _itemClassElements.add(classElement);
    }
    // superclass
    {
      var superType = classElement.supertype;
      if (superType != null) {
        item.superclass = _createSuperItem(
          superType.element,
          superType.typeArguments,
        );
      }
    }
    // mixins
    classElement.mixins.forEach((InterfaceType type) {
      var id = _createSuperItem(type.element, type.typeArguments);
      item.mixins.add(id);
    });
    // interfaces
    classElement.interfaces.forEach((InterfaceType type) {
      var id = _createSuperItem(type.element, type.typeArguments);
      item.interfaces.add(id);
    });
    // done
    return itemId;
  }

  ExecutableElement? _findMemberElement(ClassElement clazz) {
    var pivotName = _pivotName;
    if (pivotName == null) {
      return null;
    }
    ExecutableElement? result;
    // try to find in the class itself
    if (_pivotKind == ElementKind.METHOD) {
      result = clazz.getMethod(pivotName);
    } else if (_pivotKind == ElementKind.GETTER) {
      result = clazz.getGetter(pivotName);
    } else if (_pivotKind == ElementKind.SETTER) {
      result = clazz.getSetter(pivotName);
    } else if (_pivotKind == ElementKind.FIELD) {
      result = clazz.getGetter(pivotName);
      if (result == null && !_pivotFieldFinal) {
        result = clazz.getSetter(pivotName);
      }
    }
    if (result != null && result.isAccessibleIn(_pivotLibrary)) {
      return result;
    }
    // try to find in the class mixin
    for (var mixin in clazz.mixins.reversed) {
      var mixinElement = mixin.element;
      if (_pivotKind == ElementKind.METHOD) {
        result = mixinElement.lookUpMethod(pivotName, _pivotLibrary);
      } else if (_pivotKind == ElementKind.GETTER) {
        result = mixinElement.lookUpGetter(pivotName, _pivotLibrary);
      } else if (_pivotKind == ElementKind.SETTER) {
        result = mixinElement.lookUpSetter(pivotName, _pivotLibrary);
      } else if (_pivotKind == ElementKind.FIELD) {
        result = mixinElement.lookUpGetter(pivotName, _pivotLibrary);
        if (result == null && !_pivotFieldFinal) {
          result = mixinElement.lookUpSetter(pivotName, _pivotLibrary);
        }
      }
      if (result == _pivotElement) {
        return null;
      }
      if (result != null) {
        return result;
      }
    }
    // not found
    return null;
  }
}
