#include "sysconfigmgt.h"
#include <QGraphicsDropShadowEffect>
#include <QToolBar>
#include <QVBoxLayout>
#include <tbaseutil/tdataparse.h>
#include <tbaseutil/tdataresponse.h>
#include <tbaseutil/tenumlist.h>
#include <tbaseutil/ttheme.h>
#include <tdatabaseutil/tsqlconnectionpoolv2.h>
#include <tdatabaseutil/tsqlqueryv2.h>
#include <tdatabaseutil/tsqlselectorv2.h>
#include <topcore/topclasssqlthread.h>
#include <topcore/topcore.h>
#include <topcore/topenummanager.h>
#include <toputil/t.h>
#include <twidget/tmessagebar.h>
#include <twidget/tpagetool.h>
#include <twidget/tsearchentry.h>
#include <twidget/tsplitter.h>
#include <twidget/ttableview.h>

SysConfigMgt::SysConfigMgt(const QString &iModuleNameStr, const QVariantMap iUrlPars, QWidget *iParent)
    : TopClassAbs(iParent)
{
    this->appendLanguage("sys-config");
    this->setLicenseKey("sys_common");
    this->initModule(iModuleNameStr, iUrlPars);

    mBodySplitter = new TSplitter(this);
    this->setCentralWidget(mBodySplitter);

    mBodyWidget = new QWidget(this);

    QVBoxLayout *vboxlayout = new QVBoxLayout(mBodyWidget);
    vboxlayout->setMargin(0);
    vboxlayout->setSpacing(0);

    //初始化TableView
    initTableView();

    //工具栏
    if (QToolBar *toolbar = qobject_cast<QToolBar*>(uim()->getWidget("MAIN_TOOLBAR"))) {
        toolbar->setWindowTitle(ttr("ToolBar"));
        vboxlayout->addWidget(toolbar, 0);
        //搜索栏
        mSearchEntry = qobject_cast<TSearchEntry *>(uim()->getWidget("MAIN_TOOLBAR/SEARCH_ENTRY"));
    }
    //表格右键菜单
    if (QMenu *table_popup = qobject_cast<QMenu *>(uim()->getWidget("TABLEVIEW_POPUP"))) {
        mTableView->setContextMenu(table_popup);
    }

    vboxlayout->addWidget(mTableView, 1);

    //翻页工具
    mPageTool = new TPageTool(this);
    vboxlayout->addWidget(mPageTool);

    mBodySplitter->addWidget(mBodyWidget);

    QString detailModuleName = config("detailModuleName").toString();
    if (detailModuleName.isEmpty()) {
        detailModuleName = "sys-config";
    }
    mDetailView = new SysConfig(detailModuleName, QVariantMap(), this);
    mDetailView->setConfig("productCategory", this->config("productCategory"));
    connect(mDetailView, SIGNAL(dataSaved(QVariant)), this, SLOT(onDetailSaved(QVariant)));
    connect(mDetailView, SIGNAL(windowModifyChanged(bool)), SLOT(onDetailChanged()));

    mBodySplitter->addWidget(mDetailView);

    if (mSearchEntry != nullptr) {
        mSearchEntry->setOptionList(TDataParse::headerItem2searchList(mTableView->headerItem()));
        mSearchEntry->setPlaceholderText(ttr("Search %1"));
        connect(mSearchEntry, SIGNAL(search(QString,QVariant)), this, SLOT(refresh()));
        this->setFocusProxy(mSearchEntry);
    }
    if (mPageTool != nullptr) {
        mPageTool->setPageSizeVisible(true);
        connect(mPageTool, SIGNAL(pageChanged(int,int)), this, SLOT(onPageChanged()));
    }
    connect(mTableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
            this, SLOT(onSelectionChanged()));

    if (QAction *openAct = this->getAction("open")) {
        connect(mTableView, SIGNAL(activated(QModelIndex)), openAct, SLOT(trigger()));
    }

    mDetailView->resize(TTHEME_DP(config("detail.perfect_size.width", mDetailView->perfectSize().width()).toInt()), mDetailView->height());
    mBodySplitter->setStretchFactor(0, 1);

    this->restoreSizeState();
    this->restoreObjectState(mTableView);

    refreshActionState();
    QTimer::singleShot(0, this, SLOT(refresh()));
}

SysConfigMgt::~SysConfigMgt()
{
    this->saveSizeState();
    this->saveObjectState(mTableView);
}

void SysConfigMgt::refresh(bool iResetPageBol)
{
    t::loading(this);
    TSqlSelectorV2 selector = getSqlSelector(iResetPageBol);
    QVariant data = doThreadWork(new TopClassSqlThread(this), TOPSQLTHREAD_SELECT_ARRAYMAP, QVariant::fromValue(selector));
    unloading();
    TDataResponse dataRes(data.toMap());
    if (dataRes.hasError()) {
        alertError(ttr("Load data failed!"), dataRes.errText());
    } else {
        fillTableData(dataRes);
        alertOk(ttr("Load data success!"));
    }
}

void SysConfigMgt::deleteItem(const QVariantList &iIdLst)
{
    loading(ttr("Deleting data..."));
    TSqlDeleterV2 deleter;
    deleter.setTable("pub_conf");
    deleter.addWhere("id",iIdLst);

    QVariant data = doThreadWork(new TopClassSqlThread(this), TOPSQLTHREAD_DELETE_ROW, QVariant::fromValue(deleter));
    unloading();
    TDataResponse dataRes(data.toMap());
    if (dataRes.hasError()) {
        alertError(ttr("Delete data failed!"), dataRes.errText());
    } else {
        refresh(true);
        alertOk(ttr("Delete data success!"));
    }
}

QVariantList SysConfigMgt::selectedItems()
{
    return mSelectedLst;
}

TopClassAbs *SysConfigMgt::openItem(int iUserId)
{
    QString detailModuleName = "sys-config";
    if (!config("detailModuleName").toString().isEmpty()) {
        detailModuleName = config("detailModuleName").toString();
    }
    SysConfig *detail = qobject_cast<SysConfig *>(APP->openModule(detailModuleName));
    if (detail != nullptr) {
        detail->setConfig("productCategory", this->config("productCategory"));
        connect(detail, SIGNAL(dataSaved(QVariant)), this, SLOT(onDetailSaved(QVariant)));
        connect(this, SIGNAL(destroyed()), detail, SLOT(close()));
        detail->setUid(iUserId);
    }
    return detail;
}

void SysConfigMgt::newItem()
{
    mBodySplitter->cacheSizes();
    mDetailView->create();
    mDetailView->refreshActionState();
}

void SysConfigMgt::onPageChanged()
{
    refresh(false);
}

void SysConfigMgt::onSelectionChanged()
{
    if (mTableView != nullptr) {
        //因为Action的State函数中用到getSelectedList, 所以TableView选择更改时,
        //将其保存至mSelectedList中, 这样可以加快Action状态的刷新速度;
        mSelectedLst = mTableView->selectedPrimaryKeys();

        int curIdInt = 0;
        if (!mSelectedLst.isEmpty()) {
            curIdInt = mSelectedLst.value(0).toInt();
        }

        if (mDetailView->uid().toInt() != curIdInt) {
            //设置详情模块的上次Uid为当前选择的ID, 这样当如果详情模块处于编辑状态时点取消后显示的当前择的条目内容;
            mDetailView->setLastUid(curIdInt);
            if (!mDetailView->isDataModified()) {
                mDetailView->setUid(curIdInt);
            }
        }

        refreshActionState();
    }
}

void SysConfigMgt::onDetailSaved(const QVariant &iUidStr)
{
    this->refresh(false);
    mTableView->selectRow(iUidStr);
}

void SysConfigMgt::onDetailChanged()
{
    bool isModified = mDetailView->isDataModified();
    mTableView->setEnabled(!isModified);
    if (isModified) {
        this->showMaskFrame(mBodyWidget);
    } else {
        if (mBodySplitter->sizes().value(0) < 20) {
            mBodySplitter->setWidgetSize(0, mBodySplitter->getCacheSize(0), true);
        }
        this->hideMaskFrame();
    }
    refreshActionState();
}

TSqlSelectorV2 SysConfigMgt::getSqlSelector(bool iResetPageBol)
{
    TSqlSelectorV2 selector;
    selector.setTable("pub_conf");
    selector.setReturnRowCount(true);
    selector.addField("*");
    QVariantMap formatMap;
    formatMap["tags"] = "array";
    selector.setFieldFormat(formatMap);
    int pageNumInt = 1;
    int pageSizeInt = -1;
    if (mPageTool != nullptr) {
        if (iResetPageBol) {
            mPageTool->setCurrentPage(1, true);
        }

        pageNumInt = mPageTool->currentPage();
        pageSizeInt = mPageTool->pageSize();
    }

    if (mSearchEntry != nullptr) {
        selector.setWhere(mSearchEntry->sqlWhere());
    }

    selector.setOrder("id", Qt::DescendingOrder);
    QHeaderView *headerView = mTableView->horizontalHeader();
    if (headerView != nullptr) {
        QString orderField = mTableView->columnName(headerView->sortIndicatorSection());
        if (!orderField.isEmpty() && orderField != "remark") {
            selector.setOrder(orderField, headerView->sortIndicatorOrder());
        }
    }

    if (pageNumInt < 1) {
        pageNumInt = 1;
    }

    if (pageSizeInt < 1) {
        pageSizeInt = 100;
    }

    selector.setPage(pageNumInt, pageSizeInt);
    return selector;
}

void SysConfigMgt::initTableView()
{
    mTableView = new TTableView(this);
    mTableView->setObjectName("TableView");
    mTableView->setStyleSheet("QTableView{border-width:0px}");
    mTableView->setShowGrid(false);
    mTableView->setSelectionMode(QAbstractItemView::ExtendedSelection);
    mTableView->verticalHeader()->setVisible(false);
    mTableView->horizontalHeader()->setSortIndicatorShown(true);
    mTableView->horizontalHeader()->setSectionsMovable(true);
    mTableView->horizontalHeader()->setStretchLastSection(true);
    mTableView->setHeaderPopupEnabled(true);
    mTableView->horizontalHeader()->setMinimumSectionSize(75);

    connect(mTableView->horizontalHeader(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
            this, SLOT(refresh()));

    QStringList dataKeyList;
    dataKeyList << "id" << "path" << "text_data" << "remark"
                << "tags" << "extra_data" << "name" << "status" << "status.text"
                << "json_data" << "meta_data" << "attr_data" << "seq";
    mTableView->setDataKeyList(dataKeyList);
    mTableView->setPrimaryKey("id");
    mTableView->setHeaderItem(getFixedTableHeadItemList());
}

void SysConfigMgt::fillTableData(const TDataResponse &iDataRes)
{
    QVariantList dataLst = iDataRes.data().toList();
    if (mPageTool != nullptr) {
        mPageTool->setRowCount(iDataRes.dataCount(), true);
    }
    for (QVariant value : dataLst) {
        QVariantMap tmpMap = value.toMap();
        QStringList tags = tmpMap["tags"].toStringList();
        if (!tags.isEmpty()) {
            QString tagsStr = tags.join(",");
            tmpMap["tags"] = tagsStr;
        }

        dataLst.replace(dataLst.indexOf(value), tmpMap);
    }

    QVariantList resLst;
    TEnumList *enumUserStatus = TOPENM->enumList("sys-config-status");
    for (QVariant row : dataLst) {
        QVariantMap rowMap = row.toMap();
        QString statusStr = rowMap.value("status").toString();
        rowMap.insert("status.icon", enumUserStatus->itemIcon(statusStr));
        rowMap.insert("status.text", enumUserStatus->itemText(statusStr));
        resLst.append(rowMap);
    }
    mTableView->loadData(resLst);
}

QVariantList SysConfigMgt::getFixedTableHeadItemList()
{
    QVariantList headerItems;
    headerItems << QVariant();
    headerItems << tableHeaderItem("path",ttr("Config Path"),"path", 200,"string");
    headerItems << tableHeaderItem("remark",ttr("Remark"),"remark", 200,"string");
    headerItems << tableHeaderItem("tags",ttr("Tag"),"tags", 100);
    headerItems << tableHeaderItem("name",ttr("Name"),"name", 100, "string");
    headerItems << tableHeaderItem("status",ttr("Status"),"status.text", 100);
    headerItems << tableHeaderItem("seq",ttr("Sequnce"),"seq",100);
    return headerItems;
}

QVariantMap SysConfigMgt::tableHeaderItem(const QString &iKeyStr, const QString &iDispStr, const QString &iDisplayRolr, int iSizeInt, const QString &iTypeStr)
{
    QVariantList list;
    list << "name" << iKeyStr << "display" << iDispStr
         << "displayRole" << QString("$%1").arg(iDisplayRolr)
         << "resizeMode" << "Interactive" << "size" << iSizeInt ;
    if (!iTypeStr.isEmpty()) {
        list << "search" << iTypeStr;
    }
    return TDataParse::variantList2Map(list);
}