// 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' as ir;
import 'package:kernel/type_environment.dart' as ir;
import '../common/names.dart';
import 'modular_migrated.dart';

class IrAnnotationData {
  final Map<ir.Class, String> _nativeClassNames = {};
  final Set<ir.Member> _nativeMembers = {};
  final Map<ir.Member, String> _nativeMemberNames = {};
  final Map<ir.Member, List<String>> _createsAnnotations = {};
  final Map<ir.Member, List<String>> _returnsAnnotations = {};

  final Map<ir.Library, String> _jsInteropLibraryNames = {};
  final Map<ir.Class, String> _jsInteropClassNames = {};
  final Set<ir.Class> _anonymousJsInteropClasses = {};
  final Map<ir.Member, String> _jsInteropMemberNames = {};

  final Map<ir.Member, List<PragmaAnnotationData>> _memberPragmaAnnotations =
      {};

  // Returns the text from the `@Native(<text>)` annotation of [node], if any.
  String? getNativeClassName(ir.Class node) => _nativeClassNames[node];

  // Returns `true` if [node] has a native body, as in `method() native;`.
  bool hasNativeBody(ir.Member node) => _nativeMembers.contains(node);

  // Returns the text from the `@JSName(<text>)` annotation of [node], if any.
  String? getNativeMemberName(ir.Member node) => _nativeMemberNames[node];

  // Returns a list of the text from the `@Creates(<text>)` annotation of
  // [node].
  List<String> getCreatesAnnotations(ir.Member node) =>
      _createsAnnotations[node] ?? const [];

  // Returns a list of the text from the `@Returns(<text>)` annotation of
  // [node].
  List<String> getReturnsAnnotations(ir.Member node) =>
      _returnsAnnotations[node] ?? const [];

  // Returns the text from the `@JS(<text>)` annotation of [node], if any.
  String? getJsInteropLibraryName(ir.Library node) =>
      _jsInteropLibraryNames[node];

  // Returns the text from the `@JS(<text>)` annotation of [node], if any.
  String? getJsInteropClassName(ir.Class node) => _jsInteropClassNames[node];

  // Returns `true` if [node] is annotated with `@anonymous`.
  bool isAnonymousJsInteropClass(ir.Class node) =>
      _anonymousJsInteropClasses.contains(node);

  // Returns the text from the `@JS(<text>)` annotation of [node], if any.
  String? getJsInteropMemberName(ir.Member node) => _jsInteropMemberNames[node];

  // Returns a list of the `@pragma('dart2js:<suffix>')` annotations on [node].
  List<PragmaAnnotationData> getMemberPragmaAnnotationData(ir.Member node) =>
      _memberPragmaAnnotations[node] ?? const [];

  void forEachNativeClass(void Function(ir.Class, String) f) {
    _nativeClassNames.forEach(f);
  }

  void forEachJsInteropLibrary(void Function(ir.Library, String) f) {
    _jsInteropLibraryNames.forEach(f);
  }

  void forEachJsInteropClass(
      void Function(ir.Class, String, {required bool isAnonymous}) f) {
    _jsInteropClassNames.forEach((ir.Class node, String name) {
      f(node, name, isAnonymous: isAnonymousJsInteropClass(node));
    });
  }

  void forEachJsInteropMember(void Function(ir.Member, String?) f) {
    _jsInteropLibraryNames.forEach((ir.Library library, _) {
      for (ir.Member member in library.members) {
        if (member.isExternal) {
          f(member, _jsInteropMemberNames[member] ?? member.name.text);
        }
      }
    });
    _jsInteropClassNames.forEach((ir.Class cls, _) {
      for (ir.Member member in cls.members) {
        if (member is ir.Field) continue;
        String? name = _jsInteropMemberNames[member];
        if (member.isExternal) {
          name ??= member.name.text;
        }
        f(member, name);
      }
    });
  }

  void forEachNativeMethodData(
      void Function(ir.Member, String name, Iterable<String> createsAnnotations,
              Iterable<String> returnsAnnotations)
          f) {
    for (ir.Member node in _nativeMembers) {
      if (node is! ir.Field) {
        String name = _nativeMemberNames[node] ?? node.name.text;
        f(node, name, getCreatesAnnotations(node), getReturnsAnnotations(node));
      }
    }
  }

  void forEachNativeFieldData(
      void Function(ir.Member, String name, Iterable<String> createsAnnotations,
              Iterable<String> returnsAnnotations)
          f) {
    for (ir.Class cls in _nativeClassNames.keys) {
      for (ir.Field field in cls.fields) {
        if (field.isInstanceMember) {
          String name = _nativeMemberNames[field] ?? field.name.text;
          f(field, name, getCreatesAnnotations(field),
              getReturnsAnnotations(field));
        }
      }
    }
  }
}

IrAnnotationData processAnnotations(ModularCore modularCore) {
  ir.Component component = modularCore.component;
  IrAnnotationData data = IrAnnotationData();

  void processMember(ir.Member member) {
    ir.StaticTypeContext staticTypeContext = ir.StaticTypeContext(
        member, modularCore.constantEvaluator.typeEnvironment);
    List<PragmaAnnotationData>? pragmaAnnotations;
    List<String>? createsAnnotations;
    List<String>? returnsAnnotations;
    for (ir.Expression annotation in member.annotations) {
      if (annotation is ir.ConstantExpression) {
        ir.Constant constant = modularCore.constantEvaluator
            .evaluate(staticTypeContext, annotation);

        String? jsName = _getJsInteropName(constant);
        if (jsName != null) {
          data._jsInteropMemberNames[member] = jsName;
        }

        bool isNativeMember = _isNativeMember(constant);
        if (isNativeMember) {
          data._nativeMembers.add(member);
        }

        String? nativeName = _getNativeMemberName(constant);
        if (nativeName != null) {
          data._nativeMemberNames[member] = nativeName;
        }

        String? creates = _getCreatesAnnotation(constant);
        if (creates != null) {
          if (createsAnnotations == null) {
            data._createsAnnotations[member] = createsAnnotations = [];
          }
          createsAnnotations.add(creates);
        }

        String? returns = _getReturnsAnnotation(constant);
        if (returns != null) {
          if (returnsAnnotations == null) {
            data._returnsAnnotations[member] = returnsAnnotations = [];
          }
          returnsAnnotations.add(returns);
        }

        PragmaAnnotationData? pragmaAnnotation = _getPragmaAnnotation(constant);
        if (pragmaAnnotation != null) {
          if (pragmaAnnotations == null) {
            data._memberPragmaAnnotations[member] = pragmaAnnotations = [];
          }
          pragmaAnnotations.add(pragmaAnnotation);
        }
      }
    }
  }

  for (ir.Library library in component.libraries) {
    ir.StaticTypeContext staticTypeContext =
        ir.StaticTypeContext.forAnnotations(
            library, modularCore.constantEvaluator.typeEnvironment);
    for (ir.Expression annotation in library.annotations) {
      if (annotation is ir.ConstantExpression) {
        ir.Constant constant = modularCore.constantEvaluator
            .evaluate(staticTypeContext, annotation);

        String? jsName = _getJsInteropName(constant);
        if (jsName != null) {
          data._jsInteropLibraryNames[library] = jsName;
        }
      }
    }
    for (ir.Class cls in library.classes) {
      for (ir.Expression annotation in cls.annotations) {
        if (annotation is ir.ConstantExpression) {
          ir.Constant constant = modularCore.constantEvaluator
              .evaluate(staticTypeContext, annotation);

          String? nativeClassName = _getNativeClassName(constant);
          if (nativeClassName != null) {
            data._nativeClassNames[cls] = nativeClassName;
          }

          String? jsName = _getJsInteropName(constant);
          if (jsName != null) {
            data._jsInteropClassNames[cls] = jsName;
          }

          bool isAnonymousJsInteropClass = _isAnonymousJsInterop(constant);
          if (isAnonymousJsInteropClass) {
            data._anonymousJsInteropClasses.add(cls);
          }
        }
      }
      for (ir.Member member in cls.members) {
        processMember(member);
      }
    }
    for (ir.Member member in library.members) {
      processMember(member);
    }
  }
  return data;
}

String? _getNativeClassName(ir.Constant constant) {
  if (constant is ir.InstanceConstant) {
    // TODO(johnniwinther): Add an IrCommonElements for these queries; i.e.
    // `commonElements.isNativeAnnotationClass(constant.classNode)`.
    if (constant.classNode.name == 'Native' &&
        constant.classNode.enclosingLibrary.importUri == Uris.dart__js_helper) {
      if (constant.fieldValues.length == 1) {
        ir.Constant fieldValue = constant.fieldValues.values.single;
        String? name;
        if (fieldValue is ir.StringConstant) {
          name = fieldValue.value;
        }
        if (name != null) {
          return name;
        }
      }
    }
  }
  return null;
}

bool _isNativeMember(ir.Constant constant) {
  return constant is ir.InstanceConstant &&
      constant.classNode.name == 'ExternalName' &&
      constant.classNode.enclosingLibrary.importUri == Uris.dart__internal;
}

String? _getNativeMemberName(ir.Constant constant) {
  if (constant is ir.InstanceConstant &&
      constant.classNode.name == 'JSName' &&
      constant.classNode.enclosingLibrary.importUri == Uris.dart__js_helper) {
    assert(constant.fieldValues.length == 1);
    ir.Constant fieldValue = constant.fieldValues.values.single;
    if (fieldValue is ir.StringConstant) {
      return fieldValue.value;
    }
  }
  return null;
}

String? _getCreatesAnnotation(ir.Constant constant) {
  if (constant is ir.InstanceConstant &&
      constant.classNode.name == 'Creates' &&
      constant.classNode.enclosingLibrary.importUri == Uris.dart__js_helper) {
    assert(constant.fieldValues.length == 1);
    ir.Constant fieldValue = constant.fieldValues.values.single;
    if (fieldValue is ir.StringConstant) {
      return fieldValue.value;
    }
  }
  return null;
}

String? _getReturnsAnnotation(ir.Constant constant) {
  if (constant is ir.InstanceConstant &&
      constant.classNode.name == 'Returns' &&
      constant.classNode.enclosingLibrary.importUri == Uris.dart__js_helper) {
    assert(constant.fieldValues.length == 1);
    ir.Constant fieldValue = constant.fieldValues.values.single;
    if (fieldValue is ir.StringConstant) {
      return fieldValue.value;
    }
  }
  return null;
}

String? _getJsInteropName(ir.Constant constant) {
  if (constant is ir.InstanceConstant &&
      constant.classNode.name == 'JS' &&
      (constant.classNode.enclosingLibrary.importUri == Uris.package_js ||
          constant.classNode.enclosingLibrary.importUri ==
              Uris.dart__js_annotations)) {
    assert(constant.fieldValues.length == 1);
    ir.Constant fieldValue = constant.fieldValues.values.single;
    if (fieldValue is ir.NullConstant) {
      return '';
    } else if (fieldValue is ir.StringConstant) {
      return fieldValue.value;
    }
  }
  return null;
}

bool _isAnonymousJsInterop(ir.Constant constant) {
  return constant is ir.InstanceConstant &&
      constant.classNode.name == '_Anonymous' &&
      (constant.classNode.enclosingLibrary.importUri == Uris.package_js ||
          constant.classNode.enclosingLibrary.importUri ==
              Uris.dart__js_annotations);
}

class PragmaAnnotationData {
  // TODO(johnniwinther): Support non 'dart2js:' pragma names if necessary.
  final String suffix;

  // TODO(johnniwinther): Support options objects when necessary.
  final bool hasOptions;

  const PragmaAnnotationData(this.suffix, {this.hasOptions = false});

  String get name => 'dart2js:$suffix';

  @override
  String toString() => 'PragmaAnnotationData($name)';
}

PragmaAnnotationData? _getPragmaAnnotation(ir.Constant constant) {
  if (constant is! ir.InstanceConstant) return null;
  ir.InstanceConstant value = constant;
  ir.Class cls = value.classNode;
  Uri uri = cls.enclosingLibrary.importUri;
  if (uri == Uris.package_meta_dart2js) {
    if (cls.name == '_NoInline') {
      return const PragmaAnnotationData('noInline');
    } else if (cls.name == '_TryInline') {
      return const PragmaAnnotationData('tryInline');
    }
  } else if (uri == Uris.dart_core && cls.name == 'pragma') {
    ir.Constant? nameValue;
    ir.Constant? optionsValue;
    value.fieldValues.forEach((ir.Reference reference, ir.Constant fieldValue) {
      ir.Field field = reference.asField;
      if (field.name.text == 'name') {
        nameValue = fieldValue;
      } else if (field.name.text == 'options') {
        optionsValue = fieldValue;
      }
    });
    final nameValueFinal = nameValue;
    if (nameValueFinal is! ir.StringConstant) return null;
    ir.StringConstant stringValue = nameValueFinal;
    String name = stringValue.value;
    String prefix = 'dart2js:';
    if (!name.startsWith(prefix)) return null;
    String suffix = name.substring(prefix.length);
    return PragmaAnnotationData(suffix,
        hasOptions: optionsValue is! ir.NullConstant);
  }
  return null;
}

List<PragmaAnnotationData> computePragmaAnnotationDataFromIr(
    ir.Annotatable node) {
  List<PragmaAnnotationData> annotations = [];
  for (ir.Expression metadata in node.annotations) {
    if (metadata is! ir.ConstantExpression) continue;
    ir.ConstantExpression constantExpression = metadata;
    ir.Constant constant = constantExpression.constant;
    assert(constant is! ir.UnevaluatedConstant,
        "Unexpected unevaluated constant on $node: $metadata");
    PragmaAnnotationData? data = _getPragmaAnnotation(constant);
    if (data != null) {
      annotations.add(data);
    }
  }
  return annotations;
}
