#include "sysenumlist.h"
#include <QDockWidget>
#include <QResizeEvent>
#include <QToolBar>
#include <QRegularExpression>
#include <tbaseutil/tdataresponse.h>
#include <tbaseutil/tdataparse.h>
#include <tbaseutil/ttheme.h>
#include <tdatabaseutil/tsqlselectorv2.h>
#include <topcore/topcore.h>
#include <topcore/topclasssqlthread.h>
#include <toputil/t.h>
#include <twidget/tmessagebar.h>
#include <twidget/tmessagebox.h>
#include <twidget/ttablechooserdialog.h>
#include <twidget/ttableview.h>
#include <twidget/ttableviewdialog.h>
#include <twidget/tuiloader.h>
#include <twidget/twidget.h>
#include <twidget/tsplitter.h>
#include <twidget/ttitleexpander.h>
#include "sysenumlistthread.h"

SysEnumList::SysEnumList(const QString &iModuleNameStr, const QVariantMap &iUrlPars, QWidget *iParent)
    : TopClassAbs(iParent), mLastSelectIndex(QModelIndex())
{
    this->setLicenseKey("");
    this->initModule(iModuleNameStr, iUrlPars);

    QWidget *centerWgt = new QWidget(this);
    this->setCentralWidget(centerWgt);
    QVBoxLayout *centerLayout = new QVBoxLayout(centerWgt);
    centerLayout->setMargin(0);
    centerLayout->setSpacing(0);

    if (QToolBar *toolbar = qobject_cast<QToolBar *>(uim()->getWidget("MAIN_TOOLBAR"))) {
        centerLayout->addWidget(toolbar, 0);
    }

    mBodyLayout = new QHBoxLayout();
    centerLayout->addLayout(mBodyLayout, 1);
    mBodyLayout->setMargin(TTHEME_DP(16));
    mBodyLayout->setSpacing(0);

    mClassUiLoader = new TUiLoader(this);
    mClassUiLoader->setScriptEngine(APP->scriptEngine());
    mClassUiLoader->setSelf(this);
    mClassUiLoader->setMaximumWidth(TTHEME_DP(config("maximum_size.width", 800).toInt()));

    mClassUiLoader->setProperty("SS_BG", "PANEL");
    mClassUiLoader->setProperty("SS_BORDER", 1);

    mBodyLayout->addStretch(1);
    mBodyLayout->addWidget(mClassUiLoader, 99999);
    mBodyLayout->addStretch(1);

    mClassUiLoader->setUiStr(ui("enum-info").toString());

    initTableView();
    initListUiLoader();

    TWidget *detail = qobject_cast<TWidget *>(mClassUiLoader->getObject("classinfo_page2"));
    QVBoxLayout *vboxlayout = new QVBoxLayout(detail);
    vboxlayout->setMargin(0);
    vboxlayout->setSpacing(0);

    if (QToolBar *toolbar = qobject_cast<QToolBar*>(uim()->getWidget("ENUMLIST_TOOLBAR"))) {
        toolbar->setWindowTitle(ttr("ToolBar"));
        vboxlayout->insertWidget(0, toolbar);
    }

    TTitleExpander *expander = new TTitleExpander(detail);
    expander->setExpanded(true);
    expander->setText(ttr("Detail Information"));
    expander->setBodyWidget(mListUiLoader);

    TSplitter *splitter = new TSplitter(detail);
    splitter->addWidget(mTableView);
    splitter->addWidget(expander);
    vboxlayout->addWidget(splitter);

    if (QMenu* tablePopup = qobject_cast<QMenu *>(uim()->getWidget("MAINMENU_POPUP"))) {
        mTableView->setContextMenu(tablePopup);
    }

    mSearchEntry = qobject_cast<TSearchEntry *>(uim()->getWidget("MAIN_TOOLBAR/SEARCH_ENTRY"));
    if (mSearchEntry != nullptr) {
        mSearchEntry->setOptionList(TDataParse::headerItem2searchList(mTableView->headerItem()));
        mSearchEntry->setPlaceholderText(ttr("Search %1"));
        this->setFocusProxy(mSearchEntry);
    }

    connect(mClassUiLoader, SIGNAL(dataChanged()), this, SLOT(setDataModified()));
    connect(mTableView, SIGNAL(dataChanged()), this, SLOT(setDataModified()));
    connect(mTableView, SIGNAL(rowsMoved()), this, SLOT(setDataModified()));
    connect(mTableView, SIGNAL(rowsRemoved()), this, SLOT(setDataModified()));

    connect(mTableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
            this, SLOT(onSelectionChanged()));
    restoreSizeState();
    uidChangeEvent(this->uid());
    refreshActionState();
}

SysEnumList::~SysEnumList()
{
    saveSizeState();
}

void SysEnumList::reload()
{
    QString uidStr = (lastUid().isEmpty()) ? uid() : lastUid();
    setUid(uidStr, true);
}

void SysEnumList::copy()
{
    setLastUid(this->uid());
    setUid(0, false);
    QVariantMap data;
    data.insert("name", "");
    setData(data);
    setTitle(ttr("New EnumLisr"));
    setDataModified(true);
}

void SysEnumList::create()
{
    setLastUid(this->uid());
    setUid("", true);
    setDataModified(true);
}

void SysEnumList::clearData()
{
    mClassUiLoader->loadValues(QVariantMap(), true);
    if (mTableView != nullptr) {
        mTableView->loadData(QVariantList());
    }
    if (mListUiLoader != nullptr) {
        mListUiLoader->loadValues(QVariantMap(), true);
    }
}

void SysEnumList::setData(const QVariantMap &iDataMap)
{
    mClassUiLoader->loadValues(iDataMap, false);
    if (mTableView != nullptr) {
        QVariantList items = iDataMap.value("items").toList();
        const QString lang = APP->language();
        QString text;
        for (auto & i : items) {
            QVariantMap iMap = i.toMap();
            text = iMap.value("text_"+lang).toString();
            if (text.isEmpty()) {
                text = iMap.value("text").toString();
            }
            iMap.insert("disp.text", text);
            i = iMap;
        }

        qSort(items.begin(), items.end(), [](QVariant a, QVariant b){
           return a.toMap().value("num").toInt() < b.toMap().value("num").toInt();
        });
        mTableView->loadData(items);
    }
    if (iDataMap.contains("name")) {
        setTitle(ttr("Enum-%1").arg(iDataMap.value("name").toString()));
    }
}

QVariantMap SysEnumList::getData() const
{
    QVariantMap dataMap;
    QVariantMap confMap = mClassUiLoader->getAllValues().toVariant().toMap();
    QVariantList items;
    if (mTableView != nullptr) {
        items = mTableView->allDataMap();
        int num = 0;
        for (QVariant & i : items) {
            QVariantMap iMap = i.toMap();
            iMap.remove("disp");
            iMap.remove("disp.text");
            iMap.insert("num", num++);
            i = iMap;
        }
    }

    confMap.insert("items", items);
    // 去掉首尾的空格是为了使HOCON配置层级合并正常
    dataMap.insert("conf_admin", TDataParse::variant2JsonStr(confMap, true).replace(QRegularExpression("^{|}$"), ""));
    dataMap.insert("enum_name", this->uid());
    return dataMap;
}

void SysEnumList::saveData()
{
    QVariantList errLst = mClassUiLoader->validateAll("COMMIT", true, "ERROR");
    if (!errLst.isEmpty()) {
        QStringList errStrLst;
        for (QVariant err : errLst) {
            errStrLst.append(err.toMap().value("text").toString());
        }
        TMessageBox::error(this, ttr("Saving data failed!"), errStrLst.join("\n"));
        return;
    }

    if (mTableView->allDataMap().isEmpty()) {
        TMessageBox::error(this, ttr("Saving data failed!"), ttr("EnumList can not be empty!"));
        return;
    }

    for (QVariant item : mTableView->allDataMap()) {
        QVariantMap itemMap = item.toMap();
        if (itemMap.value("name").toString().isEmpty()) {
            TMessageBox::error(this, ttr("Saving data failed!"), ttr("EnumList name can not be empty!"));
            return;
        }
    }

    QStringList nameLst = repeatNameList();
    if (!nameLst.isEmpty()) {
        TMessageBox::error(this, ttr("Error"), ttr("EnumList name [%1] repeats!").arg(nameLst.join(",")));
        return;
    }

    QVariantMap dataMap = TDataParse::replaceVariantMapEmptyItem(getData());
    dataMap.insert("md5", TDataParse::getVariantMd5(TDataParse::variant2JsonStr(dataMap)));
    dataMap.insert("product_category", APP->productCategory());

    t::saving(this);
    QVariant data = doThreadWork(new SysEnumListThread(this), "SAVE_DATA", dataMap);
    unloading();
    TDataResponse dataRes(data.toMap());
    if (dataRes.hasError()) {
        alertError(ttr("Save data failed!"), dataRes.errText());
    } else {
        setUid(dataRes.data().toString());
        emit dataSaved(this->uid());
        mLastSelectIndex = QModelIndex();
    }
}

void SysEnumList::addItem()
{
    QModelIndex modelIndex = mTableView->appendRow(QVariantMap());
    mTableView->selectionModel()->clear(); //触发onSelectionChanged事件
    mTableView->selectRow(modelIndex);
}

void SysEnumList::removeItems()
{
    if (mTableView->selectedRowDataMaps().length() == 0){
        return;
    }
//    if (TMessageBox::question(this, ttr("Are you sure to remove selected items?"), "", ttr("Remove"),
//                              QStringList() << ttr("Remove") + ":Yes" << ttr("Cancel") + ":Cancel") != "Yes"){
//        return;
//    }
    mTableView->removeSelectedRows();
}

void SysEnumList::moveSelectItems(const QString &iDirection)
{
    if (iDirection.toUpper() == "UP") {
         mTableView->moveSelectedRowsUp();
    } else if(iDirection.toUpper() == "DOWN") {
        mTableView->moveSelectedRowsDown();
    } else if(iDirection.toUpper() == "TOP") {
        mTableView->moveSelectedRowsTop();
    } else if(iDirection.toUpper() == "BOTTOM") {
        mTableView->moveSelectedRowsBottom();
    }
}

void SysEnumList::setCanCreate(bool iCanBol)
{
    mCanCreate = iCanBol;
}

bool SysEnumList::canCreate()
{
    return mCanCreate;
}

void SysEnumList::onSelectionChanged()
{
    QModelIndexList indexLst = mTableView->selectedIndexes();
    mListUiLoader->blockSignals(true);
    if (indexLst.isEmpty()) {
        mListUiLoader->clearValues();
        mLastSelectIndex = QModelIndex();
    } else {
        TTableModel *model = qobject_cast<TTableModel *>(mTableView->model());
        if (model != nullptr) {
             mListUiLoader->loadValues(model->rowDataMap(indexLst.first()));
             mLastSelectIndex = indexLst.first();
        }
    }
    mListUiLoader->blockSignals(false);
}

void SysEnumList::uidChangeEvent(const QString &iUidStr)
{
    if (iUidStr.isEmpty()) {
        setTitle(ttr("New EnumList"));
        clearData();
    } else {
        t::loading(this);
        QVariant data = doThreadWork(new SysEnumListThread(this), "LOAD_DATA", QVariant(this->uid()));
        unloading();
        TDataResponse dataRes(data.toMap());
        if (dataRes.hasError()) {
            alertError(ttr("Load data failed!"), dataRes.errText());
        } else {
            QVariantMap dataMap = dataRes.data().toMap();
            dataMap.insert("name", iUidStr);
            clearData();
            setData(dataMap);
        }
    }
    setDataModified(false);
}

void SysEnumList::resizeEvent(QResizeEvent *iEvent)
{
    QSize size = iEvent->size();
    if (size.width() > this->perfectSize().width()) {
        mBodyLayout->setMargin(TTHEME_DP(16));
        mClassUiLoader->setProperty("SS_BORDER", 1);
        mClassUiLoader->setStyleSheet(".Q{}");
    } else {
        mBodyLayout->setMargin(0);
        mClassUiLoader->setProperty("SS_BORDER", 0);
        mClassUiLoader->setStyleSheet(".Q{}");
    }
}

void SysEnumList::initListUiLoader()
{
    mListUiLoader = new TUiLoader();
    mListUiLoader->setScriptEngine(APP->scriptEngine());
    mListUiLoader->setSelf(this);
    mListUiLoader->setUiStr(ui("enum-list").toString());
    mListUiLoader->setMouseTracking(true);
    connect(mListUiLoader, SIGNAL(dataChanged()), this, SLOT(tuiDataFillTableView()));
}

void SysEnumList::initTableView()
{
    mTableView = new TTableView(this);

    QStringList dbbFieldStrLst;
    dbbFieldStrLst << "name" << "text" << "icon" << "remark" << "data";
    for (QString langStr : APP->languageDefine().keys()) {
        dbbFieldStrLst << ("text_" + langStr);
    }

    QStringList tableDataKeyStrLst;
    tableDataKeyStrLst << dbbFieldStrLst;
    tableDataKeyStrLst << "disp" << "disp.text";
    mTableView->setDataKeyList(tableDataKeyStrLst);
    mTableView->setPrimaryKey("name");

    QVariantList hitems;
    hitems << QVariant();
    hitems << TDataParse::variantList2Map(
                  QVariantList() << "name" << "name" << "display" << ttr("Name") <<
                  "resizeMode" << "Interactive" << "size" << 130 <<
                  "displayRole" << "$name" << "search" << "string");

    hitems << TDataParse::variantList2Map(
                  QVariantList() <<"name" << "disp" << "display" << ttr("Disp") <<
                  "dataType" << "string" << "resizeMode" << "Interactive" <<
                  "displayRole" << "$disp.text" <<"decorationRole" << "$icon" << "search" << "string");

    hitems << TDataParse::variantList2Map(
                  QVariantList() << "name" << "remark" << "display" << ttr("Remark") <<
                  "resizeMode" << "Interactive" << "displayRole" << "$remark");
    mTableView->setHeaderItem(hitems);
}

QStringList SysEnumList::repeatNameList()
{
    QStringList ret;
    QVariantList nameLst = mTableView->allPrimaryKey();
    if (nameLst.length() < 2) {
        return ret;
    }

    for (int i = 0; i < nameLst.length(); i++) {
        for (int j = i + 1; j < nameLst.length(); j++) {
            if (nameLst.at(i).toString() == nameLst.at(j).toString() && !nameLst.at(i).toString().isEmpty()) {
                ret << nameLst.at(i).toString();
                break;
            }
        }
    }

    return ret;
}

void SysEnumList::tuiDataFillTableView()
{
    TTableModel *model = qobject_cast<TTableModel *>(mTableView->model());
    if (model != nullptr && mLastSelectIndex.isValid()) {
        QVariantMap tuiMap = mListUiLoader->getAllValues().toVariant().toMap();
        QVariantMap indexMap = model->rowDataMap(mLastSelectIndex);
        QString languageStr = APP->language();
        QString valueStr = tuiMap.value(QString("text_") + languageStr).toString();
        QString textStr = tuiMap.value(QString("text")).toString();
        tuiMap.insert("disp.text", valueStr.isEmpty() ? textStr : valueStr);
        for (QString key : tuiMap.keys()) {
            indexMap.insert(key, tuiMap.value(key));
        }

        mTableView->setRowData(mLastSelectIndex, indexMap);
    }
}