#ifndef __NORMALPREDICTOR_H
#define __NORMALPREDICTOR_H

/*@@@**************************************************************************
 ** \file  normalPredictor.h
 * \date   Mon Jun 22 14:55:16 EDT 2009
 * \author Hernan Badino
 * \notes  
*******************************************************************************
******************************************************************************/

/* INCLUDES */

#include <math.h>

#include "colorEncoding.h"
#include "operator.h"
#include "image.h"
#include "sphericalRangeImage.h"


/* CONSTANTS */

namespace VIC
{
    /* CLASS DEFINITION */
    class CNormalPredictorOp: public VIC::COperator
    {

    /// Public data types.
    public:
        typedef enum
        {
            FODM_3DSPACE,
            FODM_DISPSPACE
        } EFirstOrderDispMethod_t;

        typedef enum
        {
            CEM_VERTICAL,
            CEM_HORIZONTAL,
            CEM_NORMAL_X,
            CEM_NORMAL_Y,
            CEM_NORMAL_Z
        } EColorEncodingMode_t;
        
       typedef enum
        {
            NCM_NxCrossNy1,
            NCM_NxCrossNy2,
            NCM_Jacobian1,
            NCM_Jacobian2,
            NCM_3DDIFF,
            NCM_Rotation,
            NCM_LS
        } ENormalComputationMethod_t;
        
        const float GT_INVALID;
        
    /// Constructor, Desctructors
    public:    
        
        /// Constructors.
        CNormalPredictorOp ( COperator * const f_parent_p = NULL );
        
        /// Virtual destructor.
        virtual ~CNormalPredictorOp ();

        /// Cycle event.
        virtual bool cycle();
    
        /// Show event.
        virtual bool show();
    
        /// Init event.
        virtual bool initialize();
    
        /// Reset event.
        virtual bool reset();
    
        /// Exit event.
        virtual bool exit();

    /// User Operation Events
    public:
        /// Key pressed in display.
        virtual void keyPressed (     CKeyEvent * f_event_p );

        /// Mouse moved.
        virtual void mouseMoved (     CMouseEvent * f_event_p );


    /// Set/Gets (Parameters)
    public:
        //ADD_PARAM_ACCESS_NOTIFIER(S2D<double>,  m_roiSize,           SRISize,    createSRIs )

        ADD_PARAM_ACCESS (S2D<unsigned int>,          m_kernelSize,      KernelSize );
        ADD_PARAM_ACCESS (double,                     m_vectorLength_d,  VectorLength );
        ADD_PARAM_ACCESS (bool,                       m_applySobel_b,    ApplySobel );
        ADD_PARAM_ACCESS (bool,                       m_applyGauss_b,    ApplyGauss );
        /// Color encoding mode.
        ADD_PARAM_ACCESS (EFirstOrderDispMethod_t,    m_fodMethod_e,     FODMethod );
        ADD_PARAM_ACCESS (EColorEncodingMode_t,       m_encodingMode_e,  ColorEncodingMode );
        ADD_PARAM_ACCESS (ENormalComputationMethod_t, m_normalMode_e,    NormalMode );
        ADD_PARAM_ACCESS (bool,                       m_show3DNormals_b, Show3DNormals );
        ADD_PARAM_ACCESS (bool,                       m_show3DLocal_b,   Show3DLocal );

        ADD_PARAM_ACCESS (double,                     m_freeParam_d,     FreeParam );
        
        ADD_PARAM_ACCESS (bool,                       m_filterGauss_b,    FilterGauss );
        ADD_PARAM_ACCESS (unsigned int,               m_gaussIters_ui,    GaussIters  );
        ADD_PARAM_ACCESS (bool,                       m_filterMF_b,       FilterMF );
 
    protected:
        void         registerDrawingLists();
        void         allocateImages ();
        void         maskInvalid();
        void         calculateNormals();
        void         showNormalImage();
        void         show3D();
        void         computeLeastSquarePlane ( const std::vector<C3DVector> & f_points_v,
                                               C3DVector &                    fr_plane );

        bool         calculateGradientsWithIPP();

        void         calculateFirstOrderDisp();

        void         computeFODFromDispImgPred();        
        void         computeFODFrom3DNormals();
        
        void         maskInvalidForDisp( const CFloatImage &f_maskImg );

    /// Protected Data Types
    protected:

        /// First order disparity method to use.
        EFirstOrderDispMethod_t m_fodMethod_e;

        /// Normal image.
        C3DVectorImage          m_normalImg;

        /// Mask the output of the min/max filter with the invalid values.
        S2D<unsigned int>       m_kernelSize;

        /// Sobel or prewitt?
        bool                    m_applySobel_b;
        
        /// Apply gauss filter to the range image.
        bool                    m_applyGauss_b;

        /// Float range image.
        CFloatImage             m_rangeImg;

        /// Float range image.
        CFloatImage             m_bufferImg;

        /// Float range image.
        CFloatImage             m_gradXImg;

        /// Float range image.
        CFloatImage             m_gradYImg;

        /// Color encoding for sobel results.
        CColorEncoding          m_colorEncGrad;
        
        /// Color encoding mode for normal vectors.
        EColorEncodingMode_t    m_encodingMode_e;
        
        /// Color encoding for normal vectors.
        CColorEncoding          m_colorEncNormal;

        /// Display normal vector length.
        double                  m_vectorLength_d;
        
        /// Normal computation mode.
        ENormalComputationMethod_t
                                m_normalMode_e;

        /// Display normal vector length.
        bool                    m_show3DNormals_b;

        /// Display in local or global coord system.
        bool                    m_show3DLocal_b;

        /// Display normal vector length.
        double                  m_freeParam_d;

        /// 3D Vector image of first order disparities (du, dv, r)
        C3DVectorImage          m_firstDispUV;

        /// Aux first order disparity u.
        CFloatImage             m_sphDispU;

        /// Aux first order disparity v.
        CFloatImage             m_sphDispV;

        /// Aux range.
        CFloatImage             m_auxRange;

        /// Aux first order disparity u.
        CFloatImage             m_dispU;

        /// Aux first order disparity v.
        CFloatImage             m_dispV;

        /// Aux first order disparity u.
        CFloatImage             m_auxDispU;

        /// Aux first order disparity v.
        CFloatImage             m_auxDispV;

        /// Color encoding for normal vectors.
        CColorEncoding          m_colorEncFirstDisp;

        /// Apply MF?
        bool                    m_filterMF_b;

        /// Apply Gauss?
        bool                    m_filterGauss_b;

        /// Gauss iterations.
        unsigned int            m_gaussIters_ui;

    private:
        
   };
}

#endif // __NORMALPREDICTOR_H
