#include "dbStructureModel.h"
#include "sqlQueryExecutor.h"
#include "logger.h"
// #include <QSqlDatabase>
// #include <QSqlQuery>

DBStructureModel::DBStructureModel(QObject* parent)
    : QAbstractItemModel(parent), m_rootNode(new DBStructureNode(RootNode, "Root"))
{

}

DBStructureModel::~DBStructureModel()
{
    delete m_rootNode;
}

DBStructureNode* DBStructureModel::getNode(const QModelIndex& index) const
{
    if(index.isValid())
        return static_cast<DBStructureNode*>(index.internalPointer());
    else
        return m_rootNode;
}

DBStructureNode* DBStructureModel::getConnectionNode(const QString& name) const
{
    for(int i = 0; i < m_rootNode->childCount(); ++i)
    {
        DBStructureNode* node = m_rootNode->child(i);
        if(node->type() == ConnectionNode && node->name() == name)
            return node;
    }
    return nullptr;
}

QModelIndex DBStructureModel::index(int row, int column, const QModelIndex& parent) const
{
    if(!hasIndex(row, column, parent))
        return QModelIndex();

    DBStructureNode* parentNode = getNode(parent);
    DBStructureNode* childNode = parentNode->child(row);
    if(childNode)
        return createIndex(row, column, childNode);
    else
        return QModelIndex();
}

QModelIndex DBStructureModel::parent(const QModelIndex& index) const
{
    if(!index.isValid())
        return QModelIndex();

    DBStructureNode* childNode = static_cast<DBStructureNode*>(index.internalPointer());
    DBStructureNode* parentNode = childNode->parentNode();
    if(parentNode == m_rootNode)
        return QModelIndex();

    return createIndex(parentNode->row(), 0 ,parentNode);
}

int DBStructureModel::rowCount(const QModelIndex& parent) const
{
    DBStructureNode* parentNode = getNode(parent);
    return parentNode->childCount();
}

int DBStructureModel::columnCount(const QModelIndex& parent) const
{
    return DBStructureNode::ColumnCount;
}

QVariant DBStructureModel::data(const QModelIndex& index, int role) const
{
    if(!index.isValid())
        return QVariant();

    DBStructureNode* node = static_cast<DBStructureNode*>(index.internalPointer());

    switch (role)
    {
    case Qt::DisplayRole:
        return node->columnData(DBStructureNode::ColumnName);
    case Qt::DecorationRole:
        return node->icon();
    default:
        return node->data(role);
    }
}

QVariant DBStructureModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if(orientation == Qt::Horizontal && role == Qt::DisplayRole)
    {
        switch(section)
        {
        case DBStructureNode::ColumnName:
            return "Name";
        default:
            return QVariant();
        }
    }

    return QVariant();
}

void DBStructureModel::addConnection(const QString& name, const QString& dbType)
{
    beginInsertRows(QModelIndex(), m_rootNode->childCount(), m_rootNode->childCount()); //链接节点是根节点的(m_rootNode)的子节点，根节点的索引是QModelIndex()

    DBStructureNode* connectionNode = new DBStructureNode(ConnectionNode, name, m_rootNode);
    m_rootNode->appendChild(connectionNode);

    endInsertRows(); //该语句之后会触发rowsInserted(const QModelIndex &parent, int first, int last)信号，通知视图刷新对应行
}

QModelIndex DBStructureModel::getConnNodeIndex(const QString& name)
{
    DBStructureNode* connNode = getConnectionNode(name);
    if(!connNode)
        return QModelIndex();
    else
        return index(connNode->row(), 0, QModelIndex());
}

void DBStructureModel::addDataModel(const QString& connection, Model& model)
{
    QModelIndex connIndex = getConnNodeIndex(connection);
    if(!connIndex.isValid())
    {
        LOG_ERROR("DBStructureModel", QString::fromWCharArray(L"获取ModelIndex失败，节点名称:%1").arg(connection));
        return;
    }

    DBStructureNode* connNode = getConnectionNode(connection);
    if(!connNode)
    {
        LOG_ERROR("DBStructureModel", QString::fromWCharArray(L"获取Node对象失败，节点名称:%1").arg(connection));
        return;
    }

    beginInsertRows(connIndex, connNode->childCount(), connNode->childCount());

    DBStructureNode* modelNode = new DBStructureNode(TableNode, model.name, connNode);
    modelNode->setData(Qt::UserRole + NodeDataRole::ID, model.id);
    for(int groupID : model.groups)
    {
        QString groupName = SqlQueryExecutor::instance().getArributeGropuName(connection, groupID);
        DBStructureNode* groupNode = new DBStructureNode(GroupNode, groupName, modelNode);
        groupNode->setData(Qt::UserRole + NodeDataRole::ID, groupID);
        modelNode->appendChild(groupNode);
    }
    connNode->appendChild(modelNode);

    endInsertRows();
}

void DBStructureModel::refreshStructure_Connection(const QString& connection)
{
    DBStructureNode* connNode = getConnectionNode(connection);
    if(!connNode)
        return;

    //先删除当前链接节点下的节点
    if(connNode->childCount() > 0)
    {
        beginRemoveRows(index(connNode->row(), 0, QModelIndex()), 0, connNode->childCount() - 1);
        connNode->removeAllChildren();
        endRemoveRows(); //该语句之后会触发rowsRemoved(const QModelIndex &parent, int first, int last)信号，通知视图刷新对应行
    }

    QSqlDatabase db = QSqlDatabase::database(connection);
    if(!db.isOpen())
    {
        if(connNode->status() == Connect)
        {
            connNode->setStatus(Disconnect);
            QModelIndex topLeft = index(connNode->row(), 0, QModelIndex());
            QModelIndex bottomRight = index(connNode->row(), 0, QModelIndex());
            emit dataChanged(topLeft, bottomRight, {Qt::DecorationRole});
        }
        return;
    }

    //重新加载数据节点
    /*QString strSql = "SELECT * FROM basic.attribute_group ORDER BY id ASC";
    QSqlQuery query(db);
    if(!query.exec(strSql))
        return;

    QVector<DBStructureNode*> tables;
    while(query.next())
    {
        QString tableName = query.value(2).toString();
        tables << new DBStructureNode(TableNode, tableName, connNode);
    }*/

    const QVector<Model> models = SqlQueryExecutor::instance().getModels(connection);
    beginInsertRows(index(connNode->row(), 0, QModelIndex()), 0, models.count() - 1);

    for(const Model& model : models)
    {
        DBStructureNode* modelNode = new DBStructureNode(TableNode, model.name, connNode);
        for(int groupID : model.groups)
        {
            QString groupName = SqlQueryExecutor::instance().getArributeGropuName(connection, groupID);
            DBStructureNode* groupNode = new DBStructureNode(GroupNode, groupName, modelNode);
            modelNode->appendChild(groupNode);
        }
        connNode->appendChild(modelNode);
    }

    endInsertRows();

    if(connNode->status() == Disconnect)
    {
        connNode->setStatus(Connect);
        QModelIndex topLeft = index(connNode->row(), 0, QModelIndex());
        QModelIndex bottomRight = index(connNode->row(), 0, QModelIndex());
        emit dataChanged(topLeft, bottomRight, {Qt::DecorationRole});
    }

}
