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

library kernel.deferred_load_data;

import 'package:kernel/ast.dart' as ir;

import '../common_elements.dart';
import '../compiler.dart' show Compiler;
import '../constants/values.dart' show ConstantValue;
import '../deferred_load.dart';
import '../elements/entities.dart';
import 'element_map.dart';

class KernelDeferredLoadTask extends DeferredLoadTask {
  KernelToElementMapForImpact _elementMap;
  Map<ir.Library, Set<ir.NamedNode>> _additionalExportsSets =
      <ir.Library, Set<ir.NamedNode>>{};

  KernelDeferredLoadTask(Compiler compiler, this._elementMap) : super(compiler);

  @override
  Iterable<ImportEntity> importsTo(Entity element, LibraryEntity library) {
    ir.NamedNode node;
    String nodeName;
    ir.Library enclosingLibrary;
    if (element is ClassEntity) {
      ClassDefinition definition = _elementMap.getClassDefinition(element);
      if (definition.kind != ClassKind.regular) {
        // You can't import closures.
        return const <ImportEntity>[];
      }
      ir.Class _node = definition.node;
      nodeName = _node.name;
      enclosingLibrary = _node.enclosingLibrary;
      node = _node;
    } else if (element is MemberEntity) {
      ir.Member _node = _elementMap.getMemberDefinition(element).node;
      nodeName = _node.name.name;
      enclosingLibrary = _node.enclosingLibrary;
      node = _node;
    } else if (element is Local ||
        element is LibraryEntity ||
        element is TypeVariableEntity) {
      return const <ImportEntity>[];
    } else if (element is TypedefEntity) {
      throw new UnimplementedError("KernelDeferredLoadTask.importsTo typedef");
    } else {
      throw new UnsupportedError(
          "KernelDeferredLoadTask.importsTo unexpected entity type: "
          "${element.runtimeType}");
    }
    List<ImportEntity> imports = [];
    ir.Library source = _elementMap.getLibraryNode(library);
    for (ir.LibraryDependency dependency in source.dependencies) {
      if (dependency.isExport) continue;
      if (!_isVisible(dependency.combinators, nodeName)) continue;
      if (enclosingLibrary == dependency.targetLibrary ||
          additionalExports(dependency.targetLibrary).contains(node)) {
        imports.add(_elementMap.getImport(dependency));
      }
    }
    return imports;
  }

  @override
  void checkForDeferredErrorCases(LibraryEntity library) {
    // Nothing to do. The FE checks for error cases upfront.
  }

  @override
  void collectConstantsFromMetadata(
      Entity element, Set<ConstantValue> constants) {
    // Nothing to do. Kernel-pipeline doesn't support mirrors, so we don't need
    // to track any constants from meta-data.
  }

  @override
  void collectConstantsInBody(
      covariant MemberEntity element, Set<ConstantValue> constants) {
    ir.Member node = _elementMap.getMemberDefinition(element).node;

    // Fetch the internal node in order to skip annotations on the member.
    // TODO(sigmund): replace this pattern when the kernel-ast provides a better
    // way to skip annotations (issue 31565).
    var visitor = new ConstantCollector(_elementMap, constants);
    if (node is ir.Field) {
      node.initializer?.accept(visitor);
      return;
    }

    if (node is ir.Constructor) {
      node.initializers.forEach((i) => i.accept(visitor));
    }
    node.function?.accept(visitor);
  }

  /// Adds extra dependencies coming from mirror usage.
  @override
  void addDeferredMirrorElements(WorkQueue queue) {
    throw new UnsupportedError(
        "KernelDeferredLoadTask.addDeferredMirrorElements");
  }

  /// Add extra dependencies coming from mirror usage in [root] marking it with
  /// [newSet].
  @override
  void addMirrorElementsForLibrary(
      WorkQueue queue, LibraryEntity root, ImportSet newSet) {
    throw new UnsupportedError(
        "KernelDeferredLoadTask.addMirrorElementsForLibrary");
  }

  Set<ir.NamedNode> additionalExports(ir.Library library) {
    return _additionalExportsSets[library] ??= new Set<ir.NamedNode>.from(
        library.additionalExports.map((ir.Reference ref) => ref.node));
  }

  @override
  void cleanup() {
    _additionalExportsSets = null;
  }
}

/// Returns whether [name] would be visible according to the given list of
/// show/hide [combinators].
bool _isVisible(List<ir.Combinator> combinators, String name) {
  for (var c in combinators) {
    if (c.isShow && !c.names.contains(name)) return false;
    if (c.isHide && c.names.contains(name)) return false;
  }
  return true;
}

class ConstantCollector extends ir.RecursiveVisitor {
  final KernelToElementMapForImpact elementMap;
  final Set<ConstantValue> constants;

  ConstantCollector(this.elementMap, this.constants);

  CommonElements get commonElements => elementMap.commonElements;

  void add(ir.Expression node, {bool required: true}) {
    ConstantValue constant =
        elementMap.getConstantValue(node, requireConstant: required);
    if (constant != null) {
      constants.add(constant);
    }
  }

  @override
  void visitIntLiteral(ir.IntLiteral literal) {}

  @override
  void visitDoubleLiteral(ir.DoubleLiteral literal) {}

  @override
  void visitBoolLiteral(ir.BoolLiteral literal) {}

  @override
  void visitStringLiteral(ir.StringLiteral literal) {}

  @override
  void visitSymbolLiteral(ir.SymbolLiteral literal) => add(literal);

  @override
  void visitNullLiteral(ir.NullLiteral literal) {}

  @override
  void visitListLiteral(ir.ListLiteral literal) {
    if (literal.isConst) {
      add(literal);
    } else {
      super.visitListLiteral(literal);
    }
  }

  @override
  void visitMapLiteral(ir.MapLiteral literal) {
    if (literal.isConst) {
      add(literal);
    } else {
      super.visitMapLiteral(literal);
    }
  }

  @override
  void visitConstructorInvocation(ir.ConstructorInvocation node) {
    if (node.isConst) {
      add(node);
    } else {
      super.visitConstructorInvocation(node);
    }
  }

  @override
  void visitTypeLiteral(ir.TypeLiteral node) {
    if (node.type is! ir.TypeParameterType) add(node);
  }

  @override
  void visitInstantiation(ir.Instantiation node) {
    // TODO(johnniwinther): The CFE should mark constant instantiations as
    // constant.
    add(node, required: false);
  }
}
