// 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/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/type_provider.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/summary2/bundle_reader.dart';
import 'package:analyzer/src/summary2/linked_element_factory.dart';
import 'package:analyzer/src/summary2/linked_library_context.dart';
import 'package:analyzer/src/summary2/reference.dart';

/// The context of a unit - the context of the bundle, and the unit tokens.
class LinkedUnitContext {
  final LinkedLibraryContext libraryContext;
  final int indexInLibrary;
  final String? partUriStr;
  final String uriStr;
  final Reference reference;
  final bool isSynthetic;
  final CompilationUnit? unit;
  final UnitReader? unitReader;

  bool _hasDirectivesRead = false;

  LinkedUnitContext(this.libraryContext, this.indexInLibrary, this.partUriStr,
      this.uriStr, this.reference, this.isSynthetic,
      {required this.unit, required this.unitReader});

  CompilationUnitElementImpl get element {
    return reference.element as CompilationUnitElementImpl;
  }

  LinkedElementFactory get elementFactory => libraryContext.elementFactory;

  bool get hasPartOfDirective {
    for (var directive in unit_withDirectives.directives) {
      if (directive is PartOfDirective) {
        return true;
      }
    }
    return false;
  }

  /// Return `true` if this unit is a part of a bundle that is being linked.
  bool get isLinking => unitReader == null;

  TypeProvider get typeProvider {
    var libraryReference = libraryContext.reference;
    var libraryElement = libraryReference.element as LibraryElementImpl;
    return libraryElement.typeProvider;
  }

  CompilationUnit get unit_withDeclarations {
    unitReader?.readDeclarations();
    return unit!;
  }

  /// Ensure that [unit] has directives ready (because we are linking,
  /// and so always have full AST, or, if we are reading, we make sure
  /// that we have them read).
  CompilationUnit get unit_withDirectives {
    if (unitReader != null && !_hasDirectivesRead) {
      _hasDirectivesRead = true;
      unitReader!.readDirectives();
      var libraryElement =
          libraryContext.reference.element as LibraryElementImpl;
      for (var directive in unit!.directives) {
        if (directive is ExportDirective) {
          if (directive.element == null) {
            ExportElementImpl.forLinkedNode(libraryElement, directive);
          }
        } else if (directive is ImportDirective) {
          if (directive.element == null) {
            ImportElementImpl.forLinkedNode(libraryElement, directive);
          }
        }
      }
    }
    return unit!;
  }

  void applyResolution(AstNode node) {
    if (node is VariableDeclaration) {
      node = node.parent!.parent!;
    }
    if (node is HasAstLinkedContext) {
      var astLinkedContext = (node as HasAstLinkedContext).linkedContext;
      astLinkedContext?.applyResolution(this);
    }
  }

  void createGenericFunctionTypeElement(int id, GenericFunctionTypeImpl node) {
    var containerRef = this.reference.getChild('@genericFunctionType');
    var reference = containerRef.getChild('$id');
    var element = GenericFunctionTypeElementImpl.forLinkedNode(
      this.reference.element as ElementImpl,
      reference,
      node,
    );
    node.declaredElement = element;
  }

  int getCodeLength(AstNode node) {
    if (node is HasAstLinkedContext) {
      var linked = (node as HasAstLinkedContext).linkedContext;
      return linked != null ? linked.codeLength : node.length;
    }

    if (node is CompilationUnitImpl) {
      var data = node.summaryData as SummaryDataForCompilationUnit?;
      if (data != null) {
        return data.codeLength;
      } else {
        return node.length;
      }
    } else if (node is EnumConstantDeclaration) {
      return node.length;
    } else if (node is FormalParameter) {
      return node.length;
    } else if (node is TypeParameter) {
      return node.length;
    } else if (node is VariableDeclaration) {
      var parent2 = node.parent!.parent!;
      var linked = (parent2 as HasAstLinkedContext).linkedContext!;
      return linked.getVariableDeclarationCodeLength(node);
    }
    throw UnimplementedError('${node.runtimeType}');
  }

  int getCodeOffset(AstNode node) {
    if (node is HasAstLinkedContext) {
      var linked = (node as HasAstLinkedContext).linkedContext;
      return linked != null ? linked.codeOffset : node.offset;
    }

    if (node is CompilationUnit) {
      return 0;
    } else if (node is EnumConstantDeclaration) {
      return node.offset;
    } else if (node is FormalParameter) {
      return node.offset;
    } else if (node is TypeParameter) {
      return node.offset;
    } else if (node is VariableDeclaration) {
      var parent2 = node.parent!.parent!;
      var linked = (parent2 as HasAstLinkedContext).linkedContext!;
      return linked.getVariableDeclarationCodeOffset(node);
    }
    throw UnimplementedError('${node.runtimeType}');
  }

  List<ConstructorInitializer> getConstructorInitializers(
    ConstructorDeclaration node,
  ) {
    return node.initializers;
  }

  ConstructorName? getConstructorRedirected(ConstructorDeclaration node) {
    return node.redirectedConstructor;
  }

  List<ConstructorDeclarationImpl> getConstructors(AstNode node) {
    if (node is ClassOrMixinDeclaration) {
      return _getClassOrExtensionOrMixinMembers(node)
          .whereType<ConstructorDeclarationImpl>()
          .toList();
    }
    return const <ConstructorDeclarationImpl>[];
  }

  int getDirectiveOffset(Directive node) {
    return node.keyword.offset;
  }

  Comment? getDocumentationComment(AstNode node) {
    if (node is HasAstLinkedContext) {
      var linkedContext = (node as HasAstLinkedContext).linkedContext;
      linkedContext?.readDocumentationComment();
      return (node as AnnotatedNode).documentationComment;
    } else if (node is VariableDeclaration) {
      return getDocumentationComment(node.parent!.parent!);
    } else {
      throw UnimplementedError('${node.runtimeType}');
    }
  }

  String getFieldFormalParameterName(AstNode node) {
    if (node is DefaultFormalParameter) {
      return getFieldFormalParameterName(node.parameter);
    } else if (node is FieldFormalParameter) {
      return node.identifier.name;
    } else {
      throw StateError('${node.runtimeType}');
    }
  }

  List<VariableDeclaration> getFields(CompilationUnitMember node) {
    var fields = <VariableDeclaration>[];
    var members = _getClassOrExtensionOrMixinMembers(node);
    for (var member in members) {
      if (member is FieldDeclaration) {
        fields.addAll(member.fields.variables);
      }
    }
    return fields;
  }

  String getFormalParameterName(FormalParameter node) {
    if (node is DefaultFormalParameter) {
      return getFormalParameterName(node.parameter);
    } else if (node is NormalFormalParameter) {
      return node.identifier?.name ?? '';
    } else {
      throw UnimplementedError('${node.runtimeType}');
    }
  }

  List<FormalParameter>? getFormalParameters(AstNode node) {
    if (node is ConstructorDeclaration) {
      return node.parameters.parameters;
    } else if (node is FunctionDeclaration) {
      return getFormalParameters(node.functionExpression);
    } else if (node is FunctionExpression) {
      return node.parameters?.parameters;
    } else if (node is FormalParameter) {
      if (node is DefaultFormalParameter) {
        return getFormalParameters(node.parameter);
      } else if (node is FieldFormalParameter) {
        return node.parameters?.parameters;
      } else if (node is FunctionTypedFormalParameter) {
        return node.parameters.parameters;
      } else {
        return null;
      }
    } else if (node is FunctionTypeAlias) {
      return node.parameters.parameters;
    } else if (node is GenericFunctionType) {
      return node.parameters.parameters;
    } else if (node is MethodDeclaration) {
      return node.parameters?.parameters;
    } else {
      throw UnimplementedError('${node.runtimeType}');
    }
  }

  ImplementsClause? getImplementsClause(AstNode node) {
    if (node is ClassDeclaration) {
      return node.implementsClause;
    } else if (node is ClassTypeAlias) {
      return node.implementsClause;
    } else if (node is MixinDeclaration) {
      return node.implementsClause;
    } else {
      throw UnimplementedError('${node.runtimeType}');
    }
  }

  Expression? getInitializer(AstNode node) {
    if (node is DefaultFormalParameter) {
      return node.defaultValue;
    } else if (node is VariableDeclaration) {
      return node.initializer;
    } else {
      throw StateError('${node.runtimeType}');
    }
  }

  LibraryLanguageVersion getLanguageVersion(CompilationUnit node) {
    return (node as CompilationUnitImpl).languageVersion!;
  }

  Comment? getLibraryDocumentationComment() {
    for (var directive in unit_withDirectives.directives) {
      if (directive is LibraryDirectiveImpl) {
        var data = directive.summaryData as SummaryDataForLibraryDirective;
        data.readDocumentationComment();
        return directive.documentationComment;
      }
    }
    return null;
  }

  List<Annotation> getLibraryMetadata() {
    unit_withDirectives;
    unitReader!.applyDirectivesResolution(this);
    for (var directive in unit!.directives) {
      if (directive is LibraryDirective) {
        return directive.metadata;
      }
    }
    return const <Annotation>[];
  }

  List<Annotation> getMetadata(AstNode node) {
    if (node is ClassDeclaration) {
      return node.metadata;
    } else if (node is ClassTypeAlias) {
      return node.metadata;
    } else if (node is CompilationUnit) {
      assert(node == unit);
      if (indexInLibrary != 0) {
        return _getPartDirectiveAnnotation();
      } else {
        return const <Annotation>[];
      }
    } else if (node is ConstructorDeclaration) {
      return node.metadata;
    } else if (node is DefaultFormalParameter) {
      return getMetadata(node.parameter);
    } else if (node is Directive) {
      return node.metadata;
    } else if (node is EnumConstantDeclaration) {
      return node.metadata;
    } else if (node is EnumDeclaration) {
      return node.metadata;
    } else if (node is ExtensionDeclaration) {
      return node.metadata;
    } else if (node is FormalParameter) {
      return node.metadata;
    } else if (node is FunctionDeclaration) {
      return node.metadata;
    } else if (node is FunctionTypeAlias) {
      return node.metadata;
    } else if (node is GenericTypeAlias) {
      return node.metadata;
    } else if (node is MethodDeclaration) {
      return node.metadata;
    } else if (node is MixinDeclaration) {
      return node.metadata;
    } else if (node is TypeParameter) {
      return node.metadata;
    } else if (node is VariableDeclaration) {
      var parent2 = node.parent!.parent!;
      if (parent2 is FieldDeclaration) {
        return parent2.metadata;
      } else if (parent2 is TopLevelVariableDeclaration) {
        return parent2.metadata;
      }
    }
    return const <Annotation>[];
  }

  List<MethodDeclaration> getMethods(CompilationUnitMember node) {
    return _getClassOrExtensionOrMixinMembers(node)
        .whereType<MethodDeclaration>()
        .toList();
  }

  int getNameOffset(AstNode node) {
    if (node is ConstructorDeclaration) {
      if (node.name != null) {
        return node.name!.offset;
      } else {
        return node.returnType.offset;
      }
    } else if (node is EnumConstantDeclaration) {
      return node.name.offset;
    } else if (node is ExtensionDeclaration) {
      return node.name?.offset ?? -1;
    } else if (node is FormalParameter) {
      return node.identifier?.offset ?? -1;
    } else if (node is MethodDeclaration) {
      return node.name.offset;
    } else if (node is NamedCompilationUnitMember) {
      return node.name.offset;
    } else if (node is TypeParameter) {
      return node.name.offset;
    } else if (node is VariableDeclaration) {
      return node.name.offset;
    }
    throw UnimplementedError('${node.runtimeType}');
  }

  /// Return the actual return type for the [node] - explicit or inferred.
  DartType getReturnType(AstNode node) {
    if (node is GenericFunctionType) {
      return node.returnType?.type ?? DynamicTypeImpl.instance;
    }
    throw UnimplementedError('${node.runtimeType}');
  }

  TypeName? getSuperclass(AstNode node) {
    if (node is ClassDeclaration) {
      return node.extendsClause?.superclass;
    } else if (node is ClassTypeAlias) {
      return node.superclass;
    } else {
      throw StateError('${node.runtimeType}');
    }
  }

  TypeParameterList? getTypeParameters2(AstNode node) {
    if (node is ClassDeclaration) {
      return node.typeParameters;
    } else if (node is ClassTypeAlias) {
      return node.typeParameters;
    } else if (node is ConstructorDeclaration) {
      return null;
    } else if (node is DefaultFormalParameter) {
      return getTypeParameters2(node.parameter);
    } else if (node is ExtensionDeclaration) {
      return node.typeParameters;
    } else if (node is FieldFormalParameter) {
      return node.typeParameters;
    } else if (node is FunctionDeclaration) {
      return getTypeParameters2(node.functionExpression);
    } else if (node is FunctionExpression) {
      return node.typeParameters;
    } else if (node is FunctionTypedFormalParameter) {
      return node.typeParameters;
    } else if (node is FunctionTypeAlias) {
      return node.typeParameters;
    } else if (node is GenericFunctionType) {
      return node.typeParameters;
    } else if (node is GenericTypeAlias) {
      return node.typeParameters;
    } else if (node is MethodDeclaration) {
      return node.typeParameters;
    } else if (node is MixinDeclaration) {
      return node.typeParameters;
    } else if (node is SimpleFormalParameter) {
      return null;
    } else {
      throw UnimplementedError('${node.runtimeType}');
    }
  }

  WithClause? getWithClause(AstNode node) {
    if (node is ClassDeclaration) {
      return node.withClause;
    } else if (node is ClassTypeAlias) {
      return node.withClause;
    } else {
      throw UnimplementedError('${node.runtimeType}');
    }
  }

  bool hasImplicitReturnType(AstNode node) {
    if (node is FunctionDeclaration) {
      return node.returnType == null;
    }
    if (node is MethodDeclaration) {
      return node.returnType == null;
    }
    return false;
  }

  bool hasImplicitType(AstNode node) {
    if (node is DefaultFormalParameter) {
      return hasImplicitType(node.parameter);
    } else if (node is SimpleFormalParameter) {
      return node.type == null;
    } else if (node is VariableDeclaration) {
      var parent = node.parent as VariableDeclarationList;
      return parent.type == null;
    }
    return false;
  }

  bool hasInitializer(VariableDeclarationImpl node) {
    return node.initializer != null || node.hasInitializer;
  }

  bool isAbstract(AstNode node) {
    if (node is ClassDeclaration) {
      return node.isAbstract;
    } else if (node is ClassTypeAlias) {
      return node.isAbstract;
    } else if (node is ConstructorDeclaration) {
      return false;
    } else if (node is FunctionDeclaration) {
      return false;
    } else if (node is MethodDeclaration) {
      return node.isAbstract;
    } else if (node is VariableDeclaration) {
      var parent = node.parent;
      if (parent is VariableDeclarationList) {
        var grandParent = parent.parent;
        if (grandParent is FieldDeclaration) {
          return grandParent.abstractKeyword != null;
        } else {
          throw UnimplementedError('${grandParent.runtimeType}');
        }
      } else {
        throw UnimplementedError('${parent.runtimeType}');
      }
    } else if (node is EnumConstantDeclaration) {
      return false;
    }
    throw UnimplementedError('${node.runtimeType}');
  }

  bool isAsynchronous(AstNode node) {
    if (node is ConstructorDeclaration) {
      return false;
    } else if (node is FunctionDeclaration) {
      return isAsynchronous(node.functionExpression);
    } else if (node is FunctionExpression) {
      return node.body!.isAsynchronous;
    } else if (node is MethodDeclaration) {
      return node.body.isAsynchronous;
    } else {
      throw UnimplementedError('${node.runtimeType}');
    }
  }

  bool isConst(AstNode node) {
    if (node is FormalParameter) {
      return node.isConst;
    }
    if (node is VariableDeclaration) {
      var parent = node.parent as VariableDeclarationList;
      return parent.isConst;
    }
    throw UnimplementedError('${node.runtimeType}');
  }

  bool isExplicitlyCovariant(AstNode node) {
    if (node is DefaultFormalParameter) {
      return isExplicitlyCovariant(node.parameter);
    } else if (node is EnumConstantDeclaration) {
      return false;
    } else if (node is FormalParameter) {
      return node.covariantKeyword != null;
    } else if (node is VariableDeclaration) {
      var parent2 = node.parent!.parent!;
      return parent2 is FieldDeclaration && parent2.covariantKeyword != null;
    } else {
      throw StateError('${node.runtimeType}');
    }
  }

  bool isExternal(AstNode node) {
    if (node is ConstructorDeclaration) {
      return node.externalKeyword != null;
    } else if (node is FunctionDeclaration) {
      return node.externalKeyword != null;
    } else if (node is MethodDeclaration) {
      return node.externalKeyword != null || node.body is NativeFunctionBody;
    } else if (node is VariableDeclaration) {
      var parent = node.parent;
      if (parent is VariableDeclarationList) {
        var grandParent = parent.parent;
        if (grandParent is FieldDeclaration) {
          return grandParent.externalKeyword != null;
        } else if (grandParent is TopLevelVariableDeclaration) {
          return grandParent.externalKeyword != null;
        } else {
          throw UnimplementedError('${grandParent.runtimeType}');
        }
      } else {
        throw UnimplementedError('${parent.runtimeType}');
      }
    } else if (node is EnumConstantDeclaration) {
      return false;
    } else {
      throw UnimplementedError('${node.runtimeType}');
    }
  }

  bool isFinal(AstNode node) {
    if (node is EnumConstantDeclaration) {
      return false;
    }
    if (node is VariableDeclaration) {
      var parent = node.parent as VariableDeclarationList;
      return parent.isFinal;
    }
    throw UnimplementedError('${node.runtimeType}');
  }

  bool isGenerator(AstNode node) {
    if (node is ConstructorDeclaration) {
      return false;
    } else if (node is FunctionDeclaration) {
      return isGenerator(node.functionExpression);
    } else if (node is FunctionExpression) {
      return node.body!.isGenerator;
    } else if (node is MethodDeclaration) {
      return node.body.isGenerator;
    } else {
      throw UnimplementedError('${node.runtimeType}');
    }
  }

  bool isGetter(AstNode node) {
    if (node is FunctionDeclaration) {
      return node.isGetter;
    } else if (node is MethodDeclaration) {
      return node.isGetter;
    } else {
      throw StateError('${node.runtimeType}');
    }
  }

  bool isLate(AstNode node) {
    if (node is VariableDeclaration) {
      return node.isLate;
    }
    if (node is EnumConstantDeclaration) {
      return false;
    }
    throw UnimplementedError('${node.runtimeType}');
  }

  bool isNative(AstNode node) {
    if (node is MethodDeclaration) {
      return node.body is NativeFunctionBody;
    } else {
      throw UnimplementedError('${node.runtimeType}');
    }
  }

  bool isSetter(AstNode node) {
    if (node is FunctionDeclaration) {
      return node.isSetter;
    } else if (node is MethodDeclaration) {
      return node.isSetter;
    } else {
      throw StateError('${node.runtimeType}');
    }
  }

  bool isStatic(AstNode node) {
    if (node is FunctionDeclaration) {
      return true;
    } else if (node is MethodDeclaration) {
      return node.modifierKeyword != null;
    } else if (node is VariableDeclaration) {
      var parent2 = node.parent!.parent!;
      return parent2 is FieldDeclaration && parent2.isStatic;
    }
    throw UnimplementedError('${node.runtimeType}');
  }

  bool shouldBeConstFieldElement(AstNode node) {
    if (node is VariableDeclaration) {
      var variableList = node.parent as VariableDeclarationList;
      if (variableList.isConst) return true;

      var fieldDeclaration = variableList.parent as FieldDeclaration;
      if (fieldDeclaration.staticKeyword != null) return false;

      if (variableList.isFinal) {
        var class_ = fieldDeclaration.parent;
        if (class_ is ClassDeclaration) {
          var hasLinkedContext = class_ as HasAstLinkedContext;
          var linkedContext = hasLinkedContext.linkedContext;
          // TODO(scheglov) Get rid of this check, exists only for linking.
          // Maybe we should pre-create all elements before linking.
          if (linkedContext != null) {
            return linkedContext.isClassWithConstConstructor;
          } else {
            for (var member in class_.members) {
              if (member is ConstructorDeclaration &&
                  member.constKeyword != null) {
                return true;
              }
            }
          }
        }
      }
    }
    return false;
  }

  List<VariableDeclaration> topLevelVariables(CompilationUnit unit) {
    var variables = <VariableDeclaration>[];
    for (var declaration in unit.declarations) {
      if (declaration is TopLevelVariableDeclaration) {
        variables.addAll(declaration.variables.variables);
      }
    }
    return variables;
  }

  List<ClassMember> _getClassOrExtensionOrMixinMembers(
    CompilationUnitMember node,
  ) {
    var linkedContext = (node as HasAstLinkedContext).linkedContext;
    if (linkedContext != null) {
      return linkedContext.classMembers;
    } else {
      if (node is ClassDeclaration) {
        return node.members;
      } else if (node is ClassTypeAlias) {
        return <ClassMember>[];
      } else if (node is ExtensionDeclaration) {
        return node.members;
      } else if (node is MixinDeclaration) {
        return node.members;
      } else {
        throw StateError('${node.runtimeType}');
      }
    }
  }

  NodeList<Annotation> _getPartDirectiveAnnotation() {
    var definingContext = libraryContext.definingUnit;
    var definingUnit = definingContext.unit_withDirectives;
    var partDirectiveIndex = 0;
    for (var directive in definingUnit.directives) {
      if (directive is PartDirective) {
        partDirectiveIndex++;
        if (partDirectiveIndex == indexInLibrary) {
          return directive.metadata;
        }
      }
    }
    throw StateError('Expected to find $indexInLibrary part directive.');
  }
}
