#ifndef __DSI_H
#define __DSI_H

/*@@@**************************************************************************
 ** \file  sgm
 * \date   Thu Jun 25 10:10:33 EDT 2009
 * \author Hernan Badino
 * \notes  
*******************************************************************************
******************************************************************************/

/* INCLUDES */
#include "image.h"
#include "ippDefs.h"
#include "logger.h"
#include "paramIOHandling.h"

/* CONSTANTS */

namespace VIC
{
    template <class ImgType_, class CostType_>
    class CDispSpaceImageOp
    {
    /// Public data types.
    public:
        typedef enum
        {
            CT_UVD,
            CT_UDV,
            CT_DUV
        } ECubeType;

        struct SDispSpaceImage
        {
            CostType_ * getRowColumnSlice ( int f_disp_i ) const
            {
                return data_p + (f_disp_i-minDisp_i) * width_ui * height_ui;
            }

            CostType_ * getPtrAtDispRowColumn ( int          f_disp_i,
                                                unsigned int f_row_ui, 
                                                unsigned int f_col_ui ) const
            {
                return data_p + (f_disp_i-minDisp_i) * width_ui * height_ui + 
                    f_row_ui * width_ui + f_col_ui;
            }

            CostType_ * getPtrAtRowColumnDisp ( unsigned int f_row_ui,
                                                unsigned int f_col_ui,
                                                int          f_disp_i ) const
            {
                return data_p + ( f_row_ui *  ( width_ui * dispRange_ui ) + 
                                  f_col_ui * dispRange_ui + 
                                  f_disp_i - minDisp_i );
            }

            CostType_ * getColumnDispSlice ( unsigned int f_row_ui ) const
            {
                return data_p + f_row_ui * ( width_ui * dispRange_ui );
            }

            CostType_ * getDispColumnSlice ( unsigned int f_row_ui ) const
            {
                return data_p + f_row_ui * ( width_ui * dispRange_ui );
            }

            CostType_ * getDispScanline ( unsigned int f_row_ui,
                                          unsigned int f_col_ui ) const
            {
                return data_p + f_row_ui * ( width_ui * dispRange_ui ) + f_col_ui * dispRange_ui;
            }

            void clear ( ) 
            {
                memset(data_p, 0, sizeof(CostType_) * width_ui * height_ui * dispRange_ui );
            }

            /// Width.
            unsigned int     width_ui;

            /// Height.
            unsigned int     height_ui;

            /// Disparity range.
            unsigned int     dispRange_ui;

            /// Disparity range.
            int              minDisp_i;

            /// Disparity range.
            int              maxDisp_i;

            /// Data.
            CostType_ *      data_p;
        };

    /// Constructors/Destructor
    public:        
        CDispSpaceImageOp ( ECubeType f_type_e = CT_DUV );
        ~CDispSpaceImageOp ( );
        
    /// Sets/Gets
    public: 
       /// Load parameters from parameter file.
        void             loadParameters ( const CParamIOHandling &f_paramReader );

        /// Set the image size.
        void             setImageSizes ( unsigned int f_width_ui,
                                         unsigned int f_height_ui,
                                         int          f_minDisp_i,
                                         int          f_maxDisp_i );

        /// Get the resulting disparity image.
        SDispSpaceImage
                         getDisparitySpaceImage() const
        {
            return m_dsi;
        }
        
        /// Get the resulting disparity image.
        ECubeType        getDSIType() const
        {
            return m_dsiType;
        }

        /// Get the resulting disparity image.
        void             setDSIType( ECubeType f_newType_e )
        {
            m_dsiType = f_newType_e;
        }
 
    /// Computation.
    public:
        bool             compute ( const CTypedImage<ImgType_> & f_leftImg, 
                                   const CTypedImage<ImgType_> & f_rightImg );

        /// Computation.
        bool             computeZSSD ( const CTypedImage<ImgType_> & f_leftImg, 
                                       const CTypedImage<ImgType_> & f_rightImg,
                                       const int      f_kW_i = 3, 
                                       const int      f_kH_i = 3,
                                       const bool     f_normalize_b = false );
    
       
        void             clear()  { m_dsi.clear(); }
        
    /// Help methods.
    protected:
        bool             computeUVD ( const CTypedImage<ImgType_> & f_leftImg, 
                                      const CTypedImage<ImgType_> & f_rightImg);
        
        bool             computeUDV ( const CTypedImage<ImgType_> & f_leftImg, 
                                      const CTypedImage<ImgType_> & f_rightImg );

        bool             computeDUV ( const CTypedImage<ImgType_> & f_leftImg, 
                                      const CTypedImage<ImgType_> & f_rightImg );

        void             setScale ( );
    /// Protected members.
    protected:

        /// Disparity space image.
        SDispSpaceImage               m_dsi;

        /// Disparity space image.
        ECubeType                     m_dsiType;

        /// Scale factor.
        unsigned char                 m_scaler_t;
        
        /// Scale factor.
        CostType_                     m_largeNumber_t;
    };

    #include "dsi_inline.h"

}


#endif // __DSI_H
