/*
 * Copyright (c) 2021-2023, NVIDIA CORPORATION. All rights reserved.
 *
 * This source code and/or documentation ("Licensed Deliverables") are
 * subject to NVIDIA intellectual property rights under U.S. and
 * international Copyright laws.
 */

#pragma once

#include <cugraph-ops/cuda/stream.hpp>
#include <cugraph-ops/graph/format.hpp>

#include <raft/random/rng_state.hpp>

#include <cstdint>

namespace cugraph::ops::graph {

/**
 * @brief Generate a random graph in CSR format on device
 *
 * @param[inout] graph          graph to be generated
 * @param[inout] r              RAFT RngState object
 * @param[in]    nodes          number of nodes
 * @param[in]    nnz            number of indexes (neighbors)
 * @param[in]    is_undirected  if `true`, generate an undirected graph.
 *                              In this case, the actual number of indices is:
 *                              `2 * floor(nnz / 2)`
 * @param[in]    stream         cuda stream
 *
 * @note this could generate duplicate edges (multi-graphs)!!!
 *
 * @{
 */
void generate_csc_on_device(csc_s32_t& graph,
                            raft::random::RngState& r,
                            int32_t nodes,
                            int32_t nnz,
                            bool is_undirected,
                            const cuda::stream& stream);
void generate_csc_on_device(csc_s64_t& graph,
                            raft::random::RngState& r,
                            int64_t nodes,
                            int64_t nnz,
                            bool is_undirected,
                            const cuda::stream& stream);
/** @} */

/**
 * @brief Generate a random and undirected graph in CSR format on device
 *
 * @param[inout] graph          graph to be generated
 * @param[out]   rev_edge_ids   position indices for each edge
 *                              of the corresponding reverse edge,
 *                              i.e. its corresponding position in graph.indices
 * @param[inout] r              RAFT RngState object
 * @param[in]    nodes          number of nodes
 * @param[in]    nnz            number of indexes (neighbors)
 * @param[in]    stream         cuda stream
 *
 * @note this could generate duplicate edges (multi-graphs)!!!
 *
 * @{
 */
void generate_csc_on_device(csc_s32_t& graph,
                            int32_t* rev_edge_ids,
                            raft::random::RngState& r,
                            int32_t nodes,
                            int32_t nnz,
                            const cuda::stream& stream);
void generate_csc_on_device(csc_s64_t& graph,
                            int64_t* rev_edge_ids,
                            raft::random::RngState& r,
                            int64_t nodes,
                            int64_t nnz,
                            const cuda::stream& stream);
/** @} */

/**
 * @brief Generate a random bipartite graph in CSC format on device
 *
 * @param[inout] graph          graph to be generated
 * @param[inout] r              RAFT RngState object
 * @param[in]    src_nodes      number of source nodes
 * @param[in]    dst_nodes      number of destination nodes
 * @param[in]    nnz            number of indexes (neighbors)
 * @param[in]    stream         cuda stream
 *
 * @note this could generate duplicate edges (multi-graphs)!!!
 *
 * @{
 */
void generate_csc_on_device(bipartite_csc_s32_t& graph,
                            raft::random::RngState& r,
                            int32_t src_nodes,
                            int32_t dst_nodes,
                            int32_t nnz,
                            const cuda::stream& stream);
void generate_csc_on_device(bipartite_csc_s64_t& graph,
                            raft::random::RngState& r,
                            int64_t src_nodes,
                            int64_t dst_nodes,
                            int64_t nnz,
                            const cuda::stream& stream);
/** @} */

/**
 * @brief Delete the previously generated graph from device
 *
 * @param[inout] graph  graph to be deleted
 * @param[in]    stream cuda stream
 *
 * @{
 */
void delete_csc_from_device(const csc_s32_t& graph, const cuda::stream& stream);
void delete_csc_from_device(const csc_s64_t& graph, const cuda::stream& stream);
/** @} */

/**
 * @brief Delete the previously generated CSC graph from device
 *
 * @param[inout] graph  graph to be deleted
 * @param[in]    stream cuda stream
 *
 * @{
 */
void delete_csc_from_device(const bipartite_csc_s32_t& graph, const cuda::stream& stream);
void delete_csc_from_device(const bipartite_csc_s64_t& graph, const cuda::stream& stream);
/** @} */

}  // namespace cugraph::ops::graph
