// 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:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/type_environment.dart';

import '../../base/common.dart';
import '../builder/builder.dart';
import '../builder/class_builder.dart';
import '../builder/extension_builder.dart';
import '../builder/library_builder.dart';
import '../builder/metadata_builder.dart';
import '../builder/procedure_builder.dart';
import '../builder/type_builder.dart';
import '../builder/type_variable_builder.dart';
import '../fasta_codes.dart'
    show
        messagePatchDeclarationMismatch,
        messagePatchDeclarationOrigin,
        noLength,
        templateExtensionMemberConflictsWithObjectMember;
import '../kernel/kernel_helper.dart';
import '../operator.dart';
import '../problems.dart';
import '../scope.dart';
import '../util/helpers.dart';
import 'source_field_builder.dart';
import 'source_library_builder.dart';
import 'source_member_builder.dart';
import 'source_procedure_builder.dart';

const String extensionThisName = '#this';

class SourceExtensionBuilder extends ExtensionBuilderImpl {
  final Extension _extension;

  SourceExtensionBuilder? _origin;
  SourceExtensionBuilder? patchForTesting;

  @override
  final List<TypeVariableBuilder>? typeParameters;

  @override
  final TypeBuilder onType;

  final ExtensionTypeShowHideClauseBuilder extensionTypeShowHideClauseBuilder;

  SourceExtensionBuilder(
      List<MetadataBuilder>? metadata,
      int modifiers,
      String name,
      this.typeParameters,
      this.onType,
      this.extensionTypeShowHideClauseBuilder,
      Scope scope,
      SourceLibraryBuilder parent,
      bool isExtensionTypeDeclaration,
      int startOffset,
      int nameOffset,
      int endOffset,
      Extension? referenceFrom)
      : _extension = new Extension(
            name: name,
            fileUri: parent.fileUri,
            typeParameters:
                TypeVariableBuilder.typeParametersFromBuilders(typeParameters),
            reference: referenceFrom?.reference)
          ..isExtensionTypeDeclaration = isExtensionTypeDeclaration
          ..fileOffset = nameOffset,
        super(metadata, modifiers, name, parent, nameOffset, scope);

  @override
  SourceLibraryBuilder get libraryBuilder =>
      super.libraryBuilder as SourceLibraryBuilder;

  @override
  SourceExtensionBuilder get origin => _origin ?? this;

  @override
  Extension get extension => isPatch ? origin._extension : _extension;

  /// Builds the [Extension] for this extension build and inserts the members
  /// into the [Library] of [sourceLibraryBuilder].
  ///
  /// [addMembersToLibrary] is `true` if the extension members should be added
  /// to the library. This is `false` if the extension is in conflict with
  /// another library member. In this case, the extension member should not be
  /// added to the library to avoid name clashes with other members in the
  /// library.
  Extension build(
      SourceLibraryBuilder sourceLibraryBuilder, LibraryBuilder coreLibrary,
      {required bool addMembersToLibrary}) {
    _extension.onType = onType.build(sourceLibraryBuilder);
    extensionTypeShowHideClauseBuilder.buildAndStoreTypes(
        _extension, sourceLibraryBuilder);

    SourceLibraryBuilder.checkMemberConflicts(libraryBuilder, scope,
        checkForInstanceVsStaticConflict: true,
        checkForMethodVsSetterConflict: true);

    ClassBuilder objectClassBuilder =
        coreLibrary.lookupLocalMember('Object', required: true) as ClassBuilder;
    void buildBuilders(String name, Builder? declaration) {
      while (declaration != null) {
        Builder? objectGetter = objectClassBuilder.lookupLocalMember(name);
        Builder? objectSetter =
            objectClassBuilder.lookupLocalMember(name, setter: true);
        if (objectGetter != null || objectSetter != null) {
          addProblem(
              templateExtensionMemberConflictsWithObjectMember
                  .withArguments(name),
              declaration.charOffset,
              name.length);
        }
        if (declaration.parent != this) {
          if (fileUri != declaration.parent!.fileUri) {
            unexpected("$fileUri", "${declaration.parent!.fileUri}", charOffset,
                fileUri);
          } else {
            unexpected(fullNameForErrors, declaration.parent!.fullNameForErrors,
                charOffset, fileUri);
          }
        } else if (declaration is SourceMemberBuilder) {
          SourceMemberBuilder memberBuilder = declaration;
          memberBuilder.buildMembers(sourceLibraryBuilder,
              (Member member, BuiltMemberKind memberKind) {
            if (addMembersToLibrary &&
                !memberBuilder.isPatch &&
                !memberBuilder.isDuplicate &&
                !memberBuilder.isConflictingSetter) {
              ExtensionMemberKind kind;
              String name = memberBuilder.name;
              switch (memberKind) {
                case BuiltMemberKind.Constructor:
                case BuiltMemberKind.RedirectingFactory:
                case BuiltMemberKind.Field:
                case BuiltMemberKind.Method:
                  unhandled(
                      "${member.runtimeType}:${memberKind}",
                      "buildMembers",
                      memberBuilder.charOffset,
                      memberBuilder.fileUri);
                case BuiltMemberKind.ExtensionField:
                case BuiltMemberKind.LateIsSetField:
                  kind = ExtensionMemberKind.Field;
                  break;
                case BuiltMemberKind.ExtensionMethod:
                  kind = ExtensionMemberKind.Method;
                  break;
                case BuiltMemberKind.ExtensionGetter:
                case BuiltMemberKind.LateGetter:
                  kind = ExtensionMemberKind.Getter;
                  break;
                case BuiltMemberKind.ExtensionSetter:
                case BuiltMemberKind.LateSetter:
                  kind = ExtensionMemberKind.Setter;
                  break;
                case BuiltMemberKind.ExtensionOperator:
                  kind = ExtensionMemberKind.Operator;
                  break;
                case BuiltMemberKind.ExtensionTearOff:
                  kind = ExtensionMemberKind.TearOff;
                  break;
              }
              // ignore: unnecessary_null_comparison
              assert(kind != null);
              Reference memberReference;
              if (member is Field) {
                sourceLibraryBuilder.library.addField(member);
                memberReference = member.fieldReference;
              } else if (member is Procedure) {
                sourceLibraryBuilder.library.addProcedure(member);
                memberReference = member.reference;
              } else {
                unhandled("${member.runtimeType}", "buildBuilders",
                    member.fileOffset, member.fileUri);
              }
              extension.members.add(new ExtensionMemberDescriptor(
                  name: new Name(name, sourceLibraryBuilder.library),
                  member: memberReference,
                  isStatic: memberBuilder.isStatic,
                  kind: kind));
            }
          });
        } else {
          unhandled("${declaration.runtimeType}", "buildBuilders",
              declaration.charOffset, declaration.fileUri);
        }
        declaration = declaration.next;
      }
    }

    scope.forEach(buildBuilders);

    return _extension;
  }

  @override
  void applyPatch(Builder patch) {
    if (patch is SourceExtensionBuilder) {
      patch._origin = this;
      if (retainDataForTesting) {
        patchForTesting = patch;
      }
      scope.forEachLocalMember((String name, Builder member) {
        Builder? memberPatch =
            patch.scope.lookupLocalMember(name, setter: false);
        if (memberPatch != null) {
          member.applyPatch(memberPatch);
        }
      });
      scope.forEachLocalSetter((String name, Builder member) {
        Builder? memberPatch =
            patch.scope.lookupLocalMember(name, setter: true);
        if (memberPatch != null) {
          member.applyPatch(memberPatch);
        }
      });

      // TODO(johnniwinther): Check that type parameters and on-type match
      // with origin declaration.
    } else {
      libraryBuilder.addProblem(messagePatchDeclarationMismatch,
          patch.charOffset, noLength, patch.fileUri, context: [
        messagePatchDeclarationOrigin.withLocation(
            fileUri, charOffset, noLength)
      ]);
    }
  }

  @override
  int finishPatch() {
    if (!isPatch) return 0;

    int count = 0;
    scope.forEach((String name, Builder declaration) {
      count += declaration.finishPatch();
    });
    return count;
  }

  void checkTypesInOutline(TypeEnvironment typeEnvironment) {
    libraryBuilder.checkBoundsInTypeParameters(
        typeEnvironment, extension.typeParameters, fileUri);

    // Check on clause.
    // ignore: unnecessary_null_comparison
    if (_extension.onType != null) {
      libraryBuilder.checkBoundsInType(_extension.onType, typeEnvironment,
          onType.fileUri!, onType.charOffset!);
    }

    forEach((String name, Builder builder) {
      if (builder is SourceFieldBuilder) {
        // Check fields.
        libraryBuilder.checkTypesInField(builder, typeEnvironment);
      } else if (builder is SourceProcedureBuilder) {
        // Check procedures
        libraryBuilder.checkTypesInFunctionBuilder(builder, typeEnvironment);
        if (builder.isGetter) {
          Builder? setterDeclaration =
              scope.lookupLocalMember(builder.name, setter: true);
          if (setterDeclaration != null) {
            libraryBuilder.checkGetterSetterTypes(builder,
                setterDeclaration as ProcedureBuilder, typeEnvironment);
          }
        }
      } else {
        assert(false, "Unexpected member: $builder.");
      }
    });
  }

  @override
  void buildOutlineExpressions(
      SourceLibraryBuilder library,
      ClassHierarchy classHierarchy,
      List<DelayedActionPerformer> delayedActionPerformers,
      List<DelayedDefaultValueCloner> delayedDefaultValueCloners) {
    MetadataBuilder.buildAnnotations(isPatch ? origin.extension : extension,
        metadata, library, this, null, fileUri, library.scope);
    if (typeParameters != null) {
      for (int i = 0; i < typeParameters!.length; i++) {
        typeParameters![i].buildOutlineExpressions(library, this, null,
            classHierarchy, delayedActionPerformers, scope.parent!);
      }
    }

    void build(String ignore, Builder declaration) {
      SourceMemberBuilder member = declaration as SourceMemberBuilder;
      member.buildOutlineExpressions(library, classHierarchy,
          delayedActionPerformers, delayedDefaultValueCloners);
    }

    scope.forEach(build);
  }
}

class ExtensionTypeShowHideClauseBuilder {
  final List<TypeBuilder> shownSupertypes;
  final List<String> shownGetters;
  final List<String> shownSetters;
  final List<String> shownMembersOrTypes;
  final List<Operator> shownOperators;

  final List<TypeBuilder> hiddenSupertypes;
  final List<String> hiddenGetters;
  final List<String> hiddenSetters;
  final List<String> hiddenMembersOrTypes;
  final List<Operator> hiddenOperators;

  ExtensionTypeShowHideClauseBuilder(
      {required this.shownSupertypes,
      required this.shownGetters,
      required this.shownSetters,
      required this.shownMembersOrTypes,
      required this.shownOperators,
      required this.hiddenSupertypes,
      required this.hiddenGetters,
      required this.hiddenSetters,
      required this.hiddenMembersOrTypes,
      required this.hiddenOperators});

  void buildAndStoreTypes(Extension extension, LibraryBuilder libraryBuilder) {
    List<Supertype> builtShownSupertypes = shownSupertypes
        .map(
            (t) => t.buildSupertype(libraryBuilder, t.charOffset!, t.fileUri!)!)
        .toList();
    List<Supertype> builtHiddenSupertypes = hiddenSupertypes
        .map(
            (t) => t.buildSupertype(libraryBuilder, t.charOffset!, t.fileUri!)!)
        .toList();
    ExtensionTypeShowHideClause showHideClause =
        extension.showHideClause ?? new ExtensionTypeShowHideClause();
    showHideClause.shownSupertypes.addAll(builtShownSupertypes);
    showHideClause.hiddenSupertypes.addAll(builtHiddenSupertypes);
    extension.showHideClause ??= showHideClause;
  }
}
