/// \file


#include "steganography.h"
#include <QDebug>
Steganography::Steganography()
{
}

int cbtoi(char c){
    if(c == '0') return 0;
    else return 1 ;
}

string decToBin(int num, int pad)
{
    int r =  0;    // residue
                   // residuo
    int q = -1;    // quotient
                   // cociente
    string b = ""; // string to containt the result
                   // cadena de caracteres para contener el resultado


    while(q != 0)
    {
        r = num%2;
        q = num/2;
        num = q;

        if (r) b.insert(0, "1");
        else   b.insert(0, "0");
    }

    // if letter has less than pad bits, insert 0s at the beginning until length = pad
    // si letter tiene menos que pad bits, insertar 0s al principio hasta que el
    // length = pad
    while(b.length() < (unsigned long) pad)
        b.insert(0, "0");

    return b;
}


string messageToBinaryString(string str){
    string binStr = "";
    int temp;

    //converting message to binary string
    //convirtiendo un mensaje a una cadena de caracteres binarios
    for(unsigned int i = 0; i<str.length(); i++)
    {
        temp = static_cast<int>(str[i]);
        binStr.append(decToBin(temp, bitsPerLetter));
    }

    return binStr ;
}

char binStringToChar(string str){

    int value = 0 ;
    for(unsigned int i = 0; i < str.length(); i++){
        value = value << 1 ;
        if(str[i] == '1') value = value | 1 ;
    }
    return static_cast<char>(value) ;
}

int createMask(int lbits){
    return (1 << lbits) - 1;
}

void EmbbedMessage(const QImage & origImage, QImage & newImage, string msg){
    string binMsg ; // To store the message in binary.
                    // Para almacenar el mensaje en binario.
    unsigned long msg_index = 0 ;     // Will be used to pass through binStr
                                      // Sera utilizado para pasar atraves de binStr
    int red, green, blue ;            // Will store the integer representation of the colors.
                                      // Va a guardar la representacion entera de los colores

    int mask = createMask(1);
    QRgb p;

    binMsg = messageToBinaryString(msg);

    // We will include this postfix, so that the decoder will
    // know when the embedded message ends. It consists of 1 char
    // whose ASCII is 0.
    // Vamos a incluir este sufijo, tal que el decodificador sepa
    // cuando el mensaje embedido termina.  Este consiste de 1 caracter
    // cuyo ASCII es 0.
    binMsg.append(2*bitsPerLetter,'0');

    //for each pixel in image
    //por cada pixel.
    for(int i = 0; i < origImage.width(); i++)
    {
        for(int j = 0; j<origImage.height(); j++)
        {
            p = origImage.pixel(i,j);

            red  = qRed(p);

            if(msg_index < binMsg.length()){
                // clear the least significant bit of the red value
                // limpia el bit menos significativo del valor rojo
                red &= ~mask;
                // embed the corresponding bits from the mssage
                // empotra el bit correspondiente del mensaje
                red = red | cbtoi(binMsg[msg_index]) ;
                msg_index += 1 ;
            }

            green = qGreen(p);

            if(msg_index < binMsg.length()){
                green &= ~mask;
                green = green | cbtoi(binMsg[msg_index]);
                msg_index += 1 ;
            }

            blue  = qBlue(p);

            if(msg_index < binMsg.length()){
                blue &= ~mask;
                blue = blue |  cbtoi(binMsg[msg_index]);
                msg_index += 1 ;
            }
            else{
                // When the message is over we stop the loops
                // Cuando el mensaje termina paramos los loops
                i = origImage.width() ;
                break ;
            }
            newImage.setPixel(i,j,qRgb(red, green, blue));
        }
    }
}

string binaryStringToMessage(string binStr){

   // YOUR CODE HERE

}


string ExtractMessage(const QImage &stegoImage){

    // YOUR CODE HERE
    return "Este el mensaje cuando aun no has implementado la funcion";

}
