// 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 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/analysis/session.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/resolver/variance.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:collection/collection.dart';
import 'package:meta/meta.dart';
import 'package:path/path.dart';

/// The class `ElementFactory` defines utility methods used to create elements
/// for testing purposes. The elements that are created are complete in the
/// sense that as much of the element model as can be created, given the
/// provided information, has been created.
@internal
class ElementFactory {
  /// The element representing the class 'Object'.
  static ClassElementImpl? _objectElement;
  static InterfaceType? _objectType;

  static ClassElementImpl get object {
    return _objectElement ??= classElement("Object", null);
  }

  static InterfaceType get objectType {
    return _objectType ??= object.instantiate(
      typeArguments: const [],
      nullabilitySuffix: NullabilitySuffix.star,
    );
  }

  static ClassElementImpl classElement(
      String typeName, InterfaceType? superclassType,
      [List<String>? parameterNames]) {
    ClassElementImpl element = ClassElementImpl(typeName, 0);
    element.constructors = const <ConstructorElementImpl>[];
    element.supertype = superclassType;
    if (parameterNames != null) {
      element.typeParameters = typeParameters(parameterNames);
    }
    return element;
  }

  static ClassElementImpl classElement2(String typeName,
          [List<String>? parameterNames]) =>
      classElement(typeName, objectType, parameterNames);

  static ClassElementImpl classElement3({
    required String name,
    List<TypeParameterElement>? typeParameters,
    List<String> typeParameterNames = const [],
    InterfaceType? supertype,
    List<InterfaceType> mixins = const [],
    List<InterfaceType> interfaces = const [],
  }) {
    typeParameters ??= ElementFactory.typeParameters(typeParameterNames);
    supertype ??= objectType;

    var element = ClassElementImpl(name, 0);
    element.typeParameters = typeParameters;
    element.supertype = supertype;
    element.mixins = mixins;
    element.interfaces = interfaces;
    element.constructors = const <ConstructorElementImpl>[];
    return element;
  }

  static ClassElementImpl classElement4(String typeName,
          {bool isBase = false,
          bool isInterface = false,
          bool isFinal = false,
          bool isSealed = false,
          bool isMixinClass = false}) =>
      classElement2(typeName)
        ..isBase = isBase
        ..isInterface = isInterface
        ..isFinal = isFinal
        ..isSealed = isSealed
        ..isMixinClass = isMixinClass;

  static ClassElementImpl classTypeAlias(
      String typeName, InterfaceType superclassType,
      [List<String>? parameterNames]) {
    ClassElementImpl element =
        classElement(typeName, superclassType, parameterNames);
    element.isMixinApplication = true;
    return element;
  }

  static ClassElementImpl classTypeAlias2(String typeName,
          [List<String>? parameterNames]) =>
      classTypeAlias(typeName, objectType, parameterNames);

  static CompilationUnitElementImpl compilationUnit({
    required Source source,
    Source? librarySource,
    LineInfo? lineInfo,
  }) {
    return CompilationUnitElementImpl(
      source: source,
      librarySource: librarySource ?? source,
      lineInfo: lineInfo ?? LineInfo([0]),
    );
  }

  static ConstLocalVariableElementImpl constLocalVariableElement(String name) =>
      ConstLocalVariableElementImpl(name, 0);

  static ConstructorElementImpl constructorElement(
      ClassElement definingClass, String? name, bool isConst,
      [List<DartType> argumentTypes = const []]) {
    var offset = name == null ? -1 : 0;
    // A constructor declared as `C.new` is unnamed, and is modeled as such.
    var constructor = name == null || name == 'new'
        ? ConstructorElementImpl('', offset)
        : ConstructorElementImpl(name, offset);
    if (name != null) {
      if (name.isEmpty) {
        constructor.nameEnd = definingClass.name.length;
      } else {
        constructor.periodOffset = definingClass.name.length;
        constructor.nameEnd = definingClass.name.length + name.length + 1;
      }
    }
    constructor.isSynthetic = name == null;
    constructor.isConst = isConst;
    constructor.parameters = _requiredParameters(argumentTypes);
    constructor.enclosingElement = definingClass;
    if (!constructor.isSynthetic) {
      constructor.constantInitializers = <ConstructorInitializer>[];
    }
    return constructor;
  }

  static ConstructorElementImpl constructorElement2(
          ClassElement definingClass, String? name,
          [List<DartType> argumentTypes = const []]) =>
      constructorElement(definingClass, name, false, argumentTypes);

  static FieldElementImpl fieldElement(
      String name, bool isStatic, bool isFinal, bool isConst, DartType type,
      {Expression? initializer}) {
    FieldElementImpl field =
        isConst ? ConstFieldElementImpl(name, 0) : FieldElementImpl(name, 0);
    field.isConst = isConst;
    field.isFinal = isFinal;
    field.isStatic = isStatic;
    field.type = type;
    if (isConst) {
      (field as ConstFieldElementImpl).constantInitializer = initializer;
    }
    PropertyAccessorElementImpl_ImplicitGetter(field);
    if (!isConst && !isFinal) {
      PropertyAccessorElementImpl_ImplicitSetter(field);
    }
    return field;
  }

  static FieldFormalParameterElementImpl fieldFormalParameter(
          Identifier name) =>
      FieldFormalParameterElementImpl(
        name: name.name,
        nameOffset: name.offset,
        parameterKind: ParameterKind.REQUIRED,
      );

  /// Destroy any static state retained by [ElementFactory].  This should be
  /// called from the `setUp` method of any tests that use [ElementFactory], in
  /// order to ensure that state is not shared between multiple tests.
  static void flushStaticState() {
    _objectElement = null;
  }

  static PropertyAccessorElementImpl getterElement(
      String name, bool isStatic, DartType type) {
    FieldElementImpl field = FieldElementImpl(name, -1);
    field.isStatic = isStatic;
    field.isSynthetic = true;
    field.type = type;
    field.isFinal = true;
    PropertyAccessorElementImpl getter = PropertyAccessorElementImpl(name, 0);
    getter.isSynthetic = false;
    getter.isGetter = true;
    getter.variable = field;
    getter.returnType = type;
    getter.isStatic = isStatic;
    field.getter = getter;
    return getter;
  }

  static LibraryElementImpl library(AnalysisContext context, String libraryName,
      {FeatureSet? featureSet}) {
    FeatureSet features = featureSet ?? FeatureSet.latestLanguageVersion();
    String fileName = "/$libraryName.dart";
    CompilationUnitElementImpl unit = compilationUnit(
      source: NonExistingSource(fileName, toUri(fileName)),
    );
    LibraryElementImpl library = LibraryElementImpl(
      context,
      _MockAnalysisSession(),
      libraryName,
      0,
      libraryName.length,
      features,
    );
    library.definingCompilationUnit = unit;
    return library;
  }

  static LocalVariableElementImpl localVariableElement(Identifier name) =>
      LocalVariableElementImpl(name.name, name.offset);

  static LocalVariableElementImpl localVariableElement2(String name) =>
      LocalVariableElementImpl(name, 0);

  static MethodElementImpl methodElement(String methodName, DartType returnType,
      [List<DartType> argumentTypes = const []]) {
    MethodElementImpl method = MethodElementImpl(methodName, 0);
    method.parameters = _requiredParameters(argumentTypes);
    method.returnType = returnType;
    return method;
  }

  static MethodElementImpl methodElementWithParameters(
      ClassElement enclosingElement,
      String methodName,
      DartType returnType,
      List<ParameterElement> parameters) {
    MethodElementImpl method = MethodElementImpl(methodName, 0);
    method.enclosingElement = enclosingElement;
    method.parameters = parameters;
    method.returnType = returnType;
    return method;
  }

  static MixinElementImpl mixinElement({
    required String name,
    List<TypeParameterElement>? typeParameters,
    List<String> typeParameterNames = const [],
    List<InterfaceType> constraints = const [],
    List<InterfaceType> interfaces = const [],
  }) {
    typeParameters ??= ElementFactory.typeParameters(typeParameterNames);

    if (constraints.isEmpty) {
      constraints = [objectType];
    }

    var element = MixinElementImpl(name, 0);
    element.typeParameters = typeParameters;
    element.superclassConstraints = constraints;
    element.interfaces = interfaces;
    element.constructors = const <ConstructorElementImpl>[];
    return element;
  }

  static MixinElementImpl mixinElement2(String name,
          {bool isBase = false,
          bool isInterface = false,
          bool isFinal = false,
          bool isSealed = false}) =>
      mixinElement(name: name)
        ..isBase = isBase
        ..isInterface = isInterface
        ..isFinal = isFinal
        ..isSealed = isSealed;

  static ParameterElementImpl namedParameter(String name) {
    return ParameterElementImpl(
      name: name,
      nameOffset: 0,
      parameterKind: ParameterKind.NAMED,
    );
  }

  static ParameterElementImpl namedParameter2(String name, DartType type) {
    var parameter = ParameterElementImpl(
      name: name,
      nameOffset: 0,
      parameterKind: ParameterKind.NAMED,
    );
    parameter.type = type;
    return parameter;
  }

  static ParameterElementImpl positionalParameter(String name) {
    return ParameterElementImpl(
      name: name,
      nameOffset: 0,
      parameterKind: ParameterKind.POSITIONAL,
    );
  }

  static ParameterElementImpl positionalParameter2(String name, DartType type) {
    var parameter = ParameterElementImpl(
      name: name,
      nameOffset: 0,
      parameterKind: ParameterKind.POSITIONAL,
    );
    parameter.type = type;
    return parameter;
  }

  static PrefixElementImpl prefix(String name) => PrefixElementImpl(name, 0);

  static ParameterElementImpl requiredParameter(String name) {
    return ParameterElementImpl(
      name: name,
      nameOffset: 0,
      parameterKind: ParameterKind.REQUIRED,
    );
  }

  static ParameterElementImpl requiredParameter2(String name, DartType type) {
    var parameter = ParameterElementImpl(
      name: name,
      nameOffset: 0,
      parameterKind: ParameterKind.REQUIRED,
    );
    parameter.type = type;
    return parameter;
  }

  static PropertyAccessorElementImpl setterElement(
      String name, bool isStatic, DartType type) {
    FieldElementImpl field = FieldElementImpl(name, -1);
    field.isStatic = isStatic;
    field.isSynthetic = true;
    field.type = type;
    PropertyAccessorElementImpl getter = PropertyAccessorElementImpl(name, -1);
    getter.isGetter = true;
    getter.variable = field;
    getter.returnType = type;
    field.getter = getter;
    ParameterElementImpl parameter = requiredParameter2("a", type);
    PropertyAccessorElementImpl setter = PropertyAccessorElementImpl(name, -1);
    setter.isSetter = true;
    setter.isSynthetic = true;
    setter.variable = field;
    setter.parameters = <ParameterElement>[parameter];
    setter.returnType = VoidTypeImpl.instance;
    setter.isStatic = isStatic;
    field.setter = setter;
    return setter;
  }

  static TopLevelVariableElementImpl topLevelVariableElement(Identifier name) =>
      TopLevelVariableElementImpl(name.name, name.offset);

  static TypeParameterElementImpl typeParameterElement(String name) {
    return TypeParameterElementImpl(name, 0);
  }

  static List<TypeParameterElement> typeParameters(List<String> names) {
    return names.map((name) => typeParameterWithType(name)).toList();
  }

  static TypeParameterElementImpl typeParameterWithType(String name,
      [DartType? bound, Variance? variance]) {
    TypeParameterElementImpl typeParameter = typeParameterElement(name);
    typeParameter.bound = bound;
    typeParameter.variance = variance;
    return typeParameter;
  }

  static List<ParameterElementImpl> _requiredParameters(
      List<DartType> argumentTypes) {
    var parameters = argumentTypes.mapIndexed((index, type) {
      var parameter = ParameterElementImpl(
        name: 'a$index',
        nameOffset: index,
        parameterKind: ParameterKind.REQUIRED,
      );
      parameter.type = type;
      return parameter;
    }).toList();
    return parameters;
  }
}

class _MockAnalysisSession implements AnalysisSessionImpl {
  @override
  dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}
