#include "bdd.h"


#include <QDebug>
#include <QSqlRecord>
#include <QSqlQuery>
//#include <QDateTime>
#include <QCryptographicHash>


//============================================================================
// Création du modèle
//============================================================================
Bdd::Bdd() :
    QObject() {

    m_lignes.clear();
    m_ptr_ligne = 0;
}

//================================================================================================================================
//  Fonction :  Lit dans TB_Systeme l'état de 'Etat_cm3p' et le retourne.
//  Reçoit   :  Rien
//  Retour   :  0=En cours d'initialisation, 1=Démarré Ok ou -1=Démarrage impossible
//================================================================================================================================
qint16 Bdd::check_fin_configuration()
{
QSqlQuery query;
bool retour;

    retour = false;

    if (query.exec("SELECT Valeur FROM TB_Systeme WHERE Nom='Etat_cm3p' "))        // Exécution de la requête (sans erreur)
    {
        if (query.next())                       // Cas normal où on a trouvé une valeur :
        {
            retour = query.record().value(0).toInt();
        }
        else qDebug() << "La requête n'a renvoyé aucune valeur...";
    }
    else qDebug() << "/!\\ Erreur d'exécution de la requête !";

    return(retour);
}


//================================================================================================================================
//  Fonction :  Exécute la requête SQL reçue en paramètre puis va récupérer les résultats. Seule le premier enregistrement est
//              retourné car je ne sais pas renvoyer un vecteur de StringList (seul les vecteurs de String fonctionnent côté QML).
//              Juste avant le retour, on appelle la fonction de mise à jour du modèle. Cela permet de s'assurer que toutes les
//              valeurs utilisées dans QML sont à jour immédiatement (utile notamment après un UPDATE).
//  Reçoit   :  la requête à exécuter
//  Retour   :  un tableau de String avec autant d'entrées que de colonnes renvoyées par MariaDB. (Important : si elle renvoit
//              plus d'une ligne, seule la première est retournée)
//================================================================================================================================
QStringList Bdd::requete_unique(QString requete)
{
int i;

    QStringList resultats;
    QSqlQuery query(requete);
    while (query.next())
    {
        QSqlRecord resultat = query.record();

        for(i = 0; i < resultat.count(); i++)
        {
            resultats << resultat.value(i).toString();
        }

        break;                      // On ne renvoie que le premier enregistrement quoi qu'il arrive
    }

    return(resultats);
}


//================================================================================================================================
//  Fonction :  Exécute la requête SQL reçue en paramètre puis va récupérer les résultats. Les résultats sont stockés dans la
//              variable 'm_lignes' et la fonction renvoit soit -1 si erreur, soit le nombre d'enregistrements récupérés dans la BDD.
//  Reçoit   :  la requête à exécuter
//  Retour   :  -1 si erreur, n>=0 sinon (n = nombre de lignes récupérés dans la BDD par la requête)
//================================================================================================================================
qint64 Bdd::requete(QString requete)
{
QSqlQuery query;
QStringList ligne;                                          // Ligne temporaire
qint64 nb_lignes = 0;                                       // Nombre de lignes en retour de requête
qint16 nb_champs;                                           // Nombre de champs de la ligne
qint16 i;

//QTime myTimer;
//myTimer.start();

    m_lignes.clear();                                       // RAZ de la liste
    m_ptr_ligne = 0;                                        // RAZ du pointeur sur la liste

//qDebug() << "REQUETE : Temps écoulé avant exec : " << myTimer.elapsed() << "ms";

    query.setForwardOnly(true);                             // Permet d'améliorer l'efficacité (mais oblige ensuite à accéder dans l'ordre aux enregistrements)
    if (!query.exec(requete)) return(-1);                   // Exécution de la requête

//qDebug() << "REQUETE : Temps écoulé après exec : " << myTimer.elapsed() << "ms";

    while (query.next())                                    // Boucle sur tous les enregistrements
    {
        QSqlRecord resultat = query.record();               // Récupération de enregistrement
        nb_champs = resultat.count();                       // Récupération du nombre de champs
        //ligne = QStringList();                              // Ligne vide
        ligne.clear();

        for(i = 0; i < nb_champs; i++)                      // Boucle sur tous les champs
        {
            ligne << query.value(i).toString();             // Chargement du champs dans la ligne temporaire ('query.value' est réputé plus rapide que 'record.value'
        }

        m_lignes << ligne;                                  // Stockage de la ligne temporaire dans la liste de lignes
        nb_lignes ++;                                       // Maj du nombre de lignes
    }

//qDebug() << "REQUETE : Temps écoulé après chargement lignes : " << myTimer.elapsed() << "ms";
//qDebug() << "Taille de 'm_lignes' = " hash.toHex()<< m_lignes.count();

    return(nb_lignes);
}

//================================================================================================================================
//  Fonction :  Lit la ligne suivante dans la liste 'm_lignes'
//  Reçoit   :  Rien
//  Retour   :  un tableau de String avec autant d'entrées que de colonnes renvoyées par MariaDB.
//================================================================================================================================
QStringList Bdd::lecture_ligne()
{
QStringList ligne = QStringList();                          // Ligne temporaire


    ligne = m_lignes.at(m_ptr_ligne);
    m_ptr_ligne ++;                                        // Maj du pointeur sur la liste


    return(ligne);
}


//================================================================================================================================
//  Fonction :  Calcule le hash de la chaine reçue en entrée et le retourne
//  Reçoit   :  La chaine à hacher
//  Retour   :  La chaine hachée
//================================================================================================================================
QString Bdd::sha256(QString entree)
{
    QByteArray hash = QCryptographicHash::hash(entree.toUtf8(), QCryptographicHash::Sha256);
    return(hash.toHex());
}


//================================================================================================================================
//  Fonction :  Convertit un entier signé sur 16 bits en une chaine de 4 caractères hexa
//  Reçoit   :  La valeur à convertir
//  Retour   :  La chaine en hexa
//================================================================================================================================
QString Bdd::int16_to_chaine_hexa(qint16 entree)
{
    char chaine[20] = "";
    char retour[5] = "";
    uint16_t lg;

    sprintf(chaine, "%04X", (int16_t) entree);

    lg = strlen(chaine);
    if (lg > 4) sprintf(retour, "%s", (chaine + lg - 4));       // Nécessaire pour les valeurs négatives qui renvoient FFFF avant. Par exemple : 'FFFFFEC8' au lieu de 'FEC8'
    else sprintf(retour, "%s", chaine);                         // Cas normal de chaines déjà sur 4 octets

//qDebug() << "Chaine = " << chaine << " et Retour = [" << retour << "] et longueur = " << strlen(retour) ;
    return(retour);
}



