/***************************************************************************
 *   Copyright (C) 2008 by Dr Pierre-Marie DESOMBRE                        *
 *   pm.desombre@medsyn.fr                                                 *
 *                  on a idea from Eric Maeker                             *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "connexion.h"

#include <QMessageBox>
#include <QString>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QApplication>
#include <QtSql>
#include <QDebug>

 

bool WarnDebugMessage = true;
using namespace Common;

Connexion::Connexion(QObject *parent) : QObject(parent),
        m_IsDBConfigured(false)
{
    BASE = QString("myChoices");
}

Connexion::~Connexion(){}

const QString Connexion::getNameOfBase(){
    return BASE;
}

bool Connexion::connect(){
    int driverType = 0;
    QString log    = "root";
    QString pass   = "";
    QString host   = "localhost";
    //QString port   = ;
    QString driver = "QSQLITE";
    //--------test driver--------------------------------
    qDebug() << __FILE__ << QString::number(__LINE__)  << "Driver chosen is "+driver;
    if(driver == "QMYSQL"){
        driverType = Driver_MySQL;
    }
    else if(driver == "QSQLITE"){
        driverType = Driver_SQLite;
    }
    else if(driver == "QPOSTGRESQL"){
        driverType = Driver_PostGreSQL;
    }
    else{
        QMessageBox::critical(0,trUtf8("Critical"),
                    trUtf8("Le driver de la base de données ne peut pas être défini.\n"
                    "Vous devez écrire dans config.ini après Driver :\n"
                    "pour MySql : MYSQL\npour Sqlite : SQLITE\npour PostGresql : POSTGRESQL."),
                    QMessageBox::Ok);
        return false;
    }
    //--------------------------------------
    
    bool dbTest = 0;
    switch (driverType) {
        case Driver_MySQL :
        {
            m_db = QSqlDatabase::addDatabase("QMYSQL",BASE);
            m_db.setHostName(host);
            m_db.setDatabaseName(BASE);
            m_db.setUserName(log);
            m_db.setPassword(pass);
              if (WarnDebugMessage){
                qWarning() << "Connecting  database" << host <<  log << pass ;
              }
            dbTest = (!m_db.isOpen()) && (!m_db.open());
            break;
        }
        case Driver_SQLite :
        {
            m_db = QSqlDatabase::addDatabase("QSQLITE",BASE);
            m_db.setDatabaseName(qApp->applicationDirPath()+"/"+BASE+".db");
            m_db.setHostName(host);
            m_db.setUserName(log);
            m_db.setPassword(pass);            
            
            if(!m_db.open()){
                qWarning() << "database cannot open";
            }
            if (WarnDebugMessage){
                qWarning() << "Connecting  database SQLite " + m_db.databaseName() +" "
                + QString::number(__LINE__);
              }
            QStringList tables = m_db.tables();
            qDebug() << "tables "+QString::number(tables.size());
            dbTest = (tables.size() < 1);
            break;
        }
        case Driver_PostGreSQL :
            break;
    }

    if (dbTest) {
        if (WarnDebugMessage){
                qWarning() << "Connected to  database"
                           << m_db.databaseName()
                           << __FILE__
                           << QString::number(__LINE__);
            }
        if (isDatabaseCorrupted(driverType,m_db))
             {
             	  if (!createDatabase(driverType))
             	  {
             	  	  qWarning() << __FILE__ << QString::number(__LINE__) 
             	  	  << "database cannot be created" ;
             	  	  return false;
             	      }
                 }
             
    }
    return true;
}


bool Connexion::isDatabaseCorrupted(const int driverType,QSqlDatabase &m_db)
{

    QString driverName = "";
    if(driverType == Driver_MySQL){
        driverName = "QMYSQL";
        }
    if(driverType == Driver_SQLite){
        driverName = "QSQLITE";
        }
    if(driverType == Driver_PostGreSQL){
        driverName = "QPOSTGRESQL";
        }
    if(!m_db.isOpen()){
       qWarning() << "m_db is not opened " << __FILE__ << __LINE__;
    }
    qDebug() << __FILE__ << " driverName ="+driverName;
    qDebug() << __FILE__ << " database ="+m_db.connectionName();

    int tablesCount = 2;
    QSqlTableModel model(this,m_db);
    model.setTable(BASE);
    int count = model.columnCount();
    qDebug() << __FILE__ << QString::number(__LINE__) 
    << " count =" << QString::number(count);
    qDebug() << __FILE__ << QString::number(__LINE__) 
    << " tableCount =" << QString::number(tablesCount);
    return count !=tablesCount;
}



bool Connexion::createFirstSqlConnection() const
{

     QSqlDatabase db = QSqlDatabase :: addDatabase("QMYSQL","mysql");
     db.setHostName("localhost");
     db.setDatabaseName("mysql");
     db.setUserName("root");
     db.setPassword("");
     if(!db.open()) {
         qWarning() << "la base firstConnection ne peut être ouverte.";
     return false;
     }

  return true;
}

bool Connexion::createDatabase(int driver) 
{
    qWarning()<< "in createDatabase" << __FILE__;
    if (driver==Driver_SQLite){
        if (!createDatabaseSchema(Driver_SQLite))
        {
        	  qWarning() << __FILE__ << QString::number(__LINE__) 
        	  << "unable to create medicinesChoice database" ;
        	  return false;
            }
        return true;
        }
        

    if (!createFirstSqlConnection()) {//MYSQL
        QMessageBox::warning(qApp->activeWindow(),
            tr("Fatal error"),
            tr("An error occured during medicinesChoice database creation.\nDo you have ")+"MYSQL"+""
            ""+tr(" installed ?"),
            QMessageBox::Abort);
    }
    QSqlDatabase dbFirst = QSqlDatabase::database("mysql");
    QString reqForA = "CREATE DATABASE medicinesChoice";
    QSqlQuery q(dbFirst);
    q.exec(reqForA);
    if (q.lastError().isValid() == true) {
        QMessageBox::warning(qApp->activeWindow(),
                             tr("Fatal error"),
                             tr("An error occured during medicinesChoice database creation.\n")
                             +__FILE__+" "+QString::number(__LINE__),
                             QMessageBox::Abort);
        if (WarnDebugMessage)
            qWarning() << "SQL Error" << q.lastError().text() ;
        return false;
    }
    if (!createDatabaseSchema(Driver_MySQL))
        {
        	  qWarning() << __FILE__ << QString::number(__LINE__) 
        	  << "unable to create medicinesChoice database" ;
        	  return false;
            }
    return true;
}



bool Connexion::createDatabaseSchema(int driver)
{
    bool result = true;
    if ((driver!=Driver_SQLite) && (!createDatabase(driver))) {
        QMessageBox::critical(0, tr("Critical"), tr("Unable to create database."), QMessageBox::Ok);
        result = false;
    }
    QHash<QString, QString> name_sql;
    //ITEM TYPE_OF_ITEM PARENT_ITEM PARENT_OR_CHILD ICON DATE_DONE DATE_NEXT ABSTRACT RESULT
    if (driver==Driver_MySQL) {
    name_sql.insert("Table "+BASE,
                    "CREATE TABLE IF NOT EXISTS "+BASE+" ("
                    "ID_Primkey bigint(20) UNSIGNED  NOT NULL  auto_increment ,"
                    "ITEM longtext COLLATE utf8_unicode_ci NOT NULL,"
                    "PRIMARY KEY(ID_Primkey));");

    }
    else if(driver==Driver_SQLite) {
    name_sql.insert("Table "+BASE,
                    "CREATE TABLE IF NOT EXISTS	"+BASE+"  ("
                    "ID_Primkey   INTEGER PRIMARY KEY,"
                    "ITEM longtext COLLATE utf8_unicode_ci NOT NULL);");
    }

    // Mass execute SQL queries
    
    if ((!m_db.isOpen()) && (!m_db.open())) {  
        if (WarnDebugMessage)
            qWarning() << __FILE__ << QString::number(__LINE__) << "Unable to create database, "
                                                                   "database can not be open.";
        result = false;
    }
    qDebug() << __FILE__ << QString::number(__LINE__) <<  "Hash Size "+QString::number(name_sql.size());
    QHashIterator<QString, QString> it(name_sql);
     while (it.hasNext()) {
         it.next();
         QSqlQuery q(m_db);
         QString req = it.value();
         if (driver==Driver_SQLite) {
             req = req.remove("COLLATE utf8_unicode_ci", 
                             Qt::CaseInsensitive).remove("UNSIGNED", Qt::CaseInsensitive);

         }
         q.exec(req);
         // Is there an error with this req ?
         if (q.lastError().isValid()) {
             QMessageBox::warning(qApp->activeWindow(),
                                  tr("Fatal error"),
                                  tr("An error occured during  database creation.\n"
                                     "Reference : %1\n"
                                     "Error : %2\n\n"
                                     "Application will not work.")
                                  .arg(it.key()).arg(q.lastError().text())+QString::number(__LINE__),
                                  QMessageBox::Abort);
             if (WarnDebugMessage)
                 qWarning() << __FILE__ << QString::number(__LINE__) << "SQL Error" 
                            << it.key() << q.lastError().text();
             result = false;
         }
     }
     //-------table  et remplissage des bases d'initialisation ----------------------------------
   int numberOfTables = 1;

   QMessageBox mess;
               mess.setText(trUtf8("La base  a été installée "
                 "avec ")+QString::number(numberOfTables)
                 +trUtf8(" tables."));
               mess.setInformativeText(trUtf8("Do you want to install default values ?"));
               mess.setStandardButtons(QMessageBox::Ok | QMessageBox::Close);
               mess.setDefaultButton(QMessageBox::Close);
               int r = mess.exec();
               switch(r){
                   case QMessageBox::Ok :
                       if (!setFirstDefaultValues())
                       {
                       	  QMessageBox::warning(0,trUtf8("Warning"),
                       	  trUtf8("Unable to install default values"),QMessageBox::Ok);
                           }
                       break;
                   default :
                       break;    
                   }
               
                   
              
    return result;
}

bool Connexion::setFirstDefaultValues(){
    bool success = true;
    QSqlTableModel model(this,m_db);
    model.setTable(BASE);
    model.select();
    qDebug() << __FILE__ << QString::number(__LINE__) << " model BASE =" << BASE ;
    QStringList listOfItems;
    QFile file(qApp->applicationDirPath()+"/resources/default.txt");
    if (!file.open(QIODevice::ReadOnly))
    {
    	  qWarning() << __FILE__ << QString::number(__LINE__) << file.fileName()+"cannot open" ;
        }
    QTextStream s(&file);
    while (!s.atEnd())
    {
    	QString data = s.readLine();
    	listOfItems << data;
        }
    qDebug() << __FILE__ << QString::number(__LINE__) << " listOfItems =" << QString::number(listOfItems.size()) ;
    for (int row = 0; row < listOfItems.size(); row += 1)
    {
    	QString item = listOfItems[row];
    	qDebug() << __FILE__ << QString::number(__LINE__) << " item =" << item ;
    	if (!model.insertRows(row,1,QModelIndex()))
    	{
    		  qWarning() << __FILE__ << QString::number(__LINE__) << "cannot insert row" ;
    	    }
    	success = model.setData(model.index(row,0),row,Qt::EditRole);
        success = model.setData(model.index(row,1),item,Qt::EditRole);
        model.submit();
        }
       // model.submitAll();
       qDebug() << __FILE__ << QString::number(__LINE__) << " END "  ;
        if (success)
        {
               QMessageBox mess;
               mess.setText(trUtf8("Default categories have been installed"));
               mess.setStandardButtons(QMessageBox::Close);
               mess.setDefaultButton(QMessageBox::Close);
               int r = mess.exec();
            }  
        else
        {
        	QMessageBox::warning(0,trUtf8("Warning"),trUtf8("Unable to load default values"),QMessageBox::Ok);
            }  
    return success;
}

