#include "databaselms.h"

#include <QtSql>
#include <QSqlDatabase>
#include <QSqlDriver>
#include <QDomDocument>
#include <QProcess>

const QString DataBaseLMS::TypeUserDBInstructor = "instructor";
const QString DataBaseLMS::TypeUserDBTrainee = "trainee";

DataBaseLMS::DataBaseLMS(QWidget *ownerWidget, QObject *parent):
    QObject(parent),
    db(nullptr),
    UserNamePostgres(""),
    PasswordPostgres(""),
    ownerWidget(ownerWidget)
{

}

DataBaseLMS::~DataBaseLMS()
{
    deleteConnection();
}

void DataBaseLMS::slot_LanguageChanged(QString language)
{
    qtLanguageTranslator.load(QString(QStringLiteral("translations/DataBaseLMS_")) + language, QStringLiteral("."));
    QCoreApplication::installTranslator(&qtLanguageTranslator);
}

bool DataBaseLMS::createConnection()
{
    dbSettings = getDataBaseSettings();

    dbSettings.connectionName = "Connection_" + dbSettings.dbName;

    db = new QSqlDatabase(QSqlDatabase::addDatabase(dbSettings.dbType, dbSettings.connectionName));

    db->setDatabaseName(dbSettings.dbName);
    db->setUserName(dbSettings.dbUserName);
    db->setPassword(dbSettings.dbPassword);
    db->setHostName(dbSettings.dbHostName);
    db->setPort(dbSettings.dbPort);

    bool res = db->open();

    if(!res)
    {
        deleteConnection();
        return false;
    }
    else
    {
        bool flHas = db->driver()->hasFeature(QSqlDriver::Transactions);
        qDebug() << "db->driver()->hasFeature(QSqlDriver::Transactions): " << flHas;
        return true;
    }
}

void DataBaseLMS::deleteConnection()
{
    if(db != nullptr)
    {
        if(db->isOpen())
            db->close();

        delete  db;
        db = nullptr;
    }
}

bool DataBaseLMS::isConnected()
{
    if(db == nullptr)
    {
        return false;
    }
    else
    {
        if(db->isOpen())
        {
            return true;
        }
    }
    return false;
}

DataBaseSettings DataBaseLMS::getDataBaseSettings()
{
    DataBaseSettings settings;
    QFile file("config/settings.xml");
    if(!file.open(QIODevice::ReadOnly))
        return settings;

    QXmlStreamReader xmlReader(&file);

    while (!xmlReader.atEnd()){

        if(xmlReader.isStartElement()){

            if(xmlReader.name() == "DataBaseSettings")
            {

                foreach(const QXmlStreamAttribute &attr, xmlReader.attributes())
                {
                    QString name = attr.name().toString();
                    QString value = attr.value().toString();

                    if(name == "Type"){
                        settings.dbType = value;
                    }

                    if(name == "Name"){
                        settings.dbName = value;
                    }

                    if(name == "UserName"){
                        settings.dbUserName = value;
                    }

                    if(name == "Password"){
                        settings.dbPassword = value;
                    }

                    if(name == "HostName"){
                        settings.dbHostName = value;
                    }

                    if(name == "Port"){
                        settings.dbPort = value.toInt();
                    }

                }
            }
        }

        xmlReader.readNext();
    }

    file.close();
    return settings;
}

int DataBaseLMS::queryExecInt(QString queryStr)
{
    QSqlQuery query = QSqlQuery(*db);

    if(queryExec(queryStr, &query))
    {
        if(query.first())
            return query.value(0).toInt();
    }

    return 0;
}

QString DataBaseLMS::queryExecString(QString queryStr)
{
    QSqlQuery query = QSqlQuery(*db);

    if(queryExec(queryStr, &query))
    {
        if(query.first())
            return query.value(0).toString();
    }

    return QStringLiteral("");
}

bool DataBaseLMS::queryExecBool(QString queryStr)
{
    QSqlQuery query = QSqlQuery(*db);

    if(queryExec(queryStr, &query))
    {
        if(query.first())
            return query.value(0).toBool();
    }

    return false;
}

bool DataBaseLMS::queryExec(QString queryStr, QSqlQuery *query)
{
    bool res  = false;
    if(! (res = query->exec(queryStr)) )
            messageWarningErrorQuery(queryStr, query);
    return res;
}

void DataBaseLMS::messageWarningErrorQuery(QString queryStr, QSqlQuery* query)
{
    //Запись в файл ошибок БД
    QDomDocument commonDOM;

    QFile blankFile(":/resources/blankXML/ErrorDB.xml");

    if (! blankFile.open(QFile::ReadOnly | QFile::Text))
        qDebug() << QString("messageWarningErrorQuery: Couldn't read the file: ") + ":/resources/blankXML/ErrorDB.xml";
    else
    {
        commonDOM.setContent(blankFile.readAll());
        blankFile.close();

        QDomNode errorDBNode = commonDOM.namedItem("ErrorDB");

        QDomNode errorQueryNode = commonDOM.createElement("ErrorQuery");
        errorDBNode.appendChild(errorQueryNode);
        errorQueryNode.toElement().setAttribute("text", query->lastError().text());

        QDomNode stringOfQueryNode = commonDOM.createElement("StringOfQuery");
        errorDBNode.appendChild(stringOfQueryNode);
        stringOfQueryNode.toElement().setAttribute("text", queryStr);

        QDomNode executedQueryNode = commonDOM.createElement("ExecutedQuery");
        errorDBNode.appendChild(executedQueryNode);
        executedQueryNode.toElement().setAttribute("text", query->executedQuery());

        QFile xmlOutFile("ErrorDB.xml");
        if (!xmlOutFile.open(QFile::WriteOnly | QFile::Text))
            qDebug() << QString("messageWarningErrorQuery: Failed to write a file: ") + "ErrorDB.xml";
        else
        {
            QTextStream outFile(&xmlOutFile);
            commonDOM.save(outFile, 4);
            xmlOutFile.close();
        }
    }

    //Сообщение об ошибке
    QString textError = "";
    textError = "Error query:\n" + query->lastError().text() + "\n" +
                "String of query:\n" + queryStr + "\n" +
                "Executed query:\n" + query->executedQuery();
    emit signal_ErrorPostgreSQL(textError);
}
