// Copyright (C) 2026 EDF
// All Rights Reserved
// This code is published under the GNU Lesser General Public License (GNU LGPL)
#ifndef CONTINUATIONVALUEAUTODIFF_H
#define CONTINUATIONVALUEAUTODIFF_H
#include <iostream>
#include <Eigen/Dense>
#include <type_traits>
#include <utility>
#include "StOpt/core/grids/FullGrid.h"
#include "StOpt/core/grids/LinearInterpolator.h"
#include "StOpt/regression/BaseRegression.h"
#include "StOpt/regression/dispatchRegressionAutoDiff.h"

/** \file ContinuationValueAutoDiff.h
 *  \brief Calculate and store continuation value function
 *  For a grid store continuation function values using its polynomial coefficients
 *  Auto Differentiation versoin with FullGrid
 *  \author Xavier Warin
 */

namespace StOpt
{

/// \class ContinuationValueAutoDiff ContinuationValueAutoDiff.h
/// Permits to calculate, store continuation values on a grid for regression methods
class ContinuationValueAutoDiff :
{

private :
    std::shared_ptr< FullGrid >    m_grid ; ///< grid used to define stock points
    std::shared_ptr< BaseRegression >  m_condExp ; ///< conditional expectation
    Eigen::ArrayXXd m_values ; ///< store basis coefficient for each stock  (nb function basis, nb stock points) if date non zero, cash otherwise
    int m_nbSimul ; // simulation  number

public :
    /// \brief Default constructor
    ContinuationValueAutoDiff() {}


    /// \brief Load another Continuation value object
    ///  Only a partial load of the objects is achieved
    /// \param p_grid   Grid to load
    /// \param p_condExp Condition expectation
    /// \param p_values coefficient polynomials for regression
    virtual void loadForSimulation(const  std::shared_ptr< SpaceGrid > &p_grid,
                                   const std::shared_ptr< BaseRegression >   &p_condExp,
                                   const Eigen::ArrayXXd &p_values)
    {
        m_grid = p_grid;
        m_condExp = p_condExp;
        m_values = p_values ;
    }

    template<typename T>
     T getValue(const  Eigen::Array<T, Eigen::Dynamic, 1> & p_ptOfStock,
                        const Eigen::ArrayXd  &p_coordinates) const
    {
      return dispatchRegressionGetValue(m_condExp,p_coordinates,m_grid->template createInterpolator<T>(p_ptOfStock)->applyVec(m_values.template cast<T>()));
     }
};
}
#endif /* CONTINUATIONVALUEAUTODIFF_H */
