// Copyright (c) 2021, 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:kernel/ast.dart';
import 'package:macros/macros.dart' as macro;
import 'package:macros/src/executor.dart' as macro;
import 'package:macros/src/executor/exception_impls.dart' as macro;
import 'package:macros/src/executor/introspection_impls.dart' as macro;

import '../../base/uris.dart';
import '../../builder/declaration_builders.dart';
import '../../builder/formal_parameter_builder.dart';
import '../../builder/library_builder.dart';
import '../../builder/member_builder.dart';
import '../../builder/nullability_builder.dart';
import '../../builder/type_builder.dart';
import 'introspectors.dart';

// Coverage-ignore(suite): Not run.
abstract class IdentifierImpl extends macro.IdentifierImpl {
  IdentifierImpl({
    required int id,
    required String name,
  }) : super(id: id, name: name);

  macro.ResolvedIdentifier resolveIdentifier();

  Future<macro.TypeDeclaration> resolveTypeDeclaration(
      MacroIntrospection macroIntrospection);

  DartType buildType(
      NullabilityBuilder nullabilityBuilder, List<DartType> typeArguments);

  macro.ResolvedIdentifier _resolveTypeDeclarationIdentifier(
      TypeDeclarationBuilder? typeDeclarationBuilder) {
    if (typeDeclarationBuilder != null) {
      Uri? uri;
      switch (typeDeclarationBuilder) {
        case ClassBuilder():
          uri = typeDeclarationBuilder.libraryBuilder.origin.importUri;
        case TypeAliasBuilder():
          uri = typeDeclarationBuilder.libraryBuilder.origin.importUri;
        case ExtensionTypeDeclarationBuilder():
          uri = typeDeclarationBuilder.libraryBuilder.origin.importUri;
        case NominalParameterBuilder():
        // TODO(johnniwinther): Handle this case.
        case StructuralParameterBuilder():
        // TODO(johnniwinther): Handle this case.
        case ExtensionBuilder():
        // TODO(johnniwinther): Handle this case.
        case InvalidTypeDeclarationBuilder():
        case BuiltinTypeDeclarationBuilder():
          if (name == 'dynamic') {
            uri = dartCore;
          }
        // TODO(johnniwinther): How should we handle this case?
        case OmittedTypeDeclarationBuilder():
      }
      return new macro.ResolvedIdentifier(
          kind: macro.IdentifierKind.topLevelMember,
          name: name,
          staticScope: null,
          uri: uri);
    } else {
      throw new StateError('Unable to resolve identifier $this');
    }
  }

  macro.TypeDeclaration _resolveTypeDeclaration(
      MacroIntrospection macroIntrospection,
      TypeDeclarationBuilder? typeDeclarationBuilder) {
    switch (typeDeclarationBuilder) {
      case ClassBuilder():
        return macroIntrospection.getClassDeclaration(typeDeclarationBuilder);
      case ExtensionTypeDeclarationBuilder():
        return macroIntrospection
            .getExtensionTypeDeclaration(typeDeclarationBuilder);
      case TypeAliasBuilder():
        return macroIntrospection
            .getTypeAliasDeclaration(typeDeclarationBuilder);
      case NominalParameterBuilder():
      case StructuralParameterBuilder():
      case ExtensionBuilder():
      case InvalidTypeDeclarationBuilder():
      case BuiltinTypeDeclarationBuilder():
      // TODO(johnniwinther): How should we handle this case?
      case OmittedTypeDeclarationBuilder():
      case null:
        // TODO(johnniwinther): Handle these cases.
        throw new macro.MacroImplementationExceptionImpl(
            'Unable to resolve identifier $this');
    }
  }

  macro.Declaration resolveDeclaration(MacroIntrospection macroIntrospection) {
    throw new UnimplementedError('${runtimeType}.resolveDeclaration');
  }
}

// Coverage-ignore(suite): Not run.
class TypeBuilderIdentifier extends IdentifierImpl {
  final TypeBuilder typeBuilder;
  final LibraryBuilder libraryBuilder;

  TypeBuilderIdentifier({
    required this.typeBuilder,
    required this.libraryBuilder,
    required int id,
    required String name,
  }) : super(id: id, name: name);

  @override
  macro.ResolvedIdentifier resolveIdentifier() {
    return _resolveTypeDeclarationIdentifier(typeBuilder.declaration);
  }

  @override
  DartType buildType(
      NullabilityBuilder nullabilityBuilder, List<DartType> typeArguments) {
    return typeBuilder.declaration!.buildAliasedTypeWithBuiltArguments(
        libraryBuilder,
        nullabilityBuilder.build(),
        typeArguments,
        TypeUse.macroTypeArgument,
        // TODO(johnniwinther): How should handle malbounded types here? Should
        // we report an error on the annotation?
        missingUri,
        TreeNode.noOffset,
        hasExplicitTypeArguments: true);
  }

  @override
  Future<macro.TypeDeclaration> resolveTypeDeclaration(
      MacroIntrospection macroIntrospection) {
    return new Future.value(
        _resolveTypeDeclaration(macroIntrospection, typeBuilder.declaration));
  }

  @override
  macro.Declaration resolveDeclaration(MacroIntrospection macroIntrospection) {
    return _resolveTypeDeclaration(macroIntrospection, typeBuilder.declaration);
  }

  @override
  String toString() {
    return "TypeBuilderIdentifier("
        "typeBuilder=$typeBuilder,libraryBuilder=$libraryBuilder)";
  }
}

// Coverage-ignore(suite): Not run.
class TypeDeclarationBuilderIdentifier extends IdentifierImpl {
  final TypeDeclarationBuilder typeDeclarationBuilder;
  final LibraryBuilder libraryBuilder;

  TypeDeclarationBuilderIdentifier({
    required this.typeDeclarationBuilder,
    required this.libraryBuilder,
    required int id,
    required String name,
  }) : super(id: id, name: name);

  @override
  macro.ResolvedIdentifier resolveIdentifier() {
    return _resolveTypeDeclarationIdentifier(typeDeclarationBuilder);
  }

  @override
  Future<macro.TypeDeclaration> resolveTypeDeclaration(
      MacroIntrospection macroIntrospection) {
    return new Future.value(
        _resolveTypeDeclaration(macroIntrospection, typeDeclarationBuilder));
  }

  @override
  macro.Declaration resolveDeclaration(MacroIntrospection macroIntrospection) {
    return _resolveTypeDeclaration(macroIntrospection, typeDeclarationBuilder);
  }

  @override
  DartType buildType(
      NullabilityBuilder nullabilityBuilder, List<DartType> typeArguments) {
    return typeDeclarationBuilder.buildAliasedTypeWithBuiltArguments(
        libraryBuilder,
        nullabilityBuilder.build(),
        // TODO(johnniwinther): How should handle malbounded types here? Should
        // we report an error on the annotation?
        typeArguments,
        TypeUse.macroTypeArgument,
        missingUri,
        TreeNode.noOffset,
        hasExplicitTypeArguments: true);
  }
}

// Coverage-ignore(suite): Not run.
class MemberBuilderIdentifier extends IdentifierImpl {
  final MemberBuilder memberBuilder;

  MemberBuilderIdentifier(
      {required this.memberBuilder, required int id, required String name})
      : super(id: id, name: name);

  @override
  macro.ResolvedIdentifier resolveIdentifier() {
    Uri? uri;
    String? staticScope;
    macro.IdentifierKind kind;
    if (memberBuilder.isTopLevel) {
      uri = memberBuilder.libraryBuilder.origin.importUri;
      kind = macro.IdentifierKind.topLevelMember;
    } else if (memberBuilder.isStatic || memberBuilder.isConstructor) {
      ClassBuilder classBuilder = memberBuilder.classBuilder!;
      staticScope = classBuilder.name;
      uri = classBuilder.libraryBuilder.origin.importUri;
      kind = macro.IdentifierKind.staticInstanceMember;
    } else {
      kind = macro.IdentifierKind.instanceMember;
    }
    return new macro.ResolvedIdentifier(
        kind: kind, name: name, staticScope: staticScope, uri: uri);
  }

  @override
  DartType buildType(
      NullabilityBuilder nullabilityBuilder, List<DartType> typeArguments) {
    throw new UnsupportedError('Cannot build type from member.');
  }

  @override
  Future<macro.TypeDeclaration> resolveTypeDeclaration(
      MacroIntrospection macroIntrospection) {
    return new Future.error(new macro.MacroImplementationExceptionImpl(
        'Cannot resolve type declaration from member.'));
  }
}

// Coverage-ignore(suite): Not run.
class FormalParameterBuilderIdentifier extends IdentifierImpl {
  final LibraryBuilder libraryBuilder;
  final FormalParameterBuilder parameterBuilder;

  FormalParameterBuilderIdentifier({
    required this.parameterBuilder,
    required this.libraryBuilder,
    required int id,
    required String name,
  }) : super(id: id, name: name);

  @override
  macro.ResolvedIdentifier resolveIdentifier() {
    return new macro.ResolvedIdentifier(
        kind: macro.IdentifierKind.local,
        name: name,
        staticScope: null,
        uri: null);
  }

  @override
  DartType buildType(
      NullabilityBuilder nullabilityBuilder, List<DartType> typeArguments) {
    throw new UnsupportedError('Cannot build type from formal parameter.');
  }

  @override
  Future<macro.TypeDeclaration> resolveTypeDeclaration(
      MacroIntrospection macroIntrospection) {
    throw new macro.MacroImplementationExceptionImpl(
        'Cannot resolve type declaration from formal parameter.');
  }
}

// Coverage-ignore(suite): Not run.
class OmittedTypeIdentifier extends IdentifierImpl {
  OmittedTypeIdentifier({required int id}) : super(id: id, name: 'dynamic');

  @override
  DartType buildType(
      NullabilityBuilder nullabilityBuilder, List<DartType> typeArguments) {
    return const DynamicType();
  }

  @override
  macro.ResolvedIdentifier resolveIdentifier() {
    return new macro.ResolvedIdentifier(
        kind: macro.IdentifierKind.topLevelMember,
        name: name,
        staticScope: null,
        uri: dartCore);
  }

  @override
  Future<macro.TypeDeclaration> resolveTypeDeclaration(
      MacroIntrospection macroIntrospection) {
    return new Future.error(new macro.MacroImplementationExceptionImpl(
        'Cannot resolve type declaration from omitted type.'));
  }
}

// Coverage-ignore(suite): Not run.
class VoidTypeIdentifier extends IdentifierImpl {
  VoidTypeIdentifier({required int id}) : super(id: id, name: 'void');

  @override
  DartType buildType(
      NullabilityBuilder nullabilityBuilder, List<DartType> typeArguments) {
    return const VoidType();
  }

  @override
  macro.ResolvedIdentifier resolveIdentifier() {
    return new macro.ResolvedIdentifier(
        kind: macro.IdentifierKind.topLevelMember,
        name: name,
        staticScope: null,
        uri: null);
  }

  @override
  Future<macro.TypeDeclaration> resolveTypeDeclaration(
      MacroIntrospection macroIntrospection) {
    return new Future.error(new macro.MacroImplementationExceptionImpl(
        'Cannot resolve type declaration from void type.'));
  }
}
