// 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 '../common.dart';
import '../common/elements.dart' show KElementEnvironment;
import '../constants/values.dart';
import '../elements/entities.dart';
import '../elements/types.dart';
import '../js_backend/native_data.dart';

/// Determines all native classes in a set of libraries.
class NativeClassFinder {
  final KElementEnvironment _elementEnvironment;
  final NativeBasicData _nativeBasicData;

  final Map<String, ClassEntity> _tagOwner = {};

  NativeClassFinder(this._elementEnvironment, this._nativeBasicData);

  /// Returns the set of all native classes declared in [libraries].
  Iterable<ClassEntity> computeNativeClasses(Iterable<Uri> libraries) {
    Set<ClassEntity> nativeClasses = {};
    for (var uri in libraries) {
      _processNativeClassesInLibrary(
        _elementEnvironment.lookupLibrary(uri)!,
        nativeClasses,
      );
    }
    _processSubclassesOfNativeClasses(libraries, nativeClasses);
    return nativeClasses;
  }

  /// Adds all directly native classes declared in [library] to [nativeClasses].
  void _processNativeClassesInLibrary(
    LibraryEntity library,
    Set<ClassEntity> nativeClasses,
  ) {
    _elementEnvironment.forEachClass(library, (ClassEntity cls) {
      if (_nativeBasicData.isNativeClass(cls)) {
        _processNativeClass(cls, nativeClasses);
      }
    });
  }

  /// Adds [cls] to [nativeClasses] and performs further processing of [cls],
  /// if necessary.
  void _processNativeClass(
    covariant ClassEntity cls,
    Set<ClassEntity> nativeClasses,
  ) {
    nativeClasses.add(cls);
    // Js Interop interfaces do not have tags.
    if (_nativeBasicData.isJsInteropClass(cls)) return;
    // Since we map from dispatch tags to classes, a dispatch tag must be used
    // on only one native class.
    for (String tag in _nativeBasicData.getNativeTagsOfClass(cls)) {
      ClassEntity? owner = _tagOwner[tag];
      if (owner != null) {
        if (owner != cls) {
          failedAt(cls, "Tag '$tag' already in use by '${owner.name}'");
        }
      } else {
        _tagOwner[tag] = cls;
      }
    }
  }

  /// Returns the name of the super class of [cls] or `null` of [cls] has
  /// no explicit superclass.
  String? _findExtendsNameOfClass(covariant ClassEntity cls) {
    return _elementEnvironment
        .getSuperClass(cls, skipUnnamedMixinApplications: true)
        ?.name;
  }

  /// Adds all subclasses of [nativeClasses] found in [libraries] to
  /// [nativeClasses].
  void _processSubclassesOfNativeClasses(
    Iterable<Uri> libraries,
    Set<ClassEntity> nativeClasses,
  ) {
    Set<ClassEntity> nativeClassesAndSubclasses = {};
    // Collect potential subclasses, e.g.
    //
    //     class B extends foo.A {}
    //
    // String "A" has a potential subclass B.

    Map<String, Set<ClassEntity>> potentialExtends = {};

    for (var uri in libraries) {
      LibraryEntity library = _elementEnvironment.lookupLibrary(uri)!;
      _elementEnvironment.forEachClass(library, (ClassEntity cls) {
        String? extendsName = _findExtendsNameOfClass(cls);
        if (extendsName != null) {
          Set<ClassEntity> potentialSubclasses = potentialExtends.putIfAbsent(
            extendsName,
            () => {},
          );
          potentialSubclasses.add(cls);
        }
      });
    }

    // Resolve all the native classes and any classes that might extend them in
    // [potentialExtends], and then check that the properly resolved class is in
    // fact a subclass of a native class.

    ClassEntity? nativeSuperclassOf(ClassEntity cls) {
      if (_nativeBasicData.isNativeClass(cls)) return cls;
      ClassEntity? superclass = _elementEnvironment.getSuperClass(cls);
      if (superclass == null) return null;
      return nativeSuperclassOf(superclass);
    }

    void walkPotentialSubclasses(ClassEntity element) {
      if (nativeClassesAndSubclasses.contains(element)) return;
      ClassEntity? nativeSuperclass = nativeSuperclassOf(element);
      if (nativeSuperclass != null) {
        nativeClassesAndSubclasses.add(element);
        Set<ClassEntity>? potentialSubclasses = potentialExtends[element.name];
        potentialSubclasses?.forEach(walkPotentialSubclasses);
      }
    }

    nativeClasses.forEach(walkPotentialSubclasses);
    nativeClasses.addAll(nativeClassesAndSubclasses);
  }
}

/// Extracts the name if [value] is a named annotation based on
/// [annotationClass], otherwise returns `null`.
String? readAnnotationName(
  DartTypes dartTypes,
  Spannable spannable,
  ConstantValue value,
  ClassEntity annotationClass, {
  String? defaultValue,
}) {
  if (value is ConstructedConstantValue) {
    if (value.type.element != annotationClass) return null;

    Iterable<ConstantValue> fields = value.fields.values;
    // TODO(sra): Better validation of the constant.
    if (fields.length != 1) {
      failedAt(
        spannable,
        'Annotations needs one string: ${value.toStructuredText(dartTypes)}',
      );
    }
    final field = fields.single;
    if (field is StringConstantValue) {
      return field.stringValue;
    } else if (defaultValue != null && field is NullConstantValue) {
      return defaultValue;
    } else {
      failedAt(
        spannable,
        'Annotations needs one string: ${value.toStructuredText(dartTypes)}',
      );
    }
  }
  return null;
}
