// Copyright (c) 2020, 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 vm.transformations.deferred_loading;

import 'package:kernel/ast.dart';
import 'package:kernel/core_types.dart' show CoreTypes;
import 'package:kernel/target/targets.dart' show Target;

import '../dominators.dart';
import '../metadata/loading_units.dart';
import 'pragma.dart';

class _LoadingUnitBuilder {
  late int id;
  final _LibraryVertex root;
  final List<Library> members = <Library>[];
  final List<_LoadingUnitBuilder> children = <_LoadingUnitBuilder>[];

  _LoadingUnitBuilder(this.root);

  _LoadingUnitBuilder? get parent => root.dominator?.loadingUnit;
  int get parentId => parent == null ? 0 : parent!.id;

  LoadingUnit asLoadingUnit() {
    return new LoadingUnit(
        id, parentId, members.map((l) => l.importUri.toString()).toList());
  }

  String toString() =>
      "_LoadingUnitBuilder(id=$id, parent=${parentId}, size=${members.length})";
}

class _LibraryVertex extends Vertex<_LibraryVertex> {
  final Library library;
  bool isLoadingRoot = true;
  _LoadingUnitBuilder? loadingUnit;
  _LibraryVertex(this.library);

  String toString() => "_LibraryVertex(${library.importUri})";
}

class HasEntryPointVisitor extends RecursiveVisitor {
  final PragmaAnnotationParser parser;
  bool _hasEntryPoint = false;

  HasEntryPointVisitor(this.parser);

  visitAnnotations(List<Expression> annotations) {
    for (var ann in annotations) {
      ParsedPragma? pragma = parser.parsePragma(ann);
      if (pragma is ParsedEntryPointPragma) {
        _hasEntryPoint = true;
        return;
      }
    }
  }

  @override
  visitClass(Class klass) {
    visitAnnotations(klass.annotations);
    klass.visitChildren(this);
  }

  @override
  defaultMember(Member node) {
    visitAnnotations(node.annotations);
  }

  bool hasEntryPoint(Library lib) {
    _hasEntryPoint = false;
    visitLibrary(lib);
    return _hasEntryPoint;
  }
}

List<LoadingUnit> computeLoadingUnits(
    Component component, HasEntryPointVisitor visitor) {
  // 1. Build the dominator tree for the library import graph.
  final map = <Library, _LibraryVertex>{};
  for (final lib in component.libraries) {
    map[lib] = new _LibraryVertex(lib);
  }
  for (final vertex in map.values) {
    for (final dep in vertex.library.dependencies) {
      final target = map[dep.targetLibrary]!;
      vertex.successors.add(target);
    }
  }
  final root = map[component.mainMethod!.enclosingLibrary]!;

  // Fake imports from root library to every core library or library containing
  // an entry point pragma so that they end up in the same loading unit
  // attributed to the user's root library.
  for (final vertex in map.values) {
    if (vertex == root) {
      continue;
    }
    if (vertex.library.importUri.isScheme("dart") ||
        visitor.hasEntryPoint(vertex.library)) {
      root.successors.add(vertex);
      vertex.isLoadingRoot = false;
    }
  }

  computeDominators(root);

  // 2. Find loading unit roots.
  for (var importer in map.values) {
    if ((importer != root) && (importer.dominator == null)) {
      continue; // Unreachable library.
    }
    for (var dep in importer.library.dependencies) {
      if (dep.isDeferred) {
        continue;
      }
      var importee = map[dep.targetLibrary]!;
      if (importer.isDominatedBy(importee)) {
        continue;
      }
      importee.isLoadingRoot = false;
    }
  }
  assert(root.isLoadingRoot);

  final List<_LoadingUnitBuilder> loadingUnits = <_LoadingUnitBuilder>[];
  for (var vertex in map.values) {
    if (vertex.isLoadingRoot) {
      var unit = new _LoadingUnitBuilder(vertex);
      vertex.loadingUnit = unit;
      unit.members.add(vertex.library);
      loadingUnits.add(unit);
    }
  }

  // 3. Attribute every library to the dominating loading unit.
  for (var vertex in map.values) {
    if (vertex.isLoadingRoot) {
      continue; // Already processed.
    }
    var dom = vertex.dominator;
    if (dom == null) {
      continue; // Unreachable library.
    }
    while (dom!.loadingUnit == null) {
      dom = dom.dominator;
    }
    vertex.loadingUnit = dom.loadingUnit;
    vertex.loadingUnit!.members.add(vertex.library);
  }

  // 4. Sort loading units so parents are before children. Normally this order
  // would already exist as a side effect of loading sources in import order,
  // but this isn't guaranteed when combining separately produced kernel files.
  for (var unit in loadingUnits) {
    var parent = unit.parent;
    if (parent != null) {
      parent.children.add(unit);
    }
  }
  var index = 0;
  loadingUnits.clear();
  loadingUnits.add(root.loadingUnit!);
  while (index < loadingUnits.length) {
    var unit = loadingUnits[index];
    unit.id = ++index;
    loadingUnits.addAll(unit.children);
  }

  return loadingUnits.map((u) => u.asLoadingUnit()).toList();
}

Component transformComponent(
    Component component, CoreTypes coreTypes, Target target) {
  final parser = ConstantPragmaAnnotationParser(coreTypes, target);
  final visitor = HasEntryPointVisitor(parser);
  final metadata =
      new LoadingUnitsMetadata(computeLoadingUnits(component, visitor));
  final repo = new LoadingUnitsMetadataRepository();
  component.addMetadataRepository(repo);
  repo.mapping[component] = metadata;

  return component;
}
