// 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.

library dart2js.kernel.env;

import 'package:js_shared/variance.dart';
import 'package:kernel/ast.dart' as ir;
import 'package:kernel/library_index.dart' as ir;
import 'package:collection/collection.dart' show mergeSort; // a stable sort.

import '../common.dart';
import '../constants/values.dart';
import '../elements/entities.dart';
import '../elements/names.dart';
import '../elements/types.dart';
import '../ir/element_map.dart';
import '../ir/util.dart';
import '../js_model/class_type_variable_access.dart';
import '../js_model/element_map.dart';
import '../js_model/env.dart';
import '../ordered_typeset.dart';
import '../universe/member_usage.dart';
import 'element_map.dart' show memberIsIgnorable, KernelToElementMap;

/// Environment for fast lookup of component libraries.
class KProgramEnv {
  final Set<ir.Component> _components = {};

  late final Map<Uri, KLibraryEnv> _libraryMap = {
    for (final component in _components)
      for (final library in component.libraries)
        library.importUri: KLibraryEnv(library),
  };

  late final ir.LibraryIndex libraryIndex = ir.LibraryIndex.all(mainComponent);

  /// TODO(johnniwinther): Handle arbitrary load order if needed.
  ir.Member? get mainMethod => mainComponent.mainMethod;

  ir.Component get mainComponent => _components.first;

  void addComponent(ir.Component component) {
    if (_components.add(component)) {
      for (ir.Library library in component.libraries) {
        _libraryMap[library.importUri] ??= KLibraryEnv(library);
      }
    }
  }

  /// Return the [KLibraryEnv] for the library with the canonical [uri].
  KLibraryEnv? lookupLibrary(Uri uri) => _libraryMap[uri];

  /// Calls [f] for each library in this environment.
  void forEachLibrary(void f(KLibraryEnv library)) {
    _libraryMap.values.forEach(f);
  }

  /// Returns the number of libraries in this environment.
  int get length => _libraryMap.length;

  /// Convert this [KProgramEnv] to the corresponding [JProgramEnv].
  JProgramEnv convert() => JProgramEnv(_components);
}

/// Environment for fast lookup of library classes and members.
class KLibraryEnv {
  final ir.Library library;

  late final Map<String, KClassEnv> _classMap = {
    for (ir.Class cls in library.classes) cls.name: KClassEnv(cls),
  };

  Map<String, ir.Member>? _memberMap;
  Map<String, ir.Member>? _setterMap;

  KLibraryEnv(this.library);

  /// Return the [KClassEnv] for the class [name] in [library].
  KClassEnv? lookupClass(String name) => _classMap[name];

  /// Calls [f] for each class in this library.
  void forEachClass(void f(KClassEnv cls)) {
    _classMap.values.forEach(f);
  }

  void _ensureMemberMaps() {
    if (_memberMap == null) {
      _memberMap = <String, ir.Member>{};
      _setterMap = <String, ir.Member>{};
      for (ir.Member member in library.members) {
        if (member is ir.Procedure) {
          if (member.kind == ir.ProcedureKind.Setter) {
            _setterMap![member.name.text] = member;
          } else {
            _memberMap![member.name.text] = member;
          }
        } else if (member is ir.Field) {
          _memberMap![member.name.text] = member;
          if (member.hasSetter) {
            _setterMap![member.name.text] = member;
          }
        } else {
          failedAt(
              NO_LOCATION_SPANNABLE, "Unexpected library member node: $member");
        }
      }
    }
  }

  /// Return the [ir.Member] for the member [name] in [library].
  ir.Member? lookupMember(String name, {bool setter = false}) {
    _ensureMemberMaps();
    return setter ? _setterMap![name] : _memberMap![name];
  }

  void forEachMember(void f(ir.Member member)) {
    _ensureMemberMaps();
    _memberMap!.values.forEach(f);
    for (ir.Member member in _setterMap!.values) {
      if (member is ir.Procedure) {
        f(member);
      } else {
        // Skip fields; these are also in _memberMap.
      }
    }
  }

  /// Convert this [KLibraryEnv] to a corresponding [JLibraryEnv] containing
  /// only the members in [liveMembers].
  JLibraryEnv convert(IrToElementMap kElementMap,
      Map<MemberEntity, MemberUsage> liveMemberUsage) {
    Map<String, ir.Member> memberMap;
    Map<String, ir.Member> setterMap;
    if (_memberMap == null) {
      memberMap = const <String, ir.Member>{};
    } else {
      memberMap = <String, ir.Member>{};
      _memberMap!.forEach((String name, ir.Member node) {
        MemberEntity member = kElementMap.getMember(node);
        if (liveMemberUsage.containsKey(member)) {
          memberMap[name] = node;
        }
      });
    }
    if (_setterMap == null) {
      setterMap = const <String, ir.Member>{};
    } else {
      setterMap = <String, ir.Member>{};
      _setterMap!.forEach((String name, ir.Member node) {
        MemberEntity member = kElementMap.getMember(node);
        if (liveMemberUsage.containsKey(member)) {
          setterMap[name] = node;
        }
      });
    }
    return JLibraryEnv(library, memberMap, setterMap);
  }
}

class KLibraryData {
  final ir.Library library;
  Iterable<ConstantValue>? _metadata;
  // TODO(johnniwinther): Avoid direct access to [imports].
  Map<ir.LibraryDependency, ImportEntity>? imports;

  KLibraryData(this.library);

  Iterable<ConstantValue> getMetadata(KernelToElementMap elementMap) {
    return _metadata ??= elementMap.getMetadata(library.annotations);
  }

  Iterable<ImportEntity> getImports(KernelToElementMap elementMap) {
    if (imports == null) {
      List<ir.LibraryDependency> dependencies = library.dependencies;
      if (dependencies.isEmpty) {
        imports = const <ir.LibraryDependency, ImportEntity>{};
      } else {
        imports = <ir.LibraryDependency, ImportEntity>{};
        dependencies.forEach((ir.LibraryDependency node) {
          if (node.isExport) return;
          imports![node] = ImportEntity(
              node.isDeferred,
              node.name,
              node.targetLibrary.importUri,
              elementMap.getLibrary(node.enclosingLibrary).canonicalUri);
        });
      }
    }
    return imports!.values;
  }

  /// Convert this [KLibraryData] to the corresponding [JLibraryData].
  // TODO(johnniwinther): Why isn't [imports] ensured to be non-null here?
  JLibraryData convert() {
    return JLibraryData(library, imports ?? const {});
  }
}

int orderByFileOffset(ir.TreeNode a, ir.TreeNode b) {
  var aLoc = a.location!;
  var bLoc = b.location!;
  var aUri = '${aLoc.file}';
  var bUri = '${bLoc.file}';
  var uriCompare = aUri.compareTo(bUri);
  if (uriCompare != 0) return uriCompare;
  return a.fileOffset.compareTo(b.fileOffset);
}

/// Environment for fast lookup of class members.
class KClassEnv {
  final ir.Class cls;

  Map<String, ir.Member>? _constructorMap;
  Map<Name, ir.Member>? _memberMap;
  List<ir.Member>? _members; // in declaration order.
  bool? _isMixinApplicationWithMembers;

  /// Constructor bodies created for this class.
  List<ConstructorBodyEntity>? _constructorBodyList;

  KClassEnv(this.cls);

  bool get isUnnamedMixinApplication => cls.isAnonymousMixin;

  bool get isMixinApplicationWithMembers => _isMixinApplicationWithMembers!;

  bool checkHasMember(ir.Member node) {
    if (_memberMap == null) return false;
    return _memberMap!.values.contains(node) ||
        _constructorMap!.values.contains(node);
  }

  void ensureMembers(KernelToElementMap elementMap) {
    _ensureMaps(elementMap);
  }

  void _ensureMaps(KernelToElementMap elementMap) {
    if (_memberMap != null) return;

    _memberMap = <Name, ir.Member>{};
    _constructorMap = <String, ir.Member>{};
    var members = <ir.Member>[];
    _isMixinApplicationWithMembers = false;

    void addField(ir.Field member, {required bool includeStatic}) {
      if (!includeStatic && member.isStatic) return;
      var name = elementMap.getName(member.name);
      _memberMap![name] = member;
      if (member.hasSetter) {
        _memberMap![name.setter] = member;
      }
      members.add(member);
    }

    void addProcedure(ir.Procedure member,
        {required bool includeStatic,
        required bool includeNoSuchMethodForwarders,
        bool isFromMixinApplication = false}) {
      if (memberIsIgnorable(member, cls: cls)) return;
      if (!includeStatic && member.isStatic) return;
      if (member.isNoSuchMethodForwarder) {
        if (!includeNoSuchMethodForwarders) {
          return;
        }
      }
      if (member.kind == ir.ProcedureKind.Factory) {
        if (member.isRedirectingFactory) {
          // Don't include redirecting factories.
          return;
        }
        _constructorMap![member.name.text] = member;
      } else {
        var name = elementMap.getName(member.name, setter: member.isSetter);
        _memberMap![name] = member;
        members.add(member);
        if (isFromMixinApplication) {
          _isMixinApplicationWithMembers = true;
        }
      }
    }

    void addConstructors(ir.Class c) {
      for (ir.Constructor member in c.constructors) {
        var name = member.name.text;
        _constructorMap![name] = member;
      }
    }

    int mixinMemberCount = 0;

    if (cls.mixedInClass != null) {
      for (ir.Field field in cls.mixedInClass!.mixin.fields) {
        if (field.containsSuperCalls) {
          _isMixinApplicationWithMembers = true;
          continue;
        }
        addField(field, includeStatic: false);
      }
      for (ir.Procedure procedure in cls.mixedInClass!.mixin.procedures) {
        if (procedure.containsSuperCalls) {
          _isMixinApplicationWithMembers = true;
          continue;
        }
        addProcedure(procedure,
            includeStatic: false, includeNoSuchMethodForwarders: false);
      }
      mergeSort(members, compare: orderByFileOffset);
      mixinMemberCount = members.length;
    }

    for (ir.Field member in cls.fields) {
      addField(member, includeStatic: true);
    }
    addConstructors(cls);
    for (ir.Procedure member in cls.procedures) {
      addProcedure(member,
          includeStatic: true,
          includeNoSuchMethodForwarders: true,
          isFromMixinApplication: cls.mixedInClass != null);
    }

    mergeSort(members, start: mixinMemberCount, compare: orderByFileOffset);
    _members = members;
  }

  MemberEntity? lookupMember(
      covariant KernelToElementMap elementMap, Name name) {
    _ensureMaps(elementMap);
    ir.Member? member = _memberMap![name];
    return member != null ? elementMap.getMember(member) : null;
  }

  void forEachMember(IrToElementMap elementMap, void f(MemberEntity member)) {
    _ensureMaps(elementMap as KernelToElementMap);
    _members!.forEach((ir.Member member) {
      f(elementMap.getMember(member));
    });
  }

  ConstructorEntity? lookupConstructor(
      IrToElementMap elementMap, String? name) {
    _ensureMaps(elementMap as KernelToElementMap);
    ir.Member? constructor = _constructorMap![name!];
    return constructor != null ? elementMap.getConstructor(constructor) : null;
  }

  void forEachConstructor(
      IrToElementMap elementMap, void f(ConstructorEntity constructor)) {
    _ensureMaps(elementMap as KernelToElementMap);
    _constructorMap!.values.forEach((ir.Member constructor) {
      f(elementMap.getConstructor(constructor));
    });
  }

  void addConstructorBody(ConstructorBodyEntity constructorBody) {
    _constructorBodyList ??= <ConstructorBodyEntity>[];
    _constructorBodyList!.add(constructorBody);
  }

  void forEachConstructorBody(void f(ConstructorBodyEntity constructor)) {
    _constructorBodyList?.forEach(f);
  }

  JClassEnv convert(
      IrToElementMap kElementMap,
      Map<MemberEntity, MemberUsage> liveMemberUsage,
      Iterable<MemberEntity> liveAbstractMembers,
      LibraryEntity Function(ir.Library library) getJLibrary) {
    Map<String, ir.Member> constructorMap;
    Map<Name, ir.Member> memberMap;
    List<ir.Member> members;
    if (_constructorMap == null) {
      constructorMap = const <String, ir.Member>{};
    } else {
      constructorMap = <String, ir.Member>{};
      _constructorMap!.forEach((String name, ir.Member node) {
        MemberEntity member = kElementMap.getMember(node);
        if (liveMemberUsage.containsKey(member) ||
            liveAbstractMembers.contains(member)) {
          constructorMap[name] = node;
        }
      });
    }
    if (_memberMap == null) {
      memberMap = const <Name, ir.Member>{};
    } else {
      memberMap = <Name, ir.Member>{};
      _memberMap!.forEach((Name name, ir.Member node) {
        MemberEntity member = kElementMap.getMember(node);
        if (liveMemberUsage.containsKey(member) ||
            liveAbstractMembers.contains(member)) {
          memberMap[name] = node;
        }
      });
    }
    if (_members == null) {
      members = const <ir.Member>[];
    } else {
      members = <ir.Member>[];
      _members!.forEach((ir.Member node) {
        MemberEntity member = kElementMap.getMember(node);
        if (liveMemberUsage.containsKey(member) ||
            liveAbstractMembers.contains(member)) {
          members.add(node);
        }
      });
    }
    return JClassEnvImpl(cls, constructorMap, memberMap, members,
        _isMixinApplicationWithMembers ?? false);
  }
}

class KClassData {
  final ir.Class node;
  late bool isMixinApplication;

  InterfaceType? thisType;
  InterfaceType? jsInteropType;
  InterfaceType? rawType;
  InterfaceType? instantiationToBounds;
  InterfaceType? supertype;
  InterfaceType? mixedInType;
  List<InterfaceType>? interfaces;
  OrderedTypeSet? orderedTypeSet;

  Iterable<ConstantValue>? _metadata;
  List<Variance>? _variances;

  KClassData(this.node);

  bool get isEnumClass => node.isEnum;

  FunctionType? callType;
  bool isCallTypeComputed = false;

  Iterable<ConstantValue> getMetadata(covariant KernelToElementMap elementMap) {
    return _metadata ??= elementMap.getMetadata(node.annotations);
  }

  List<Variance> getVariances() =>
      _variances ??= node.typeParameters.map(convertVariance).toList();

  JClassData convert() {
    return JClassDataImpl(node, RegularClassDefinition(node));
  }
}

abstract class KMemberData {
  final ir.Member node;

  Iterable<ConstantValue>? _metadata;

  ClassTypeVariableAccess get classTypeVariableAccess;

  KMemberData(this.node);

  Iterable<ConstantValue> getMetadata(covariant KernelToElementMap elementMap) {
    return _metadata ??= elementMap.getMetadata(node.annotations);
  }

  InterfaceType? getMemberThisType(JsToElementMap elementMap) {
    MemberEntity member = elementMap.getMember(node);
    ClassEntity? cls = member.enclosingClass;
    if (cls != null) {
      return elementMap.elementEnvironment.getThisType(cls);
    }
    return null;
  }

  /// Convert this [KMemberData] to the corresponding [JMemberData].
  JMemberData convert();
}

class KFunctionData extends KMemberData {
  final ir.FunctionNode functionNode;
  FunctionType? _type;
  List<TypeVariableType>? _typeVariables;

  KFunctionData(super.node, this.functionNode);

  FunctionType getFunctionType(covariant KernelToElementMap elementMap) {
    return _type ??= elementMap.getFunctionType(functionNode);
  }

  void forEachParameter(JsToElementMap elementMap,
      void f(DartType type, String? name, ConstantValue? defaultValue)) {
    void handleParameter(ir.VariableDeclaration parameter,
        {bool isOptional = true}) {
      DartType type = elementMap.getDartType(parameter.type);
      String? name = parameter.name;
      ConstantValue? defaultValue;
      if (isOptional) {
        if (parameter.initializer != null) {
          defaultValue = elementMap.getConstantValue(parameter.initializer);
        } else {
          defaultValue = NullConstantValue();
        }
      }
      f(type, name, defaultValue);
    }

    for (int i = 0; i < functionNode.positionalParameters.length; i++) {
      handleParameter(functionNode.positionalParameters[i],
          isOptional: i >= functionNode.requiredParameterCount);
    }
    functionNode.namedParameters.toList()
      ..sort(namedOrdering)
      ..forEach(handleParameter);
  }

  List<TypeVariableType> getFunctionTypeVariables(
      covariant KernelToElementMap elementMap) {
    if (_typeVariables == null) {
      if (functionNode.typeParameters.isEmpty) {
        _typeVariables = const <TypeVariableType>[];
      } else {
        ir.TreeNode? parent = functionNode.parent;
        if (parent is ir.Constructor ||
            (parent is ir.Procedure &&
                parent.kind == ir.ProcedureKind.Factory)) {
          _typeVariables = const <TypeVariableType>[];
        } else {
          _typeVariables = functionNode.typeParameters
              .map<TypeVariableType>((ir.TypeParameter typeParameter) {
            return elementMap
                .getDartType(ir.TypeParameterType(
                    typeParameter, ir.Nullability.nonNullable))
                .withoutNullability as TypeVariableType;
          }).toList();
        }
      }
    }
    return _typeVariables!;
  }

  @override
  FunctionData convert() {
    return FunctionDataImpl(node, functionNode, RegularMemberDefinition(node));
  }

  @override
  ClassTypeVariableAccess get classTypeVariableAccess {
    if (node.isInstanceMember) return ClassTypeVariableAccess.property;
    return ClassTypeVariableAccess.none;
  }
}

class KConstructorData extends KFunctionData {
  ConstructorBodyEntity? constructorBody;

  KConstructorData(super.node, super.functionNode);

  @override
  JConstructorData convert() {
    MemberDefinition definition;
    if (node is ir.Constructor) {
      definition = SpecialMemberDefinition(node, MemberKind.constructor);
    } else {
      definition = RegularMemberDefinition(node);
    }
    return JConstructorData(node, functionNode, definition);
  }

  @override
  ClassTypeVariableAccess get classTypeVariableAccess =>
      ClassTypeVariableAccess.parameter;
}

class KFieldData extends KMemberData {
  DartType? _type;

  final bool isLateBackingField;

  final bool isLateFinalBackingField;

  KFieldData(super.node,
      {required this.isLateBackingField,
      required this.isLateFinalBackingField});

  @override
  ir.Field get node => super.node as ir.Field;

  DartType getFieldType(covariant KernelToElementMap elementMap) {
    return _type ??= elementMap.getDartType(node.type);
  }

  @override
  ClassTypeVariableAccess get classTypeVariableAccess {
    if (node.isInstanceMember) return ClassTypeVariableAccess.instanceField;
    return ClassTypeVariableAccess.none;
  }

  @override
  JFieldData convert() {
    return JFieldDataImpl(node, RegularMemberDefinition(node));
  }
}

class KTypeVariableData {
  final ir.TypeParameter node;
  DartType? _bound;
  DartType? _defaultType;

  KTypeVariableData(this.node);

  DartType getBound(IrToElementMap elementMap) {
    return _bound ??= elementMap.getDartType(node.bound);
  }

  DartType getDefaultType(IrToElementMap elementMap) {
    return _defaultType ??= elementMap.getDartType(node.defaultType);
  }

  JTypeVariableData copy() {
    return JTypeVariableData(node);
  }
}
