#ifndef IMAGESCRAMBLER_H
#define IMAGESCRAMBLER_H

#include <QMainWindow>
#include <QFileDialog>
#include <QDir>
#include <QMessageBox>
#include <QShortcut>
#include <QImage>

namespace Ui {
    class ImageScrambler;
}

class ImageScrambler : public QMainWindow
{
    Q_OBJECT

public:

    /// \fn ImageScrambler::ImageScrambler(QWidget *parent)
    /// \~English
    /// \brief Constructor
    /// \~Spanish
    /// \brief Constructor
    explicit ImageScrambler(QWidget *parent = 0);

    /// \fn ImageScrambler::~ImageScrambler(QWidget *parent)
    /// \~English
    /// \brief Destructor
    /// \~Spanish
    /// \brief Destructor
    ~ImageScrambler();

    /// \fn void ImageScrambler::cropSwap(QImage &img, int x0, int y0, int x1, int y1, int width, int height )
    /// \~English
    /// \brief Funtion that crop two squares of equal size of an image or sub image and swaps them.
    /// The funtion receives two coords (x0, y0) and (x1, y1)  and a width and a height. Then swaps pixel
    /// by pixel the square formed from the top left coordinate (x0, y0) to the bottom right coordinate (x0+width, y0+height)
    /// with the square formed from the top left coordinate (x1, y1) to the bottom right (x1+width, y1+height).
    /// \param image Reference to the image to swap the squares.
    /// \param x0    The top left x coordinate of the first square in the image.
    /// \param y0    The top left y coordinate of the first square in the image.
    /// \param x1    The top left x coordinate of the second square in the image.
    /// \param y1    The top left y coordinate of the second square in the image.
    /// \param width Width of the squares
    /// \param height Height of the squares
    /// \~Spanish
    /// \brief Function que corta dos cuadrados del mismo tamano de una imagen o sub imagen y luego los intercambia.
    /// La funcion recibe dos coordenadas (x0,y0) y (x1,y1) y un ancho y un alto.  Entonces intercambia
    /// pixel por pixel el cuadrado que se forma desde la coordenada en el tope a la izquierda (x0,y0) a la coordenada abajo derecha (x0+ancho, y0+alto)
    /// con el cuadrado formado desde la coordenada en el tope izquierda (x1, y1) hasta la coordenada abajo derecha (x1+width, y1+height).
    /// \param image Referencia a la imagen a la que se le van a intercambiar los cuadros.
    /// \param x0    La coordenada arriba izquierda x del primer cuadrado en la imagen.
    /// \param y0    La coordenada arriba izquierda y del primer cuadrado en la imagen.
    /// \param x1    La coordenada arriba izquierda x del segundo cuadrado en la imagen.
    /// \param y1    La coordenada arriba izquierda y del segundo cuadrado en la imagen.
    /// \param width ancho de los cuadrados
    /// \param height altura de los cuadrados
    void cropSwap(QImage &img, int x0, int y0, int x1, int y1, int width, int height );

    /// \fn QImage ImageScrambler::ScrambleFilter(QImage image, int N, int sw, int sh, int width, int height)
    /// \~English
    /// \brief Funtion that recursively scrambles an images by dividing the image in squares (sub images)
    /// and then swapping them.  The first step the program does is divide the image in two or four squares
    /// and swap the squares, the resulting image is divided in four squares and then the same steps are applied
    /// recursively to each of the four squares.
    /// \param image The image to scramble
    /// \param level The depth of the recursion. The image will be scrambled in 4^n squares.
    /// \param sx Starting left top x coordinate of the image or sub image to divide
    /// \param sy Starting left top y coodinate of the image or sub image to divide
    /// \param width Width of the received image
    /// \param height Height of the received image
    /// \return the scrambled image
    /// \~Spanish
    /// \brief Funcion que recursivamente revuelve una imagen dividiendola en cuadrados (sub imagenes)
    /// y luego intercambiandolas.  El primer paso que el programa hace es dividir la imagen en two o cuatro cuadrados
    /// e intercambia los cuadrados, el resultado de la imagen se divide en cuatros cuadros y cada uno de los cuadros
    /// se le aplican los mismos pasos recursivamente.
    /// \param image The image a revolver
    /// \param level La profundidad de la recursion. La imagen se revolvera en 4^N cuadrados.
    /// \param sx La coordenada arriba izquierda x inicial de la imagen o sub imagen a dividir.
    /// \param sy La coordenada arriba izquierda y inicial de la imagen o sub imagen a dividir.
    /// \param width Ancho de la imagen recibida
    /// \param height Altura de la imagen recibida
    /// \return la imagen revuelta
    QImage ScrambleFilter(QImage image, int level, int sx, int sy, int width, int height);

private slots:

    /// \fn void ImageScrambler::on_btnLoadNewImage_clicked()
    /// \~English
    /// \brief Function display a file browsing window to load an image into the GUI
    /// \~Spanish
    /// \brief Funcion que despliega una ventana de busqueda de archivos para cargar
    /// una imagen en el GUI.
    void on_btnLoadNewImage_clicked();

    /// \fn void ImageScrambler::on_btnSave_clicked()
    /// \~English
    /// \brief Function that saves the scrambled image in the computer.
    /// \~Spanish
    /// \brief Funcion que guarda la imagen revuelta en la computadora.
    void on_btnSave_clicked();

    /// \fn void ImageScrambler::on_btnScrambleImage_clicked()
    /// \~English
    /// \brief Function invokes the ScrambleFilter function to scramble the image and
    /// load it in the GUI.
    /// \~Spanish
    /// \brief Funcion que invoca la funcion ScrambleFilter para revolver la imagen y
    /// cargarla en el GUI.
    void on_btnScrambleImage_clicked();

    /// \fn void ImageScrambler::on_btnDescrambleImage_clicked()
    /// \~English
    /// \brief Function that restore the scrambled image to the original image.
    /// \~Spanish
    /// \brief Funcion que restaura la imagen revuelta a la imagen original.
    void on_btnDescrambleImage_clicked();

    /// \fn void ImageScrambler::on_actionLoad_Image_triggered()
    /// \~English
    /// \brief Function that invokes the on_btnLoadNewImage_clicked() function.
    /// \~Spanish
    /// \brief Funcion que invoca la funcion on_btnLoadNewImage_clicked().
    void on_actionLoad_Image_triggered();

    /// \fn void ImageScrambler::on_actionSave_Image_triggered()
    /// \~English
    /// \brief Function that invokes the on_btnSave_clicked() function.
    /// \~Spanish
    /// \brief Funcion que invoca la funcion on_btnSave_clicked().
    void on_actionSave_Image_triggered();

    /// \fn void ImageScrambler::on_actionScramble_Image_triggered()
    /// \~English
    /// \brief Function that invokes the on_btnScrambleImage_clicked() function.
    /// \~Spanish
    /// \brief Funcion que invoca la funcion on_btnScrambleImage_clicked().
    void on_actionScramble_Image_triggered();

    /// \fn void ImageScrambler::on_actionDescramble_Image_triggered()
    /// \~English
    /// \brief Function that invokes the on_btnDescrambleImage_clicked() function.
    /// \~Spanish
    /// \brief Funcion que invoca la funcion on_btnDescrambleImage_clicked().
    void on_actionDescramble_Image_triggered();

private:
    Ui::ImageScrambler *ui;
    QImage originalImage;  //This will hold the original image.
    QImage scrambledImage; //This will hold the encrypted image.
    int scrambleDepth ;
};

#endif // MAINWINDOW_H
