// 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/source/line_info.dart';
import 'package:dartdoc/src/element_type.dart';
import 'package:dartdoc/src/model/attribute.dart';
import 'package:dartdoc/src/model/comment_referable.dart';
import 'package:dartdoc/src/model/kind.dart';
import 'package:dartdoc/src/model/model.dart';

class Method extends ModelElement
    with ContainerMember, Inheritable, TypeParameters {

  @override
  final MethodElement element;

  Container? _enclosingContainer;

  final bool _isInherited;

  @override
  late final List<TypeParameter> typeParameters;

  Method(this.element, super.library, super.packageGraph)
      : _isInherited = false {
    _calcTypeParameters();
  }

  Method.inherited(this.element, this._enclosingContainer, super.library,
      super.packageGraph,
      {ExecutableElement? super.originalElement})
      : _isInherited = true {
    _calcTypeParameters();
  }

  Method.providedByExtension(
    this.element,
    this._enclosingContainer,
    super.library,
    super.packageGraph, {
        ExecutableElement? super.originalElement,
  }) : _isInherited = false {
    _calcTypeParameters();
  }

  void _calcTypeParameters() {
    typeParameters = element.typeParameters.map((f) {
      return getModelFor(f, library) as TypeParameter;
    }).toList(growable: false);
  }

  @override
  CharacterLocation? get characterLocation {
    if (enclosingElement is Enum && name == 'toString') {
      // The toString() method on Enums is special, treated as not having
      // a definition location by the analyzer yet not being inherited, either.
      // Just directly override our location with the Enum definition --
      // this is OK because Enums can not inherit from each other nor
      // have their definitions split between files.
      return enclosingElement.characterLocation;
    }
    return super.characterLocation;
  }

  @override
  Container get enclosingElement => _enclosingContainer ??=
      getModelFor(element.enclosingElement!, library) as Container;

  @override
  String get aboveSidebarPath => enclosingElement.sidebarPath;

  @override
  String? get belowSidebarPath => null;

  String get fullkind {
    // A method cannot be abstract and static at the same time.
    if (element.isAbstract) return 'abstract $kind';
    if (element.isStatic) return 'static $kind';
    return kind.toString();
  }

  @override
  String? get href {
    assert(!identical(canonicalModelElement, this) ||
        canonicalEnclosingContainer == enclosingElement);
    return super.href;
  }

  @override
  bool get isInherited => _isInherited;

  bool get isOperator => false;

  bool get isProvidedByExtension =>
      element.enclosingElement is ExtensionElement;

  /// The [enclosingElement], which is expected to be an [Extension].
  Extension get enclosingExtension => enclosingElement as Extension;

  @override
  Set<Attribute> get attributes => {
        ...super.attributes,
        if (isInherited) Attribute.inherited,
      };

  bool get isStatic => element.isStatic;

  @override
  Kind get kind => Kind.method;

  @override
  ExecutableElement? get originalMember =>
      super.originalMember as ExecutableElement?;

  late final Callable modelType =
      getTypeFor((originalMember ?? element).type, library) as Callable;

  @override
  Method? get overriddenElement {
    if (_enclosingContainer is Extension ||
        element.enclosingElement is ExtensionElement) {
      return null;
    }
    var parent = element.enclosingElement as InterfaceElement;
    for (var t in parent.allSupertypes) {
      Element? e = t.getMethod(element.name ?? '');
      if (e != null) {
        assert(
          e.enclosingElement is InterfaceElement,
          'Expected "${e.enclosingElement?.name}" to be a InterfaceElement, '
          'but was ${e.enclosingElement.runtimeType}',
        );
        return getModelForElement(e) as Method?;
      }
    }
    return null;
  }

  /// Methods can not be covariant; always returns false.
  @override
  bool get isCovariant => false;

  Map<String, CommentReferable>? _referenceChildren;
  @override
  Map<String, CommentReferable> get referenceChildren {
    var from = documentationFrom.first as Method;
    if (!identical(this, from)) {
      return from.referenceChildren;
    }
    return _referenceChildren ??= <String, CommentReferable>{
      // If we want to include all types referred to in the signature of this
      // method, this is woefully incomplete. Notice we don't currently include
      // the element of the returned type itself, nor nested type arguments,
      // nor other nested types e.g. in the case of function types or record
      // types. But this is all being replaced with analyzer's resolution soon.
      ...modelType.returnType.typeArguments.modelElements
          .explicitOnCollisionWith(this),
      ...parameters.explicitOnCollisionWith(this),
      ...typeParameters.explicitOnCollisionWith(this),
    };
  }
}

extension on Iterable<ElementType> {
  /// The [ModelElement] associated with each type, for each type that is a
  /// [DefinedElementType].
  List<ModelElement> get modelElements => [
        for (var type in this)
          if (type is DefinedElementType) type.modelElement,
      ];
}
