#include "KokkosGraph_wiki_9pt_stencil.hpp"
#include "KokkosGraph_RCM.hpp"

template<typename rowmap_t, typename entries_t, typename labels_t>
void printReorderedMatrix(const rowmap_t& rowmapIn, const entries_t& entriesIn, const labels_t& invPermIn)
{
  using size_type = typename rowmap_t::non_const_value_type;
  using lno_t = typename entries_t::non_const_value_type;
  auto rowmap = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), rowmapIn);
  auto entries = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), entriesIn);
  auto invPerm = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), invPermIn);
  lno_t numVerts = rowmap.extent(0) - 1;
  decltype(invPerm) perm(Kokkos::view_alloc(Kokkos::WithoutInitializing, "Perm"), numVerts);
  for(lno_t i = 0; i < numVerts; i++)
    perm(invPerm(i)) = i;
  std::vector<lno_t> neighbors;
  for(lno_t i = 0; i < numVerts; i++)
  {
    lno_t origRow = perm(i);
    neighbors.clear();
    for(size_type j = rowmap(origRow); j < rowmap(origRow + 1); j++)
    {
      lno_t origNei = entries(j);
      lno_t nei = invPerm(origNei);
      neighbors.push_back(nei);
    }
    std::sort(neighbors.begin(), neighbors.end());
    size_t it = 0;
    for(lno_t j = 0; j < numVerts; j++)
    {
      if(it < neighbors.size() && j == neighbors[it])
      {
        std::cout << '*';
        it++;
      }
      else
        std::cout << ' ';
    }
    std::cout << '\n';
  }
  std::cout << '\n';
}


int main()
{
  Kokkos::initialize();
  {
    using GraphDemo::numVertices;
    GraphDemo::setGridDimensions(6, 6);
    RowmapType rowmapDevice;
    ColindsType colindsDevice;
    //Make the graph smaller so the matrix can be printed easily
    //Step 1: Generate the graph on host, allocate space on device, and copy.
    //See function "generate9pt" below.
    GraphDemo::generate9pt(rowmapDevice, colindsDevice);
    //Step 2: Run RCM and print the reordered matrix
    {
      auto rcmDevice = KokkosGraph::Experimental::graph_rcm<ExecSpace, RowmapType, ColindsType>(
          rowmapDevice, colindsDevice);
      std::cout << "Graph reordered by reverse Cuthill-McKee:\n";
      printReorderedMatrix(rowmapDevice, colindsDevice, rcmDevice);
    }
  }
  Kokkos::finalize();
  return 0;
}

