#ifndef SOPT_TESTME
#define SOPT_TESTME
#include <sopt/config.h>
#include <Eigen/Core>
#include <sopt/types.h>
#include <sopt/wavelets/wavelets.h>

namespace sopt {
namespace pyWavelets {
template <class T> using Array = Eigen::Array<T, Eigen::Dynamic, Eigen::Dynamic>;
template <class T> using Map = Eigen::Map<Array<T>>;
template <class T> using Vector = Eigen::Array<T, Eigen::Dynamic, 1>;
template <class T> using MapV = Eigen::Map<Vector<T>>;

//! \brief direct transform wrapper called by cython
//! \param[in] py_input: double or complex pointer of input data generated by cython code.
//! \param[in] name: Daubechie wavelets coefficient.
//! \param[in] level: wavelet transform level.
//! \param[in] nrow/ncol: number of rows and columns of input data. In the case of a vector
//!                       input, ncol = 1.
//! \param[out] py_out: result data in either double or complex pointer.
template <class T>
void direct(T *py_input, T *py_output, std::string const &name, t_uint level, t_uint nrow,
            t_uint ncol) {
  auto const wavelets = sopt::wavelets::factory(name, level);
  if(nrow == 1 or ncol == 1) {
    wavelets.direct(MapV<T>(py_output, nrow * ncol), MapV<T>(py_input, nrow * ncol));
  } else
    wavelets.direct(Map<T>(py_output, nrow, ncol), Map<T>(py_input, nrow, ncol));
};
//! \brief indirect transform wrapper called by cython
//! \param[in] py_input: double or complex pointer of input data generated by cython code.
//! \param[in] name: Daubechie wavelets coefficient.
//! \param[in] level: wavelet transform level.
//! \param[in] nrow/ncol: number of rows and columns of input data. In the case of a vector
//!                       input, ncol = 1.
//! \param[out] py_out: result data in either double or complex pointer.
template <class T>
void indirect(T *py_input, T *py_output, std::string const &name, t_uint level, t_uint nrow,
              t_uint ncol) {
  auto const wavelets = sopt::wavelets::factory(name, level);
  if(nrow == 1 or ncol == 1)
    wavelets.indirect(MapV<T>(py_input, nrow * ncol), MapV<T>(py_output, nrow * ncol));
  else
    wavelets.indirect(Map<T>(py_input, nrow, ncol), Map<T>(py_output, nrow, ncol));
};
}
}

#endif
