#include "dbManager.h"
#include "logger.h"

DatabaseManager::DatabaseManager(QObject* parent)
    : QObject(parent)
{

}

DatabaseManager::~DatabaseManager()
{
    /*for(auto i = m_connections.constBegin(); i != m_connections.constEnd(); i++)
    {
        QSqlDatabase db = i.value();
        db.close();
        QSqlDatabase::removeDatabase(i.key());
    }*/

    //见disconnect注释
    QList<QString> keys = m_connections.keys();
    for(int i = 0; i < keys.count(); i++)
    {
        QSqlDatabase db = m_connections.take(keys.at(i));
        db.close();
    }
}

bool DatabaseManager::addDatabase(const DatabaseConfig& config)
{
    if(m_configs.contains(config.strConnectionName))
    {
        QSqlError error(QString::fromWCharArray(L"配置信息错误"),
                        //QString("Connection name '%1' already exists").arg(config.strConnectionName),
                        QString::fromWCharArray(L"已存在同名的链接: '%1'").arg(config.strConnectionName),
                        QSqlError::ConnectionError);
        emit errorOccurred(config.strConnectionName, error);
        return false;
    }

    for(auto i = m_configs.constBegin(); i != m_configs.constEnd(); i++)
    {
        DatabaseConfig c = i.value();
        if(config.strHost == c.strHost && config.nPort == c.nPort)
        {
            QSqlError error(QString::fromWCharArray(L"配置信息错误"),
                            QString::fromWCharArray(L"'%1' 具有相同配置信息").arg(c.strConnectionName),
                            QSqlError::ConnectionError);
            emit errorOccurred(config.strConnectionName, error);
            return false;
        }
    }

    m_configs[config.strConnectionName] = config;
    return true;
}

bool DatabaseManager::connect(const QString& strConnectionName)
{
    LOG_INFO("DB", QString("Connect to %1").arg(strConnectionName));
    if(!m_configs.contains(strConnectionName))
    {
        QSqlError error(QString::fromWCharArray(L"配置信息错误"),
                        QString::fromWCharArray(L"没有找到该链接的配置信息"),
                        QSqlError::ConnectionError);
        emit errorOccurred(strConnectionName, error);
        LOG_ERROR("DB", QString("Connection failed: %1 due 2%").arg(strConnectionName).arg("no configuration information"));
        return false;
    }

    const DatabaseConfig& config = m_configs[strConnectionName];
    QSqlDatabase db = QSqlDatabase::addDatabase(config.strDBType, strConnectionName);
    db.setHostName(config.strHost);
    db.setPort(config.nPort);
    db.setDatabaseName(config.strDBName);
    db.setUserName(config.strUserName);
    db.setPassword(config.strPassword);

    if(!db.open())
    {
        LOG_ERROR("DB", QString("DB: %1 open failed. connectionName: %2. error: %2")
                            .arg(config.strDBName)
                            .arg(strConnectionName)
                            .arg(db.lastError().databaseText()));
        emit errorOccurred(strConnectionName, db.lastError());
        QSqlDatabase::removeDatabase(strConnectionName);
        return false;
    }

    m_connections[strConnectionName] = db;
    emit connectionStatusChanged(strConnectionName, true);
    return true;
}
void DatabaseManager::disconnect(const QString& strConnectionName)
{
    if(m_connections.contains(strConnectionName))
    {
        LOG_INFO("DB", QString("Disconnect to %1").arg(strConnectionName));
        //按照官方文档，如果数据库移除了对象，db就是一个"悬空的无效数据库链接"(is now a dangling invalid database connection),因为被remove了，但是并没有被delete
        //加上括号变成局部变量，超出括号后就被自动删除(delete)了，不会再出现"connection '***' is still in use, all queries will cease to work"的警告
        {
            QSqlDatabase db = m_connections.take(strConnectionName);
        }
        QSqlDatabase::removeDatabase(strConnectionName);
        emit connectionStatusChanged(strConnectionName, false);
    }
}

QStringList DatabaseManager::conncetions()
{
    return m_connections.keys();
}
