#ifndef MESH_HPP
#define MESH_HPP

#include <Kokkos_Core.hpp>
#include <TinyVector.hpp>
#include <random>
#include <iostream>

template <typename ConnectivityType>
class Mesh
{
public:
  typedef ConnectivityType Connectivity;
  static constexpr size_t dimension = ConnectivityType::dimension;
  typedef TinyVector<dimension> Rd;

private:
  const Connectivity& m_connectivity;
  Kokkos::View<Rd*> m_xr;
  Kokkos::View<Rd*> m_x0;
  Kokkos::View<Rd*> m_xmax;

public:

  const Connectivity& connectivity() const
  {
    return m_connectivity;
  }

  const size_t& numberOfNodes() const
  {
    return m_connectivity.numberOfNodes();
  }

  const size_t& numberOfFaces() const
  {
    return m_connectivity.numberOfFaces();
  }

  const size_t& numberOfCells() const
  {
    return m_connectivity.numberOfCells();
  }

  Kokkos::View<Rd*> xr()
  {
    return m_xr;
  }

  const Kokkos::View<const Rd*> xr() const
  {
    return m_xr;
  }

  Kokkos::View<Rd*> x0()
  {
    return m_x0;
  }

  const Kokkos::View<const Rd*> x0() const
  {
    return m_x0;
  }

  Kokkos::View<Rd*> xmax()
  {
    return m_xmax;
  }

  const Kokkos::View<const Rd*> xmax() const
  {
    return m_xmax;
  }


  // pas constant

  /*
  Mesh(const Connectivity& connectivity)
    : m_connectivity(connectivity),
      m_xr("xr", connectivity.numberOfNodes()),
      m_x0("x0", 1),
      m_xmax("xmax", 1)
  {
    double a = -1.;
    double b = 2.;
    m_x0[0][0] = a;
    m_xmax[0][0] = b;
    const double delta_x = (b-a)/connectivity.numberOfCells();
    Kokkos::parallel_for(connectivity.numberOfNodes(), KOKKOS_LAMBDA(const int& r){
  	m_xr[r][0] = a + r*delta_x;
      });
  }
  */

  // pas non constant
  
  /*
  Mesh(const Connectivity& connectivity)
  : m_connectivity(connectivity),
    m_xr("xr", connectivity.numberOfNodes()),
    m_x0("x0", 1),
    m_xmax("xmax", 1)
  {
    double a = 0.;
    double b = 1.;
    m_x0[0][0] = a;
    m_xmax[0][0] = b;
    const double delta_x = (b-a)/connectivity.numberOfCells();
    Kokkos::parallel_for(connectivity.numberOfNodes(), KOKKOS_LAMBDA(const int& r){
  	if (r%4 == 1) {
  	  m_xr[r][0] = (r*2+1)*0.5*delta_x;
  	}
  	else {
  	  if (r%4==3) {
  	    m_xr[r][0] = ((r*3-1)/3.)*delta_x;
  	  }
  	  else 
  	    {
  	      m_xr[r][0] = r*delta_x;
  	    }
  	}
      });
  }
  */


  // pas aleatoire

  
  Mesh(const Connectivity& connectivity)
    : m_connectivity(connectivity),
      m_xr("xr", connectivity.numberOfNodes()),
      m_x0("x0", 1),
      m_xmax("xmax", 1)
  {
    double a = 0.;
    double b = 1.;
    m_x0[0][0] = a;
    m_xmax[0][0] = b;
    const double h = (b-a)/connectivity.numberOfCells();
    m_xr[0][0] = a;
    m_xr[connectivity.numberOfNodes()-1][0] = b;
    std::random_device rd;
    std::mt19937 mt(rd());
    std::uniform_real_distribution<double> dist(-h/2.1,h/2.1);
    for (int r=1; r<connectivity.numberOfNodes()-1; ++r){
      const double delta_xr = dist(mt);
      //      m_xr[r][0] = m_xr[r-1][0] + std::abs(delta_xr);
      m_xr[r][0] = r*h + delta_xr;
      std::cout << m_xr[r][0] << std::endl;
      } 
    std::exit(0);
  }
  



  ~Mesh()
  {
    ;
  }
};

#endif // MESH_HPP