/**
 *
 * @file plugins/MatrixVisualizer/Common/Quadtree.hpp
 *
 * @copyright 2008-2024 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria,
 *                      Univ. Bordeaux. All rights reserved.
 *
 * @author Camille Ordronneau
 *
 * @date 2024-07-17
 */
#ifndef QUADTREE_HPP
#define QUADTREE_HPP

#include "Zoom.hpp"

/**
 * \struct sliced_matrix
 * \brief A representation of a slice of a symbol matrix
 *
 */
typedef struct sliced_matrix_s
{
    /**
     * \brief The first column in the sliced matrix
     */
    int start_col;

    /**
     * \brief The first row in the sliced matrix
     */
    int start_row;

    /**
     * \brief The last column in the sliced matrix
     */
    int end_col;

    /**
     * \brief The last row in the sliced matrix
     */
    int end_row;

    /**
     * \brief The first column block in the sliced matrix
     */
    int start_cblk;

    /**
     * \brief The last column block in the sliced matrix
     */
    int end_cblk;

    /**
     * \brief The average color of the sliced matrix
     */
    float color_avg;

    /**
     * \brief A pointer to the matrix from where the slice have been taken
     */
    symbol_matrix_t *m_matrix;
} sliced_matrix_t;

/**
 * \class Quadtree
 * \brief This class contains one of the zoom methods, it is inherited from Zoom abstract class
 */
class Quadtree : public Zoom
{
public:
    /**
     * \fn Quadtree(symbol_matrix_t* matrix)
     * \brief Construct a new Quadtree object
     * \param matrix The matrix where the zoom is applied
     */
    Quadtree(symbol_matrix_t *matrix);

    /**
     * \fn ~Quadtree()
     * \brief Destroy the Quadtree object
     */
    ~Quadtree();

    /**
     * \fn void move(double x_start, double x_end, double y_start, double y_end)
     * \brief The function that is called when the zoom is applied, it containts the implementation of the zoom method.
     * \param x_start The start of x coordinate of the selected zone
     * \param x_end The end of x coordinate of the selected zone
     * \param y_start The start of y coordinate of the selected zone
     * \param y_end The end of y coordinate of the selected zone
     */
    void move(double x_start, double x_end, double y_start, double y_end);

private:
    /***********************
     *
     * Helper Functions.
     *
     ***********************/

    /**
     * \fn void createTiles(sliced_matrix_t &m, float x_coeff, float y_coeff)
     * \brief Slices the matrix `m` recursively untill the presision condition is satisfied then it fills the color matrix
     * \param m The matrix to be sliced
     * \param x_coeff A coefficient that helps in convertion between symbol matrix size and color matrix size
     * \param y_coeff A coefficient that helps in convertion between symbol matrix size and color matrix size
     */
    void createTiles(sliced_matrix_t &m, float x_coeff, float y_coeff);

    /**
     * \fn float average(sliced_matrix_t &m)
     * \brief Computes the average color for the matrix `m`
     * \param m The matrix for which the average color is computed
     * \return The average color
     */
    float average(sliced_matrix_t &m);

    /**
     * \fn float error(sliced_matrix_t &m)
     * \brief Computes the error between the average computed and the real color in the matrix `m`
     * \param m The matrix for which the error color is computed
     * \return The error
     */
    float error(sliced_matrix_t &m);

private:
    /**
     * \brief start column of the selected matrix
     */
    int start_col;

    /**
     * \brief start row of the selected matrix
     */
    int start_row;

    /**
     * \brief last column of the selected matrix
     */
    int end_col;

    /**
     * \brief last row of the selected matrix
     */
    int end_row;
};

#endif
