// Copyright (C) 2025 EDF
// All Rights Reserved
// This code is published under the GNU Lesser General Public License (GNU LGPL)
#ifndef MESH2DGENERS_H
#define MESH2DGENERS_H
#include "geners/GenericIO.hh"
#include "StOpt/core/grids/Mesh2D.h"

/** \file Mesh2DGener.h
 *  \brief Define non intrusive serialization with random access
*  \author Xavier Warin
 */
/// specialize the ClassIdSpecialization template
/// so that a ClassId object can be associated with the class we want to
/// serialize.  The second argument is the version number.
///@{
gs_specialize_class_id(StOpt::Mesh2D, 1)
/// an external class
gs_declare_type_external(StOpt::Mesh2D)
///@}
namespace gs
{
//
/// \brief  This is how the specialization of GenericWriter should look like
//
template <class Stream, class State >
struct GenericWriter < Stream, State, StOpt::Mesh2D,
           Int2Type<IOTraits<int>::ISEXTERNAL> >
{
    inline static bool process(const StOpt::Mesh2D  &p_mesh, Stream &p_os,
                               State *, const bool p_processClassId)
    {
        // If necessary, serialize the class id
        static const ClassId current(ClassId::makeId<StOpt::Mesh2D >());
        const bool status = p_processClassId ? ClassId::makeId<StOpt::Mesh2D >().write(p_os) : true;
        // Serialize object data if the class id was successfully
        // written out
        if (status)
        {
	  write_pod(p_os, p_mesh.getXL());
	  write_pod(p_os, p_mesh.getXR());
	  write_pod(p_os, p_mesh.getYB());
	  write_pod(p_os, p_mesh.getYT());
	  write_pod(p_os, p_mesh.getVerticeLT());
	  write_pod(p_os, p_mesh.getVerticeLB());
	  write_pod(p_os, p_mesh.getVerticeRB());
	  write_pod(p_os, p_mesh.getVerticeRT());
       }
        // Return "true" on success, "false" on failure
        return status && !p_os.fail();
    }
};

/// \brief  And this is the specialization of GenericReader
//
template <class Stream, class State  >
struct GenericReader < Stream, State, StOpt::Mesh2D, Int2Type<IOTraits<int>::ISEXTERNAL> >
{
    inline static bool readIntoPtr(StOpt::Mesh2D  *&ptr, Stream &p_is,
                                   State *p_st, const bool p_processClassId)
    {

      // Make sure that the serialized class id is consistent with
      // the current one
      static const ClassId current(ClassId::makeId<StOpt::Mesh2D>());
      const ClassId &stored = p_processClassId ? ClassId(p_is, 1) : p_st->back();
      current.ensureSameId(stored);
      
      double xL;
      read_pod(p_is,&xL);
      double xR;
      read_pod(p_is,&xR);
      double yB;
      read_pod(p_is,&yB);
      double yT;
      read_pod(p_is,&yT);
      int verticeLT;
      read_pod(p_is, &verticeLT);
      int verticeLB;
      read_pod(p_is, &verticeLB);
      int verticeRB;
      read_pod(p_is, &verticeRB);
      int verticeRT;
      read_pod(p_is, &verticeRT);
      if (p_is.fail())
	// Return "false" on failure
	return false;
      //Build the object from the stored data
      if (ptr)
        {
	  *ptr = StOpt::Mesh2D(xL,xR,yB,yT,verticeLT,verticeLB,verticeRB,verticeRT);
        }
      else
	{
	   ptr = new StOpt::Mesh2D(xL,xR,yB,yT,verticeLT,verticeLB,verticeRB,verticeRT);
	}
      return true;
    }

    inline static bool process(StOpt::Mesh2D &s, Stream &is,
                               State *st, const bool p_processClassId)
    {
      // Simply convert reading by reference into reading by pointer
      StOpt::Mesh2D *ps = &s;
      return readIntoPtr(ps, is, st, p_processClassId);
    }
};
}


#endif
