#ifndef __DYNPROGRAMMINGOP_H
#define __DYNPROGRAMMINGOP_H

/*@@@*************************************************************************/
/** \file  dynProg4Freespace.h
 * \date   Wed March 7 16:51 CET 2007
 * \author Hernan Badino
 * \notes  
*******************************************************************************
******************************************************************************/

/* INCLUDES */
#include <vector>
#include "typedImage.h"
#include "floatImage.h"

/* CONSTANTS */
#define DP4F_MAX_MEDFILT_KERNEL_SIZE 51

/* PROTOTYPES */

/* ******************************** CLASS ********************************** */
/**
 * High resolution depth map class.
 * 
 *
 * \brief    High resolution depth map class.
 * \author   Hernan Badino
 * \date     07.03.2007
 * \note     -
 * \sa       -
 *
 *************************************************************************** */
namespace VIC
{    
    class CDynamicProgrammingOp
    {
    public:
        /******************************/
        /*  DATA TYPES and CONSTANTS  */
        /******************************/

        struct Node
        {
            /// Value of the node.
            float     m_nodCost_f;

            /// Accumulated cost of the path.
            float     m_accCost_f;

            /// Best parent node.
            short int m_parNode_i;
        };

        typedef CTypedImage<Node> CNodeImage;

    public:
    
        /******************************/
        /*  Constructors/Destructor   */
        /******************************/

        CDynamicProgrammingOp ( );

        CDynamicProgrammingOp ( const int f_width_i,
                                const int f_height_i );

        virtual ~CDynamicProgrammingOp ( );


        /******************************/
        /*    COMPUTE METHODS         */
        /******************************/

        virtual bool compute ( const CFloatImage      & f_costImg,
                               std::vector<int>       & fr_vecRes_v,
                               const std::vector<int> & f_followPath    = std::vector<int>(0),
                               const std::vector<int> & f_pathTolVector = std::vector<int>(0) );

        /******************************/
        /*          DISPLAY           */
        /******************************/
    
        //virtual void showCostImageOvl ( const CDrawingList & f_drawList );
    
        /******************************/
        /*    SET GET METHODS         */
        /******************************/

        void  setDistanceCost ( const float f_distCost_f ) { m_distCost_f = f_distCost_f; }
        float getDistanceCost ( ) const { return m_distCost_f; }

        void  setDistanceTh ( const float f_distTh_f ) { m_distTh_f = f_distTh_f; }
        float getDistanceTh ( ) const { return m_distTh_f; }

        void  setPredictionCost ( const float f_predCost_f ) { m_predCost_f = f_predCost_f; }
        float getPredictionCost ( ) const { return m_predCost_f; }

        void  setPredictionTh ( const float f_predTh_f ) { m_predTh_f = f_predTh_f; }
        float getPredictionTh ( ) const { return m_predTh_f; }
 
        void  setInitialCost ( const float f_initialCost_f ) { m_initialCost_f = f_initialCost_f; }
        float getInitialCost ( ) const { return m_initialCost_f; }

        void  setMinCostValue ( const float f_minCost_f ) { m_minCostValue_f = f_minCost_f; }
        float getMinCostValue ( ) const { return m_minCostValue_f; }

        void  setMaxCostValue ( const float f_maxCost_f ) { m_maxCostValue_f = f_maxCost_f; }
        float getMaxCostValue ( ) const { return m_maxCostValue_f; }

        void  setApplyMedianFilter ( const bool f_apply_b ) { m_applyMedianFilter_b = f_apply_b; }
        bool  getApplyMedianFilter ( ) const { return m_applyMedianFilter_b; }

        void  setMedFiltKernelSize ( const int f_size_i ) { m_medFiltHKSize_i = f_size_i<=3?1:f_size_i/2; }
        int   getMedFiltKernelSize ( ) const { return m_medFiltHKSize_i * 2 + 1; }

        void  setFollowPathTolerance ( const int f_tol_i ) { m_pathTol_i = f_tol_i<1?1:f_tol_i; }
        int   getFollowPathTolerance ( ) const { return m_pathTol_i; }
    
        void  setCostImageSize( const int f_width_i, 
                                const int f_height_i );
 
        int   getWidth()  const { return m_width_i; }
        int   getHeight() const { return m_height_i; }
    
        void  setExpectedGradient ( const float * const f_vec_p );
        const float * getExpectedGradient ( ) const { return m_expectedGradient_p; }
        
        void  setDistCostVector ( const std::vector <float> * const f_vec_p );
        const std::vector <float> * getDistCostVector ( ) const { return m_distCostVector_p; }


        CNodeImage  getGraphImage() const { return m_nodesImg; }

        /******************************/
        /*    PROTECTED METHODS       */
        /******************************/
    protected:

        void  reinitialize();


        /******************************/
        /*    PROTECTED MEMBERS       */
        /******************************/
    protected:

        /// Matrix for the nodes.
        CNodeImage                        m_nodesImg;

        /// Width of the depth input cost image.
        int                               m_width_i;

        /// Height of the depth input cost image.
        int                               m_height_i;

        /// Distance cost.
        float                             m_distCost_f;

        /// Prediction cost.
        float                             m_predCost_f;

        /// Threshold for saturating the smoothness cost.
        float                             m_distTh_f;

        /// Threshold for saturating the prediction cost.
        float                             m_predTh_f;

        /// Initial cost.
        float                             m_initialCost_f;

        /// Minimum Cost to consider in the freespace computation.
        float                             m_minCostValue_f;

        /// Maximum Cost to consider in the freespace computation.
        float                             m_maxCostValue_f;

        /// Auxiliar internal vector.
        std::vector<int>                  m_auxVector;

        /// Expected Gradient vector.
        const float *                     m_expectedGradient_p;

        /// Distance Cost Vector.
        const std::vector<float> *        m_distCostVector_p;

        /// Apply Median Filter to result?
        bool                              m_applyMedianFilter_b;

        /// Size of the median filter kernel
        int                               m_medFiltHKSize_i;

        /// Tolerance in pixels of the region to consider 
        /// around the path to follow. For pyramidal implementation.
        int                               m_pathTol_i;
    };
}

#endif // __DYNPROGRAMMINGOP_H

