// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// -*- mode: C++ -*-
//
// Copyright 2020-2022 Google LLC
//
// Licensed under the Apache License v2.0 with LLVM Exceptions (the
// "License"); you may not use this file except in compliance with the
// License.  You may obtain a copy of the License at
//
//     https://llvm.org/LICENSE.txt
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: Giuliano Procida

#ifndef STG_SCC_H_
#define STG_SCC_H_

#include <cstddef>
#include <exception>
#include <functional>
#include <iterator>
#include <optional>
#include <unordered_map>
#include <utility>
#include <vector>

#include "error.h"

namespace stg {

/*
 * This is a streamlined Strongly-Connected Component finder for use with
 * procedurally generated or explored graphs, where the nodes and edges are not
 * known a priori.
 *
 * REQUIREMENTS
 *
 * The Node type must be copyable and have a suitable hash function.
 *
 * The user code must take the form of a Depth First Search which can be
 * repeatedly invoked on unvisited nodes until the whole graph has been
 * traversed.
 *
 * The user code must always follow edges to child nodes, even if it knows the
 * node has already been visited. The SCC finder needs to know about all edges.
 *
 * The user code must ensure that nodes are not re-examined once they have been
 * assigned to an SCC. The finder does not maintain any state for such nodes.
 *
 * GUARANTEES
 *
 * The SCC finder will ensure each node is examined exactly once.
 *
 * The SCCs will be presented in a topological order, leaves first.
 *
 * Note that within each SCC, nodes will be presented in DFS traversal order,
 * roots first. However, this is just an implementation detail, not a guarantee.
 *
 * USAGE
 *
 * Create an SCC finder with a lifetime bracketing a top-level DFS invocation.
 *
 * Before examining a node, check it's not been assigned to an SCC already and
 * then call Open. If the node is already "open" (i.e., is already waiting to be
 * assigned to an SCC), this will return an empty optional value and the node
 * should not be examined. If Open succeeds, a numerical node handle will be
 * returned and the node will be recorded as waiting to be assigned to an SCC.
 *
 * Now examine the node, making recursive calls to follow edges to other nodes.
 * Information about the node can be stored provisionally, but must NOT be used
 * to make decisions about whether to revisit it - that is Open's job.
 *
 * Once the examination is done, call Close, passing in the handle. If the node
 * has been identified as the "root" of an SCC, the whole SCC will be returned
 * as a vector of nodes. If any processing needs to be done (such as recording
 * the nodes as visited), this should be done now. Otherwise, an empty vector
 * will be returned.
 *
 * On destruction, after a top-level DFS invocation has completed, the SCC
 * finder will check that it is carrying no state.
 */
template <typename Node, typename Hash = std::hash<Node>>
class SCC {
 public:
  ~SCC() noexcept(false) {
    if (std::uncaught_exceptions() == 0) {
      Check(open_.empty() && is_open_.empty() && root_index_.empty())
          << "internal error: SCC state broken";
    }
  }

  std::optional<size_t> Open(const Node& node) {
    // Insertion will fail if the node is already open.
    auto [it, inserted] = is_open_.insert({node, is_open_.size()});
    auto ix = it->second;
    if (!inserted) {
      // Pop indices to nodes which cannot be the root of their SCC.
      while (root_index_.back() > ix) {
        root_index_.pop_back();
      }
      return {};
    }
    // Unvisited, record open node and record root index.
    open_.push_back(node);
    root_index_.push_back(ix);
    return {ix};
  }

  std::vector<Node> Close(size_t ix) {
    std::vector<Node> scc;
    Check(ix < open_.size()) << "internal error: illegal SCC node index";
    if (ix == root_index_.back()) {
      // Close SCC.
      root_index_.pop_back();
      const auto begin = open_.begin() + ix;
      const auto end = open_.end();
      for (auto it = begin; it != end; ++it) {
        is_open_.erase(*it);
      }
      scc.reserve(end - begin);
      std::move(begin, end, std::back_inserter(scc));
      open_.erase(begin, end);
    }
    return scc;
  }

 private:
  std::vector<Node> open_;  // index to node
  std::unordered_map<Node, size_t, Hash> is_open_;  // node to index
  std::vector<size_t> root_index_;
};

}  // namespace stg

#endif  // STG_SCC_H_
