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

import 'dart:math';

import '../ast.dart';

abstract class Graph<T> {
  Iterable<T> get vertices;

  Iterable<T> neighborsOf(T vertex);
}

/// [Graph] implementation using a collection of [Library] nodes as the graph
/// vertices and using library dependencies to compute neighbors.
///
/// If [coreLibrary] is provided, it will be included in the neighbor of all
/// vertices. Otherwise, `dart:core` will only be neighboring libraries that
/// explicitly dependent on it.
class LibraryGraph implements Graph<Library> {
  final Iterable<Library> libraries;
  final Library? coreLibrary;

  LibraryGraph(this.libraries, {this.coreLibrary});

  @override
  Iterable<Library> get vertices => libraries;

  @override
  Iterable<Library> neighborsOf(Library library) sync* {
    if (coreLibrary != null && library != coreLibrary) {
      yield coreLibrary!;
    }
    for (LibraryDependency dependency in library.dependencies) {
      yield dependency.targetLibrary;
    }
  }
}

/// Computes the strongly connected components of [graph].
///
/// This implementation is based on [Dijkstra's path-based strong component
/// algorithm]
/// (https://en.wikipedia.org/wiki/Path-based_strong_component_algorithm#Description).
List<List<T>> computeStrongComponents<T>(Graph<T> graph) {
  List<List<T>> result = <List<T>>[];
  int count = 0;
  Map<T, int> preorderNumbers = <T, int>{};
  List<T> unassigned = <T>[];
  List<T> candidates = <T>[];
  Set<T> assigned = new Set<T>();

  void recursivelySearch(T vertex) {
    // Step 1: Set the preorder number of [vertex] to [count], and increment
    // [count].
    preorderNumbers[vertex] = count++;

    // Step 2: Push [vertex] onto [unassigned] and also onto [candidates].
    unassigned.add(vertex);
    candidates.add(vertex);

    // Step 3: For each edge from [vertex] to a neighboring vertex [neighbor]:
    for (T neighbor in graph.neighborsOf(vertex)) {
      int? neighborPreorderNumber = preorderNumbers[neighbor];
      if (neighborPreorderNumber == null) {
        // If the preorder number of [neighbor] has not yet been assigned,
        // recursively search [neighbor];
        recursivelySearch(neighbor);
      } else if (!assigned.contains(neighbor)) {
        // Otherwise, if [neighbor] has not yet been assigned to a strongly
        // connected component:
        //
        // * Repeatedly pop vertices from [candidates] until the top element of
        //   [candidates] has a preorder number less than or equal to the
        //   preorder number of [neighbor].
        while (preorderNumbers[candidates.last]! > neighborPreorderNumber) {
          candidates.removeLast();
        }
      }
    }
    // Step 4: If [vertex] is the top element of [candidates]:
    if (candidates.last == vertex) {
      // Pop vertices from [unassigned] until [vertex] has been popped, and
      // assign the popped vertices to a new component.
      List<T> component = <T>[];
      while (true) {
        T top = unassigned.removeLast();
        component.add(top);
        assigned.add(top);
        if (top == vertex) break;
      }
      result.add(component);

      // Pop [vertex] from [candidates].
      candidates.removeLast();
    }
  }

  for (T vertex in graph.vertices) {
    if (preorderNumbers[vertex] == null) {
      recursivelySearch(vertex);
    }
  }

  return result;
}

/// A [Graph] using strongly connected components, as computed by
/// [computeStrongComponents], as vertices. Neighbors are computed using the
/// neighbors of the provided [subgraph] which was used to compute the strongly
/// connected components.
class StrongComponentGraph<T> implements Graph<List<T>> {
  final Graph<T> subgraph;
  final List<List<T>> components;
  final Map<T, List<T>> _elementToComponentMap = {};
  final Map<List<T>, Set<List<T>>> _neighborsMap = {};

  StrongComponentGraph(this.subgraph, this.components) {
    for (List<T> component in components) {
      for (T element in component) {
        _elementToComponentMap[element] = component;
      }
    }
  }

  Set<List<T>> _computeNeighborsOf(List<T> component) {
    Set<List<T>> neighbors = {};
    for (T element in component) {
      for (T neighborElement in subgraph.neighborsOf(element)) {
        List<T> neighborComponent = _elementToComponentMap[neighborElement]!;
        if (component != neighborComponent) {
          neighbors.add(neighborComponent);
        }
      }
    }
    return neighbors;
  }

  @override
  Iterable<List<T>> neighborsOf(List<T> vertex) {
    return _neighborsMap[vertex] ??= _computeNeighborsOf(vertex);
  }

  @override
  Iterable<List<T>> get vertices => components;
}

const int cyclicMarker = -1;

int _topologicalSortInternal<T>(
    Graph<T> graph, TopologicalSortResult<T> result, T vertex) {
  int? index = result.indexMap[vertex];
  if (index == null) {
    result.indexMap[vertex] = cyclicMarker;
    int index = 0;
    for (T neighbor in graph.neighborsOf(vertex)) {
      int neighborIndex = _topologicalSortInternal(graph, result, neighbor);
      if (neighborIndex == cyclicMarker) {
        result.cyclicVertices.add(vertex);
        return cyclicMarker;
      } else {
        index = max(index, neighborIndex + 1);
      }
    }
    result.sortedVertices.add(vertex);
    if (index >= result.layers.length) {
      assert(index == result.layers.length);
      result.layers.add([vertex]);
    } else {
      result.layers[index].add(vertex);
    }
    return result.indexMap[vertex] = index;
  }
  return index;
}

/// Perform a topological sorting of the vertices in [graph], returning a
/// [TopologicalSortResult] object with the result.
TopologicalSortResult<T> topologicalSort<T>(Graph<T> graph) {
  TopologicalSortResult<T> result = new TopologicalSortResult();

  for (T vertex in graph.vertices) {
    _topologicalSortInternal(graph, result, vertex);
  }
  return result;
}

/// The result of computing the [topologicalSort] on a [Graph].
class TopologicalSortResult<T> {
  /// The non-cyclic vertices of the graph sorted in topological order.
  final List<T> sortedVertices = [];

  /// The cyclic vertices of graph, including vertices that have a path to
  /// a vertex.
  final List<T> cyclicVertices = [];

  /// The topological index of all non-cyclic vertices of the graph.
  ///
  /// The "topological index" of a vertex is the length of the longest path
  /// through neighbors. For vertices with no neighbors, the index is 0.
  /// For any other vertex, it is 1 plus max of the index of its neighbors.
  final Map<T, int> indexMap = {};

  /// The non-cyclic vertices in layers according to their topological index.
  /// That is, `layers[i]` contain the list of vertices with index `i`.
  final List<List<T>> layers = [];
}

/// Find vertices in [graph] that either is in [vertices], has a neighbor in
/// [vertices], has a neighbor of a neighbor (etc) in [vertices].
Set<T> calculateTransitiveDependenciesOf<T>(Graph<T> graph, Set<T> vertices) {
  // Compute direct dependencies for each vertex (the reverse of the
  // edges returned by `graph.neighborsOf`).
  Map<T, Set<T>> directDependencies = <T, Set<T>>{};
  List<T> workList = [];
  {
    for (T vertex in graph.vertices) {
      if (vertices.contains(vertex)) workList.add(vertex);
      for (T neighbor in graph.neighborsOf(vertex)) {
        (directDependencies[neighbor] ??= new Set<T>()).add(vertex);
        if (vertices.contains(neighbor)) workList.add(vertex);
      }
    }
  }

  // Collect and remove all dependencies.
  Set<T> left = new Set<T>.of(graph.vertices);
  Set<T> transitive = {};
  while (workList.isNotEmpty) {
    T removed = workList.removeLast();
    if (left.remove(removed)) {
      Set<T>? s = directDependencies[removed];
      if (s != null) {
        // [s] is null for leaves.
        workList.addAll(s);
      }
      transitive.add(removed);
    }
  }
  return transitive;
}
