/*
 * Copyright (c) 2020-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 "test_utils.hpp"

#include <cugraph-ops-test/random/csr_generator.hpp>

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

#include <raft/random/rng_state.hpp>

#include <thrust/host_vector.h>

namespace cugraph::ops {

template <typename IdxT>
graph::fg_csr<IdxT> make_host_graph(const graph::fg_csr<IdxT> g, IdxT* offsets, IdxT* indices)
{
  graph::fg_csr<IdxT> out;
  out.n_nodes   = g.n_nodes;
  out.n_indices = g.n_indices;
  out.offsets   = offsets;
  out.indices   = indices;
  return out;
}

template <typename IdxT>
void generate_csr(graph::fg_csr<IdxT>& graph,
                  raft::random::RngState& r,
                  IdxT nodes,
                  IdxT nnz,
                  bool is_undirected = false)
{
  cuda::stream s(nullptr);
  generate_csr_on_device(graph, r, nodes, nnz, is_undirected, s);
}

template <typename IdxT>
void delete_csr(graph::fg_csr<IdxT>& graph)
{
  cuda::stream s(nullptr);
  delete_csr_from_device(graph, s);
}

template <typename IdxT>
void generate_csr_seq(graph::fg_csr_seq<IdxT>& graph,
                      raft::random::RngState& r,
                      IdxT n_graphs,
                      IdxT nodes,
                      IdxT nnz,
                      bool is_undirected = false)
{
  cuda::stream s(nullptr);
  generate_csr_seq_on_device(graph, r, n_graphs, nodes, nnz, is_undirected, s);
}

template <typename IdxT>
void generate_csc(graph::bipartite_csc<IdxT>& graph,
                  raft::random::RngState& r,
                  IdxT src_nodes,
                  IdxT dst_nodes,
                  IdxT nnz)
{
  cuda::stream s(nullptr);
  generate_csc_on_device(graph, r, src_nodes, dst_nodes, nnz, s);
}

template <typename IdxT>
void delete_csc(graph::bipartite_csc<IdxT>& graph)
{
  cuda::stream s(nullptr);
  delete_csc_from_device(graph, s);
}

template <typename IdxT>
void delete_csr_seq(graph::fg_csr_seq<IdxT>& graph)
{
  cuda::stream s(nullptr);
  delete_csr_seq_from_device(graph, s);
}

template <typename IdxT>
struct __attribute__((aligned(16))) ellpack_info {
  host_buffer<IdxT> neighbors{};
  host_buffer<IdxT> neighbor_counts{};
  ellpack_info() = default;
  ellpack_info(const ellpack_info& other)
  {
    neighbors.reserve(other.neighbors.size());
    neighbor_counts.reserve(other.neighbor_counts.size());
    neighbors.copy_from(other.neighbors);
    neighbor_counts.copy_from(other.neighbor_counts);
  }
};

template <typename IdxT>
struct __attribute__((aligned(16))) csr_info {
  host_buffer<IdxT> offsets{};
  host_buffer<IdxT> indices{};
  csr_info() = default;
  csr_info(const csr_info& other)
  {
    offsets.reserve(other.offsets.size());
    indices.reserve(other.indices.size());
    offsets.copy_from(other.offsets);
    indices.copy_from(other.indices);
  }
};

}  // namespace cugraph::ops
