// $Header: https://oberon.oapd.inaf.it/shins/trunk/shins/src/tiptilt_ctrl/bcu/util/rtcDetector.hpp 3953 2022-05-19 08:34:04Z depa $

#pragma once

#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION

#include <algorithm>
#include <cmath>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

// #ifndef BOOST_NO_CXX11_HDR_TYPE_TRAITS
// #include <type_traits>
// #endif

#include <boost/python.hpp>
#include <boost/math/special_functions/round.hpp>
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/shared_ptr.hpp>


#include <Nice/BuiltinSequences.h>

#include "util/shins_util.h"
#include "tiptilt_ctrl/bcu/util/bcuMemoryMap.h"


namespace shins
{

namespace util
{

namespace su = shins::util;
namespace suc = shins::util::constants;
namespace sud = shins::util::defaults;


class rtcDetector
{
    private:
    bool m_simulation;

    int m_winRows;
    int m_winCols;
    int m_winCoordX;
    int m_winCoordY;
    int m_winSize;
    float m_detectorFrameRate;
    float m_camIntegrationTime;
    float m_lastSnakeTemperature;

    int m_nSlopePixels; // deve essere divisibile per 16 e compatibile con la generazione automatica delle sottoaperture
    int m_IrqNiosDelay;

    std::string m_strPixelBiasFile;      // must correspond with the window to be monitored
    Nice::SeqInt m_matPixelBias;

    std::vector<unsigned int> m_pixelInUseMask;       // _ocaub_OcamInUsePixelMap
    std::vector<unsigned int> m_nSlopesToDoMap;       // _ocaub_OcamNumSlopeToDo
    std::vector<unsigned int> m_SlopePixelsMap;     // pixel pointer map _ocaub_OcamSlopePixelsMap
    std::vector<unsigned int> m_pixelToSaveMap;       // _ocaub_OcamToSavePixelMap
    int set_irq_nios_delay();

    public:
    rtcDetector(const std::map<std::string, std::string>& _mapSetup);
    ~rtcDetector();

    void init(const std::map<std::string, std::string>& _mapSetup);


    int init_bias(const std::string & file_name);
    int update_n_slopes(int n_slopes);

    int set_cropping(const std::map<std::string, std::string> & cropSetup);

    const Nice::SeqInt & get_pixel_bias() const {
        return m_matPixelBias;
    }

    float get_last_snake_temperature() const {
        return m_lastSnakeTemperature;
    }
    void set_last_snake_temperature(float temp){
        m_lastSnakeTemperature = temp;
    }
    /* getters */
    Nice::SeqInt     get_irq_nios_delay_for_bcu () const;
    std::vector<int> get_window_size_cols();
    std::vector<int> get_window_size_rows();
    Nice::SeqInt get_in_use_pixel_map_for_bcu    () const;       // _ocaub_OcamInUsePixelMap
    Nice::SeqInt get_slopes_todo_map_for_bcu     () const;       // _ocaub_OcamNumSlopeToDo
    Nice::SeqInt get_pixel_to_save_map_for_bcu   () const;       // _ocaub_OcamToSavePixelMap
    Nice::SeqInt get_slope_pixel_map_for_bcu     () const;       // _ocaub_OcamSlopePixelsMap

    inline float get_cam_integration_time()       const {
        return m_camIntegrationTime;
    }
    int set_cam_integration_time(float cit);
    int set_frame_rate(float fr);

    inline bool get_simulation                          () {
        return m_simulation;
    }
    inline int get_slope_pixels_number                  () const {
        return m_nSlopePixels;
    }
    inline int get_window_size                          () const {
        return m_winSize;
    }
    inline int get_num_rows                             () const {
        return m_winRows;
    }
    inline int get_num_cols                             () const {
        return m_winCols;
    }
    inline Nice::SeqInt get_slope_pixels_number_for_bcu () const {
        return Nice::SeqInt(1, m_nSlopePixels);
    }
    inline float get_frame_rate                           () const {
        return m_detectorFrameRate;
    }


    template <typename T>
    T get_value_from_map(const std::map<std::string, std::string>& _mapSetup,
                         const std::string& _key);

};




template <typename T>
T rtcDetector::get_value_from_map(const std::map<std::string, std::string>& _mapSetup,
                                  const std::string& _key)
{
    T value = T();
    try
    {
        value = shins::util::get_value_from_map<
            T, std::map<std::string, std::string>, std::string
            >(_mapSetup, _key);
    }
    catch(std::invalid_argument& e)
    {
        W_LOG(e.what());
        throw e;
    }
    return value;
}

typedef boost::shared_ptr<rtcDetector> rtcDetectorPtr;


} // namespace util

} // namespace Sharknir
