// Copyright (c) 2019, 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 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:dartdoc/src/element_type.dart';
import 'package:dartdoc/src/model/extension_target.dart';
import 'package:dartdoc/src/model/model.dart';
import 'package:dartdoc/src/model_utils.dart' as model_utils;
import 'package:dartdoc/src/quiver.dart' as quiver;
import 'package:meta/meta.dart';

/// A [Container] defined with a `class` declaration in Dart.
///
/// Members follow similar naming rules to [Container], with the following
/// additions:
///
/// **instance**: As with [Container], but also includes inherited children.
/// **inherited**: Filtered getters giving only inherited children.
class Class extends Container
    with Categorization, ExtensionTarget
    implements EnclosedElement {
  // TODO(srawlins): To make final, remove public getter, setter, rename to be
  // public, and add `final` modifier.
  List<DefinedElementType> _mixins;

  List<DefinedElementType> get mixins => _mixins;

  @Deprecated('Field intended to be final; setter will be removed as early as '
      'Dartdoc 1.0.0')
  set mixins(List<DefinedElementType> value) => _mixins = value;

  // TODO(srawlins): To make final, remove public getter, setter, rename to be
  // public, and add `final` modifier.
  DefinedElementType _supertype;

  DefinedElementType get supertype => _supertype;

  @Deprecated('Field intended to be final; setter will be removed as early as '
      'Dartdoc 1.0.0')
  set supertype(DefinedElementType value) => _supertype = value;

  final List<DefinedElementType> _interfaces;

  Class(ClassElement element, Library library, PackageGraph packageGraph)
      : _mixins = element.mixins
            .map<DefinedElementType>(
                (f) => ElementType.from(f, library, packageGraph))
            .where((mixin) => mixin != null)
            .toList(growable: false),
        _supertype = element.supertype?.element?.supertype == null
            ? null
            : ElementType.from(element.supertype, library, packageGraph),
        _interfaces = element.interfaces
            .map<DefinedElementType>(
                (f) => ElementType.from(f, library, packageGraph))
            .toList(growable: false),
        super(element, library, packageGraph) {
    packageGraph.specialClasses.addSpecial(this);
  }

  Constructor _unnamedConstructor;

  Constructor get unnamedConstructor {
    _unnamedConstructor ??= constructors
        .firstWhere((c) => c.isUnnamedConstructor, orElse: () => null);
    return _unnamedConstructor;
  }

  @Deprecated(
      'Renamed to `unnamedConstructor`; this getter with the old name will be '
      'removed as early as Dartdoc 1.0.0')
  Constructor get defaultConstructor => unnamedConstructor;

  @override
  Iterable<Method> get instanceMethods =>
      quiver.concat([super.instanceMethods, inheritedMethods]);

  @override
  bool get publicInheritedInstanceMethods =>
      instanceMethods.every((f) => f.isInherited);

  @override
  Iterable<Operator> get instanceOperators =>
      quiver.concat([super.instanceOperators, inheritedOperators]);

  List<ModelElement> _allModelElements;

  @override
  List<ModelElement> get allModelElements {
    _allModelElements ??= List.from(
        quiver.concat<ModelElement>([
          super.allModelElements,
          constructors,
          typeParameters,
        ]),
        growable: false);
    return _allModelElements;
  }

  List<ModelElement> _allCanonicalModelElements;

  List<ModelElement> get allCanonicalModelElements {
    return (_allCanonicalModelElements ??=
        allModelElements.where((e) => e.isCanonical).toList());
  }

  Iterable<Constructor> get constructors => element.constructors
      .map((e) => ModelElement.from(e, library, packageGraph) as Constructor);

  @visibleForTesting
  Iterable<Constructor> get publicConstructors =>
      model_utils.filterNonPublic(constructors);

  /// Returns the library that encloses this element.
  @override
  ModelElement get enclosingElement => library;

  @override
  ClassElement get element => super.element;

  @override
  String get fileName => '$name-class.$fileType';

  @override
  String get filePath => '${library.dirName}/$fileName';

  String get fullkind {
    if (isAbstract) return 'abstract $kind';
    return kind;
  }

  @override
  bool get hasPublicConstructors => publicConstructorsSorted.isNotEmpty;

  List<Constructor> _publicConstructorsSorted;

  @override
  List<Constructor> get publicConstructorsSorted =>
      _publicConstructorsSorted ??= publicConstructors.toList()..sort(byName);

  bool get hasPublicImplementors => publicImplementors.isNotEmpty;

  bool get hasPublicInterfaces => publicInterfaces.isNotEmpty;

  bool get hasPublicMixins => publicMixins.isNotEmpty;

  @override
  bool get hasModifiers =>
      hasPublicMixins ||
      hasAnnotations ||
      hasPublicInterfaces ||
      hasPublicSuperChainReversed ||
      hasPublicImplementors ||
      hasPotentiallyApplicableExtensions;

  bool get hasPublicSuperChainReversed => publicSuperChainReversed.isNotEmpty;

  @override
  String get href {
    if (!identical(canonicalModelElement, this)) {
      return canonicalModelElement?.href;
    }
    assert(canonicalLibrary != null);
    assert(canonicalLibrary == library);
    return '${package.baseHref}$filePath';
  }

  /// Returns the [Class] with the library in which [element] is defined.
  Class get definingClass =>
      ModelElement.from(element, definingLibrary, packageGraph);

  /// Returns all the "immediate" public implementors of this class.
  ///
  /// If this class has a private implementor, then that is counted as a proxy
  /// for any public implementors of that private class.
  Iterable<Class> get publicImplementors {
    var result = <Class>{};
    var seen = <Class>{};

    // Recursively adds [implementor] if public, or the implementors of
    // [implementor] if not.
    void addToResult(Class implementor) {
      if (seen.contains(implementor)) return;
      seen.add(implementor);
      if (implementor.isPublicAndPackageDocumented) {
        result.add(implementor);
      } else {
        model_utils
            .findCanonicalFor(packageGraph.implementors[implementor] ?? [])
            .forEach(addToResult);
      }
    }

    model_utils
        .findCanonicalFor(packageGraph.implementors[this] ?? [])
        .forEach(addToResult);
    return result;
  }

  /*lazy final*/ List<Method> _inheritedMethods;

  Iterable<Method> get inheritedMethods {
    if (_inheritedMethods == null) {
      _inheritedMethods = <Method>[];
      var methodNames = declaredMethods.map((m) => m.element.name).toSet();

      var inheritedMethodElements = _inheritedElements.where((e) {
        return (e is MethodElement &&
            !e.isOperator &&
            e is! PropertyAccessorElement &&
            !methodNames.contains(e.name));
      }).toSet();

      for (var e in inheritedMethodElements) {
        Method m = ModelElement.from(e, library, packageGraph,
            enclosingContainer: this);
        _inheritedMethods.add(m);
      }
    }
    return _inheritedMethods;
  }

  Iterable<Method> get publicInheritedMethods =>
      model_utils.filterNonPublic(inheritedMethods);

  bool get hasPublicInheritedMethods => publicInheritedMethods.isNotEmpty;

  /*lazy final*/ List<Operator> _inheritedOperators;

  Iterable<Operator> get inheritedOperators {
    if (_inheritedOperators == null) {
      _inheritedOperators = [];
      var operatorNames = declaredOperators.map((o) => o.element.name).toSet();

      var inheritedOperatorElements = _inheritedElements.where((e) {
        return (e is MethodElement &&
            e.isOperator &&
            !operatorNames.contains(e.name));
      }).toSet();
      for (var e in inheritedOperatorElements) {
        Operator o = ModelElement.from(e, library, packageGraph,
            enclosingContainer: this);
        _inheritedOperators.add(o);
      }
    }
    return _inheritedOperators;
  }

  @override
  Iterable<Operator> get publicInheritedInstanceOperators =>
      model_utils.filterNonPublic(inheritedOperators);

  Iterable<Field> get inheritedFields => allFields.where((f) => f.isInherited);

  Iterable<Field> get publicInheritedFields =>
      model_utils.filterNonPublic(inheritedFields);

  List<DefinedElementType> get interfaces => _interfaces;

  Iterable<DefinedElementType> get publicInterfaces =>
      model_utils.filterNonPublic(interfaces);

  bool get isAbstract => element.isAbstract;

  @override
  bool get isCanonical => super.isCanonical && isPublic;

  bool get isErrorOrException {
    bool _doCheck(ClassElement element) {
      return (element.library.isDartCore &&
          (element.name == 'Exception' || element.name == 'Error'));
    }

    // if this class is itself Error or Exception, return true
    if (_doCheck(element)) return true;

    return element.allSupertypes.map((t) => t.element).any(_doCheck);
  }

  /// Returns true if [other] is a parent class for this class.
  bool _isInheritingFrom(Class other) =>
      superChain.map((et) => (et.element as Class)).contains(other);

  @Deprecated(
      'Public method intended to be private; will be removed as early as '
      'Dartdoc 1.0.0')
  bool isInheritingFrom(Class other) => _isInheritingFrom(other);

  @override
  String get kind => 'class';

  Iterable<DefinedElementType> get publicMixins =>
      model_utils.filterNonPublic(mixins);

  @override
  DefinedElementType get modelType => super.modelType;

  /// Not the same as superChain as it may include mixins.
  /// It's really not even the same as ordinary Dart inheritance, either,
  /// because we pretend that interfaces are part of the inheritance chain
  /// to include them in the set of things we might link to for documentation
  /// purposes in abstract classes.
  List<Class> _inheritanceChain;

  List<Class> get inheritanceChain {
    if (_inheritanceChain == null) {
      _inheritanceChain = [];
      _inheritanceChain.add(this);

      /// Caching should make this recursion a little less painful.
      for (var c in mixins.reversed.map((e) => (e.element as Class))) {
        _inheritanceChain.addAll(c.inheritanceChain);
      }

      for (var c in superChain.map((e) => (e.element as Class))) {
        _inheritanceChain.addAll(c.inheritanceChain);
      }

      /// Interfaces need to come last, because classes in the superChain might
      /// implement them even when they aren't mentioned.
      _inheritanceChain.addAll(
          interfaces.expand((e) => (e.element as Class).inheritanceChain));
    }
    return _inheritanceChain.toList(growable: false);
  }

  List<DefinedElementType> get superChain {
    var typeChain = <DefinedElementType>[];
    var parent = supertype;
    while (parent != null) {
      typeChain.add(parent);
      if (parent.type is InterfaceType) {
        // Avoid adding [Object] to the superChain (_supertype already has this
        // check)
        if ((parent.type as InterfaceType)?.superclass?.superclass == null) {
          parent = null;
        } else {
          parent = ElementType.from(
              (parent.type as InterfaceType).superclass, library, packageGraph);
        }
      } else {
        parent = (parent.element as Class).supertype;
      }
    }
    return typeChain;
  }

  Iterable<DefinedElementType> get publicSuperChain =>
      model_utils.filterNonPublic(superChain);

  Iterable<DefinedElementType> get publicSuperChainReversed =>
      publicSuperChain.toList().reversed;

  List<ExecutableElement> __inheritedElements;

  List<ExecutableElement> get _inheritedElements {
    if (__inheritedElements == null) {
      if (element.isDartCoreObject) {
        return __inheritedElements = <ExecutableElement>[];
      }

      if (definingLibrary == null) {
        // [definingLibrary] may be null if [element] has been imported or
        // exported with a non-normalized URI, like "src//a.dart".
        // TODO(srawlins): It would be nice to allow references from such
        // libraries, but for now, PackageGraph.allLibraries is a Map with
        // LibraryElement keys, which include [Element.location] in their
        // `==` calculation; I think we should not key off of Elements.
        return __inheritedElements = <ExecutableElement>[];
      }

      var inheritance = definingLibrary.inheritanceManager;
      var cmap = inheritance.getInheritedConcreteMap2(element);
      var imap = inheritance.getInheritedMap2(element);

      var combinedMap = <String, ExecutableElement>{};
      for (var nameObj in cmap.keys) {
        combinedMap[nameObj.name] = cmap[nameObj];
      }
      for (var nameObj in imap.keys) {
        combinedMap[nameObj.name] ??= imap[nameObj];
      }

      __inheritedElements = combinedMap.values.toList();
    }
    return __inheritedElements;
  }

  List<Field> _allFields;

  List<Field> get allFields {
    if (_allFields == null) {
      _allFields = [];
      var inheritedAccessorElements = <PropertyAccessorElement>{}
        ..addAll(_inheritedElements.whereType<PropertyAccessorElement>());

      // This structure keeps track of inherited accessors, allowing lookup
      // by field name (stripping the '=' from setters).
      var accessorMap = <String, List<PropertyAccessorElement>>{};
      for (var accessorElement in inheritedAccessorElements) {
        var name = accessorElement.name.replaceFirst('=', '');
        accessorMap.putIfAbsent(name, () => []).add(accessorElement);
      }

      // For half-inherited fields, the analyzer only links the non-inherited
      // to the [FieldElement].  Compose our [Field] class by hand by looking up
      // inherited accessors that may be related.
      for (var f in element.fields) {
        var getterElement = f.getter;
        if (getterElement == null && accessorMap.containsKey(f.name)) {
          getterElement = accessorMap[f.name]
              .firstWhere((e) => e.isGetter, orElse: () => null);
        }
        var setterElement = f.setter;
        if (setterElement == null && accessorMap.containsKey(f.name)) {
          setterElement = accessorMap[f.name]
              .firstWhere((e) => e.isSetter, orElse: () => null);
        }
        _addSingleField(
            getterElement, setterElement, inheritedAccessorElements, f);
        accessorMap.remove(f.name);
      }

      // Now we only have inherited accessors who aren't associated with
      // anything in cls._fields.
      for (var fieldName in accessorMap.keys) {
        var elements = accessorMap[fieldName].toList();
        var getterElement =
            elements.firstWhere((e) => e.isGetter, orElse: () => null);
        var setterElement =
            elements.firstWhere((e) => e.isSetter, orElse: () => null);
        _addSingleField(
            getterElement, setterElement, inheritedAccessorElements);
      }
    }
    return _allFields;
  }

  @override
  Iterable<Field> get declaredFields => allFields.where((f) => !f.isInherited);

  /// Add a single Field to _fields.
  ///
  /// If [f] is not specified, pick the FieldElement from the PropertyAccessorElement
  /// whose enclosing class inherits from the other (defaulting to the getter)
  /// and construct a Field using that.
  void _addSingleField(
      PropertyAccessorElement getterElement,
      PropertyAccessorElement setterElement,
      Set<PropertyAccessorElement> inheritedAccessors,
      [FieldElement f]) {
    var getter =
        ContainerAccessor.from(getterElement, inheritedAccessors, this);
    var setter =
        ContainerAccessor.from(setterElement, inheritedAccessors, this);
    // Rebind getterElement/setterElement as ModelElement.from can resolve
    // MultiplyInheritedExecutableElements or resolve Members.
    getterElement = getter?.element;
    setterElement = setter?.element;
    assert(!(getter == null && setter == null));
    if (f == null) {
      // Pick an appropriate FieldElement to represent this element.
      // Only hard when dealing with a synthetic Field.
      if (getter != null && setter == null) {
        f = getterElement.variable;
      } else if (getter == null && setter != null) {
        f = setterElement.variable;
      } else {
        /* getter != null && setter != null */
        // In cases where a Field is composed of two Accessors defined in
        // different places in the inheritance chain, there are two FieldElements
        // for this single Field we're trying to compose.  Pick the one closest
        // to this class on the inheritance chain.
        if (setter.enclosingElement is Class &&
            (setter.enclosingElement as Class)
                ._isInheritingFrom(getter.enclosingElement)) {
          f = setterElement.variable;
        } else {
          f = getterElement.variable;
        }
      }
    }
    Field field;
    if ((getter == null || getter.isInherited) &&
        (setter == null || setter.isInherited)) {
      // Field is 100% inherited.
      field = ModelElement.fromPropertyInducingElement(f, library, packageGraph,
          enclosingContainer: this, getter: getter, setter: setter);
    } else {
      // Field is <100% inherited (could be half-inherited).
      // TODO(jcollins-g): Navigation is probably still confusing for
      // half-inherited fields when traversing the inheritance tree.  Make
      // this better, somehow.
      field = ModelElement.fromPropertyInducingElement(f, library, packageGraph,
          getter: getter, setter: setter);
    }
    _allFields.add(field);
  }

  Iterable<Method> _declaredMethods;

  @override
  Iterable<Method> get declaredMethods =>
      _declaredMethods ??= element.methods.map((e) {
        return ModelElement.from(e, library, packageGraph) as Method;
      });

  List<TypeParameter> _typeParameters;

  // a stronger hash?
  @override
  List<TypeParameter> get typeParameters {
    _typeParameters ??= element.typeParameters.map((f) {
      var lib = Library(f.enclosingElement.library, packageGraph);
      return ModelElement.from(f, lib, packageGraph) as TypeParameter;
    }).toList();
    return _typeParameters;
  }

  Iterable<Field> _instanceFields;

  @override
  Iterable<Field> get instanceFields =>
      _instanceFields ??= allFields.where((f) => !f.isStatic);

  @override
  bool get publicInheritedInstanceFields =>
      publicInstanceFields.every((f) => f.isInherited);

  @override
  Iterable<Field> get constantFields => allFields.where((f) => f.isConst);

  @override
  bool operator ==(Object o) =>
      o is Class &&
      name == o.name &&
      o.library.name == library.name &&
      o.library.package.name == library.package.name;
}
