// Copyright (C) 2019 EDF
// All Rights Reserved
// This code is published under the GNU Lesser General Public License (GNU LGPL)
#include <pybind11/pybind11.h>
#include <pybind11/eigen.h>
#include <pybind11/stl_bind.h>
#include <pybind11/stl.h>
#include "StOpt/core/grids/OneDimRegularSpaceGrid.h"
#include "StOpt/core/grids/OneDimData.h"
#include "StOpt/sddp/OptimizerSDDPBase.h"
#include "test/c++/tools/sddp/OptimizeDemandSDDP.h"
#include "test/c++/tools/simulators/SimulatorGaussianSDDP.h"
#include "test/c++/python/FutureCurveWrap.h"

/** \file Pybind11SDDPOptimizers.cpp
*  \brief permits to map Optimizers for SDDP
* \author Xavier Warin
*/


/// \wrapper for Optimizer for demand test case in SDDP
class OptimizeDemandSDDPWrap : public OptimizeDemandSDDP<SimulatorGaussianSDDP>
{
public :

    /// \brief Constructor
    /// \param   p_sigD                volatility for demand
    /// \param   p_kappaD              AR coefficient for demand
    /// \param   p_timeDAverage        average demand
    /// \param   p_spot                Spot price
    /// \param   p_simulatorBackward   backward  simulator
    /// \param   p_simulatorForward    Forward simulator
    OptimizeDemandSDDPWrap(const  double   &p_sigD, const double &p_kappaD,
                           const  FutureCurve &p_timeDAverage,
                           const double &p_spot,
                           const std::shared_ptr<SimulatorGaussianSDDP> &p_simulatorBackward,
                           const std::shared_ptr<SimulatorGaussianSDDP> &p_simulatorForward):
        OptimizeDemandSDDP(p_sigD, p_kappaD,
                           std::make_shared< StOpt::OneDimData< StOpt::OneDimRegularSpaceGrid, double> >(static_cast<StOpt::OneDimData< StOpt::OneDimRegularSpaceGrid, double> >(p_timeDAverage)),
                           p_spot, p_simulatorBackward, p_simulatorForward) { }

};

namespace py = pybind11;

PYBIND11_MODULE(SDDPOptimizers, m)
{


    py::class_<OptimizeDemandSDDPWrap, std::shared_ptr<OptimizeDemandSDDPWrap>, StOpt::OptimizerSDDPBase >(m, "OptimizeDemandSDDP")
    .def(py::init< const  double &, const double &,  const  FutureCurve &,
         const double &,
         const std::shared_ptr<SimulatorGaussianSDDP> &,
         const std::shared_ptr<SimulatorGaussianSDDP> &>())
    .def("getSimulatorBackward", &OptimizeDemandSDDP<SimulatorGaussianSDDP>::getSimulatorBackward)
    .def("getSimulatorForward", &OptimizeDemandSDDP<SimulatorGaussianSDDP>::getSimulatorForward)
    .def("oneAdmissibleState", &OptimizeDemandSDDP<SimulatorGaussianSDDP>::oneAdmissibleState)
    ;
}
