#ifndef PETSC_UTILS_HPP
#define PETSC_UTILS_HPP

#include <utils/pugs_config.hpp>

#ifdef PUGS_HAS_PETSC

#include <algebra/CRSMatrix.hpp>
#include <algebra/DenseMatrix.hpp>
#include <algebra/TinyMatrix.hpp>

#include <petsc.h>

class PETScAijMatrixEmbedder
{
 private:
  Mat m_petscMat;
  Array<PetscInt> m_row_indices;
  Array<PetscInt> m_column_indices;
  const size_t m_nb_rows;
  const size_t m_nb_columns;

  PETScAijMatrixEmbedder(const size_t nb_rows, const size_t nb_columns, const double* A);

 public:
  PUGS_INLINE
  size_t
  numberOfRows() const
  {
    return m_nb_rows;
  }

  PUGS_INLINE
  size_t
  numberOfColumns() const
  {
    return m_nb_columns;
  }

  PUGS_INLINE
  operator Mat&()
  {
    return m_petscMat;
  }

  PUGS_INLINE
  operator const Mat&() const
  {
    return m_petscMat;
  }

  template <size_t N>
  PETScAijMatrixEmbedder(const TinyMatrix<N>& A) : PETScAijMatrixEmbedder{N, N, &A(0, 0)}
  {}

  PETScAijMatrixEmbedder(const DenseMatrix<double>& A) : PETScAijMatrixEmbedder{A.nbRows(), A.nbColumns(), &A(0, 0)} {}

  PETScAijMatrixEmbedder(const CRSMatrix<double, size_t>& A);

  ~PETScAijMatrixEmbedder();
};

#endif   // PUGS_HAS_PETSC

#endif   // PETSC_UTILS_HPP