// 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 'dart:convert';

import 'package:analyzer/dart/element/element2.dart';
import 'package:analyzer/source/line_info.dart';
// ignore: implementation_imports
import 'package:analyzer/src/dart/element/member.dart' show ExecutableMember;
import 'package:collection/collection.dart' show IterableExtension;
import 'package:dartdoc/src/element_type.dart';
import 'package:dartdoc/src/model/comment_referable.dart';
import 'package:dartdoc/src/model/kind.dart';
import 'package:dartdoc/src/model/model.dart';
import 'package:dartdoc/src/utils.dart';
import 'package:dartdoc/src/warnings.dart';

/// Getters and setters.
class Accessor extends ModelElement {

  @override
  final PropertyAccessorElement2 element;

  /// The combo ([Field] or [TopLevelVariable]) containing this accessor.
  ///
  /// Initialized in [Field]'s constructor and in [TopLevelVariable]'s
  /// constructor.
  // TODO(srawlins): This might be super fragile. This field should somehow be
  // initialized by code inside this library.
  late final GetterSetterCombo enclosingCombo;

  Accessor(this.element, super.library, super.packageGraph,
      {ExecutableMember? super.originalMember});

  @override
  CharacterLocation? get characterLocation => element.isSynthetic
      ? enclosingCombo.characterLocation
      : super.characterLocation;

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

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

  bool get isSynthetic => element.isSynthetic;

  /// The [enclosingCombo] where this element was defined.
  late final GetterSetterCombo definingCombo =
      getModelForElement(element.variable3!) as GetterSetterCombo;

  String get _sourceCode {
    if (!isSynthetic) {
      return super.sourceCode;
    }
    var modelNode = packageGraph.getModelNodeFor(definingCombo.element);
    return modelNode == null
        ? ''
        : const HtmlEscape().convert(modelNode.sourceCode);
  }

  @override
  String get sourceCode => _sourceCode;

  @override
  late final String documentationComment = () {
    if (isSynthetic) {
      /// Build a documentation comment for this accessor.
      return _hasSyntheticDocumentationComment
          ? definingCombo.documentationComment
          : '';
    }
    // TODO(srawlins): This doesn't seem right... the super value has delimiters
    // (like `///`), but this one doesn't?
    return stripCommentDelimiters(super.documentationComment);
  }();

  /// If this is a getter, assume we want synthetic documentation.
  ///
  /// If the [definingCombo] has a `nodoc` tag, we want synthetic documentation
  /// for a synthetic accessor just in case it is inherited somewhere down the
  /// line due to split inheritance.
  bool get _hasSyntheticDocumentationComment =>
      (isGetter || definingCombo.hasNodoc || _comboDocsAreIndependent) &&
      definingCombo.hasDocumentationComment;

  // If we're a setter, and a getter exists, do not add synthetic documentation
  // if the combo's documentation is actually derived from that getter.
  bool get _comboDocsAreIndependent {
    if (isSetter && definingCombo.hasGetter) {
      if (definingCombo.getter!.isSynthetic ||
          !definingCombo.documentationFrom.contains(this)) {
        return true;
      }
    }
    return false;
  }

  @override
  bool get hasDocumentationComment => isSynthetic
      ? _hasSyntheticDocumentationComment
      : element.documentationComment != null;

  @override
  void warn(
    PackageWarning kind, {
    String? message,
    Iterable<Locatable> referredFrom = const [],
    Iterable<String> extendedDebug = const [],
  }) {
    enclosingCombo.warn(kind,
        message: message,
        referredFrom: referredFrom,
        extendedDebug: extendedDebug);
  }

  @override
  ModelElement get enclosingElement => switch (element.enclosingElement2) {
        LibraryFragment enclosingCompilationUnit =>
          getModelForElement(enclosingCompilationUnit.element),
        _ => getModelFor(element.enclosingElement2, library)
      };

  @override
  String get filePath => enclosingCombo.filePath;

  @override
  String get aboveSidebarPath {
    final enclosingElement = this.enclosingElement;
    return switch (enclosingElement) {
      Container() => enclosingElement.sidebarPath,
      Library() => enclosingElement.sidebarPath,
      _ => throw StateError(
          'Enclosing element of $this should be Container or Library, but was '
          '${enclosingElement.runtimeType}')
    };
  }

  @override
  String? get belowSidebarPath => null;

  @override
  bool get isCanonical => enclosingCombo.isCanonical;

  @override
  String? get href => enclosingCombo.href;

  bool get isGetter => element is GetterElement;

  bool get isSetter => element is SetterElement;

  @override
  Kind get kind => Kind.accessor;

  /// Accessors should never be participating directly in comment reference
  /// lookups.
  @override
  Map<String, CommentReferable> get referenceChildren =>
      enclosingCombo.referenceChildren;

  /// Accessors should never be participating directly in comment reference
  /// lookups.
  @override
  Iterable<CommentReferable> get referenceParents =>
      enclosingCombo.referenceParents;
}

/// A getter or setter that is a member of a [Container].
class ContainerAccessor extends Accessor with ContainerMember, Inheritable {
  late final Container _enclosingElement;

  @override
  final bool isInherited;

  ContainerAccessor(super.element, super.library, super.packageGraph,
      [Container? enclosingElement])
      : isInherited = false {
    _enclosingElement = enclosingElement ?? super.enclosingElement as Container;
  }

  ContainerAccessor.inherited(
      super.element, super.library, super.packageGraph, this._enclosingElement,
      {super.originalMember})
      : isInherited = true;

  /// The index and values fields are never declared, and must be special cased.
  bool get _isEnumSynthetic =>
      enclosingCombo is EnumField && (name == 'index' || name == 'values');

  @override
  CharacterLocation? get characterLocation {
    if (_isEnumSynthetic) return enclosingElement.characterLocation;
    // TODO(jcollins-g): Remove the enclosingCombo case below once
    // https://github.com/dart-lang/sdk/issues/46154 is fixed.
    if (enclosingCombo is EnumField) return enclosingCombo.characterLocation;
    return super.characterLocation;
  }

  @override
  bool get isCovariant => isSetter && parameters.first.isCovariant;

  @override
  Container get enclosingElement => _enclosingElement;

  @override
  ContainerAccessor? get overriddenElement {
    assert(packageGraph.allLibrariesAdded);
    final parent = element.enclosingElement2;
    if (parent is! InterfaceElement2) {
      return null;
    }
    for (final supertype in parent.allSupertypes) {
      var accessor = isGetter
          ? supertype.getters
              .firstWhereOrNull((e) => e.lookupName == element.lookupName)
              ?.baseElement
          : supertype.setters
              .firstWhereOrNull((e) => e.lookupName == element.lookupName)
              ?.baseElement;
      if (accessor == null) {
        continue;
      }
      final parentContainer =
          getModelForElement(supertype.element3) as InheritingContainer;
      final possibleFields =
          parentContainer.declaredFields.where((f) => !f.isStatic);
      final fieldName = accessor.lookupName?.replaceFirst('=', '');
      final foundField =
          possibleFields.firstWhereOrNull((f) => f.element.name3 == fieldName);
      if (foundField == null) {
        continue;
      }
      final overridden = isGetter ? foundField.getter! : foundField.setter!;
      assert(!overridden.isInherited);
      return overridden;
    }
    return null;
  }
}
