// Copyright (c) 2017, 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' as ir;

import '../common.dart';
import '../common/elements.dart';
import '../constants/values.dart';
import '../elements/entities.dart';
import '../ir/annotations.dart';
import '../js_backend/native_data.dart';
import '../native/resolver.dart';

import 'element_map.dart';

class KernelAnnotationProcessor {
  final KernelToElementMap elementMap;
  final NativeBasicDataBuilder _nativeBasicDataBuilder;
  final IrAnnotationData annotationData;

  KernelAnnotationProcessor(
    this.elementMap,
    this._nativeBasicDataBuilder,
    this.annotationData,
  );

  void extractNativeAnnotations(LibraryEntity library) {
    KElementEnvironment elementEnvironment = elementMap.elementEnvironment;

    elementEnvironment.forEachClass(library, (ClassEntity cls) {
      ir.Class node = elementMap.getClassNode(cls);
      String? annotationName = annotationData.getNativeClassName(node);
      if (annotationName != null) {
        _nativeBasicDataBuilder.setNativeClassTagInfo(cls, annotationName);
      }
    });
  }

  String? getJsInteropName(
    Spannable spannable,
    Iterable<ConstantValue> metadata,
  ) {
    KCommonElements commonElements = elementMap.commonElements;
    String? annotationName;
    for (ConstantValue value in metadata) {
      String? name;
      List<ClassEntity?> jsAnnotationClasses = [
        commonElements.jsAnnotationClass1,
        commonElements.jsAnnotationClass2,
        commonElements.jsAnnotationClass3,
      ];
      for (ClassEntity? jsAnnotationClass in jsAnnotationClasses) {
        if (jsAnnotationClass != null) {
          name = readAnnotationName(
            commonElements.dartTypes,
            spannable,
            value,
            jsAnnotationClass,
            defaultValue: '',
          );
          if (name != null) break;
        }
      }
      if (annotationName == null) {
        annotationName = name;
      } else if (name != null) {
        // TODO(johnniwinther): This should be an error, not a crash.
        failedAt(spannable, 'Too many name annotations.');
      }
    }
    return annotationName;
  }

  void extractJsInteropAnnotations(LibraryEntity library) {
    // Unused reporter, add back in if uncommenting report lines down below.
    // DiagnosticReporter reporter = elementMap.reporter;
    KElementEnvironment elementEnvironment = elementMap.elementEnvironment;

    ir.Library libraryNode = elementMap.getLibraryNode(library);
    String? libraryName = annotationData.getJsInteropLibraryName(libraryNode);
    final bool isExplicitlyJsLibrary = libraryName != null;
    bool isJsLibrary = isExplicitlyJsLibrary;

    elementEnvironment.forEachLibraryMember(library, (MemberEntity member) {
      ir.Member memberNode = elementMap.getMemberNode(member);
      String? memberName = annotationData.getJsInteropMemberName(memberNode);
      if (member is FieldEntity) {
        if (memberName != null) {
          // TODO(34174): Disallow js-interop fields.
          /*reporter.reportErrorMessage(
              member, MessageKind.JS_INTEROP_FIELD_NOT_SUPPORTED);*/
        }
      } else {
        FunctionEntity function = member as FunctionEntity;
        // We need this explicit check as object literal constructors in
        // extension types do not need an `@JS()` annotation on them, their
        // extension type, or their library. JS interop checks assert that the
        // only extension type interop member that has named parameters is an
        // object literal constructor.
        // TODO(54968): We should handle the lowering for object literal
        // constructors in the interop transformer somehow instead and avoid
        // assuming all such members are object literal constructors or
        // otherwise paying the cost to verify by indexing extension types.
        bool isObjectLiteralConstructor =
            (memberNode.isExtensionTypeMember &&
                memberNode.function?.namedParameters.isNotEmpty == true);
        if (function.isExternal &&
            (isExplicitlyJsLibrary || isObjectLiteralConstructor)) {
          // External members of explicit js-interop library are implicitly
          // js-interop members.
          memberName ??= function.name;
        }
        if (memberName != null) {
          if (!function.isExternal) {
            // TODO(johnniwinther): Disallow non-external js-interop members.
            /*reporter.reportErrorMessage(
                function, MessageKind.JS_INTEROP_NON_EXTERNAL_MEMBER);*/
          } else {
            _nativeBasicDataBuilder.markAsJsInteropMember(function, memberName);
            // TODO(johnniwinther): It is unclear whether library can be
            // implicitly js-interop. For now we allow it.
            isJsLibrary = true;
          }
        }
      }
    });

    elementEnvironment.forEachClass(library, (ClassEntity cls) {
      ir.Class classNode = elementMap.getClassNode(cls);
      String? className = annotationData.getJsInteropClassName(classNode);
      if (className != null) {
        bool isAnonymous = annotationData.isAnonymousJsInteropClass(classNode);
        bool isStaticInterop = annotationData.isStaticInteropClass(classNode);
        // TODO(johnniwinther): Report an error if the class is anonymous but
        // has a non-empty name.
        _nativeBasicDataBuilder.markAsJsInteropClass(
          cls,
          name: className,
          isAnonymous: isAnonymous,
          isStaticInterop: isStaticInterop,
        );
        // TODO(johnniwinther): It is unclear whether library can be implicitly
        // js-interop. For now we allow it.
        isJsLibrary = true;

        elementEnvironment.forEachLocalClassMember(cls, (MemberEntity member) {
          if (member is FieldEntity) {
            // TODO(34174): Disallow js-interop fields.
            /*reporter.reportErrorMessage(
                member, MessageKind.IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED);*/
          } else {
            FunctionEntity function = member as FunctionEntity;
            ir.Member memberNode = elementMap.getMemberNode(member);
            // Members that are not annotated and not external will result in
            // null here. For example, the default constructor which is not
            // user-specified.
            String? memberName = annotationData.getJsInteropMemberName(
              memberNode,
            );
            if (function.isExternal) {
              memberName ??= function.name;
            }
            if (memberName != null) {
              // TODO(johnniwinther): The documentation states that explicit
              // member name annotations are not allowed on instance members.
              _nativeBasicDataBuilder.markAsJsInteropMember(
                function,
                memberName,
              );
            }
          }
        });
        elementEnvironment.forEachConstructor(cls, (
          ConstructorEntity constructor,
        ) {
          String? memberName = getJsInteropName(
            library,
            elementEnvironment.getMemberMetadata(constructor),
          );
          if (constructor.isExternal) {
            // TODO(johnniwinther): It should probably be an error to have a
            // no-name constructor without a @JS() annotation.
            memberName ??= constructor.name;
          }
          if (memberName != null) {
            // TODO(johnniwinther): The documentation states that explicit
            // member name annotations are not allowed on instance members.
            _nativeBasicDataBuilder.markAsJsInteropMember(
              constructor,
              memberName,
            );
          }
        });
      }
    });

    if (isJsLibrary) {
      // TODO(johnniwinther): It is unclear whether library can be implicitly
      // js-interop. For now we allow it and assume the empty name.
      libraryName ??= '';
      _nativeBasicDataBuilder.markAsJsInteropLibrary(
        library,
        name: libraryName,
      );
    }
  }
}
