#include <QHBoxLayout>
#include <QMessageBox>

#include <kysdk/applications/knavigationbar.h>

#include "property_window.h"
#include "property_list_window.h"
#include "mainwindow.h"
#include "select_ppd_dialog.h"
#include "dictionary_for_chinese_printer.h"
#include "property_itemwidget.h"
#include "common.h"

PropertyWindow::PropertyWindow(const UkuiUsbPrinter &printerInfo, QWidget *parent) :
    m_currentPrinterInfo(printerInfo),
    kdk::KDialog(parent)
{
    initUi();
    
    setWindowModality(Qt::ApplicationModal);

    addTab(tr("base"));
    if (m_currentPrinterInfo.flexibleOptions.size()) {
        addTab(tr("advanced"));
    }

    auto index = m_navigationBar->model()->item(0)->index();
    m_navigationBar->listview()->setCurrentIndex(index);

    for (auto &it : m_currentPrinterInfo.flexibleOptions)
    {
        getZhPropertyfromEn(it);
    }
    insertItemListLayout();
    initConnect();
    QPoint temp = QPoint(parent->mapToGlobal(QPoint(0,0)).x() + parent->width()/2,parent->mapToGlobal(QPoint(0,0)).y() + parent->height()/2);
    this->move(temp - this->rect().center());
}

void PropertyWindow::initUi()
{
    setWindowIcon(QIcon::fromTheme("kylin-printer"));
    setWindowTitle(tr("PrinterProperty"));

    sideBar = new QWidget();
    sideBar->setFixedSize(198, 539);
    baseBar = new QWidget();

    mainLayout = new QHBoxLayout();
    mainLayout->setMargin(0);
    mainLayout->setSpacing(0);
    mainLayout->addWidget(sideBar);
    mainLayout->addWidget(baseBar);
    mainWidget()->setLayout(mainLayout);

    m_navigationBar = new kdk::KNavigationBar(nullptr);
    

    m_leftLayout = new QHBoxLayout();
    m_leftLayout->setContentsMargins(11, 16, 23, 0);
    m_leftLayout->setSpacing(0);

    m_leftLayout->addWidget(m_navigationBar);
    sideBar->setLayout(m_leftLayout);


    m_propertyListWindow = new PropertyListWindow();
    m_propertyListWindow->getNameLabel()->setText(tr("base"));
    m_rightLayout = new QHBoxLayout();
    m_rightLayout->setMargin(0);
    m_rightLayout->setSpacing(0);
    m_rightLayout->addWidget(m_propertyListWindow);
    baseBar->setLayout(m_rightLayout);

    // setStyleSheet(QString::fromUtf8("border:3px solid blue"));
}

PropertyWindow::~PropertyWindow()
{
    delete mainLayout;
    delete sideBar;
    delete baseBar;
    delete m_leftLayout;
    delete m_rightLayout;
    delete m_navigationBar;
    delete m_propertyListWindow;
    delete m_itemMap;
}

void PropertyWindow::insertItemListLayout()
{
    m_itemMap = new QMap<QString, ProperytItemWidget *>;

    createItem(0, g_propertyList.find("Name").value(),     tr("Name"));
    createItem(0, g_propertyList.find("Location").value(), tr("Location"));
    createItem(0, g_propertyList.find("Status").value(),   tr("Status"));
    auto item = createItem(0, g_propertyList.find("Driver").value(),   tr("Driver"));
    if (item) {
        connect(item, &ProperytItemWidget::thirdOperateButtonClicked, this, &PropertyWindow::selectPPDDialogShow);
        item->setThirdButtonText(tr("Modify"));
    }
    createItem(0, g_propertyList.find("URI").value(),      tr("URI"));


    if (!m_currentPrinterInfo.flexibleOptions.size()) {
        return ;
    }

    for(auto cur : m_currentPrinterInfo.flexibleOptions)
    {
        qDebug() << "当前项展示名：" << cur.keyword.displayName;
        auto item = createItem(1, PropertyBoxStyle::TEXT_WITH_COMBOBOX, cur.keyword.displayName);
        if (item) {
            item->setObjectName(cur.keyword.name);
            connect(item,  &ProperytItemWidget::showProperyChanged, this, &PropertyWindow::checkOptionConflicts);
        }
    }
}

void PropertyWindow::onShow()
{
    for (auto &it : m_currentPrinterInfo.flexibleOptions)
    {
        getZhPropertyfromEn(it);
    }

    updateItemListLayout(m_currentPrinterInfo);
    g_printerManger.startModifyAttr(m_currentPrinterInfo.name,m_currentPrinterInfo);

    if(!isActiveWindow())
    {
        hide();
        show();
    }

    show();
    raise();
    activateWindow();

    m_propertyListWindow->getNameLabel()->setText(tr("base"));
    m_propertyListWindow->getStackedWidget()->setCurrentIndex(0);
}

void PropertyWindow::updateItemListLayout(const UkuiUsbPrinter& currentPrinterInfo)
{
    for (auto i = m_itemMap->begin(); i != m_itemMap->end(); i++) {
        QString propertyName = i.key();
        if (!propertyName.compare("Name")||!propertyName.compare(tr("Name"))) {
            i.value()->setSecondProperty(currentPrinterInfo.name);
        }
        else if (!propertyName.compare("Location")||!propertyName.compare(tr("Location")))
        {
            i.value()->setSecondProperty(currentPrinterInfo.location);
        }
        else if (!propertyName.compare("Status")||!propertyName.compare(tr("Status")))
        {
            if(!currentPrinterInfo.connect_status.compare(tr("Idle")))
            {
                i.value()->setSecondProperty(tr("Idle"));
            }
            else if(!currentPrinterInfo.connect_status.compare(tr("Printing")))
            {
                i.value()->setSecondProperty(tr("Printing"));
            }
            else if(!currentPrinterInfo.connect_status.compare(tr("Stopped")))
            {
                i.value()->setSecondProperty(tr("Stopped"));
            }
            else
            {
                qWarning() << "打印机状态异常：" << currentPrinterInfo.connect_status;
                i.value()->setSecondProperty(tr("Unknow"));
            }
        }
        else if (!propertyName.compare("Driver")||!propertyName.compare(tr("Driver"))) {
            i.value()->setSecondProperty(currentPrinterInfo.make_and_model);
        }
        else if (!propertyName.compare("URI")||!propertyName.compare(tr("URI")))
        {
            i.value()->setSecondProperty(currentPrinterInfo.device_uri);
        }
        else {
            qDebug() << propertyName;
            disconnect(i.value(),  &ProperytItemWidget::showProperyChanged, this, &PropertyWindow::checkOptionConflicts);

            for(auto cur : m_currentPrinterInfo.flexibleOptions)
            {
                if (!propertyName.compare(cur.keyword.displayName))
                {
                    qDebug() << cur.current.name;
                    for (auto l : cur.supported) {
                        qDebug() << l.displayName;
                    }
                    i.value()->setSecondProperty(cur.current, cur.supported);
                    break;
                }
            }
            connect(i.value(),  &ProperytItemWidget::showProperyChanged, this, &PropertyWindow::checkOptionConflicts);
        }
    }
}

void PropertyWindow::checkOptionConflicts(QString optionName, QString curVal)
{
    qDebug() << optionName;
    qDebug() << curVal;

    QMap<QString, QString> conflicts;

    int res = g_printerManger.modifyPrinterAttr(optionName, curVal, conflicts);
    if(-1 == res)
    {
        updateItemListLayout(m_currentPrinterInfo);

        QMessageBox Msg(QMessageBox::Warning, tr("Warning"), tr("Error happened, all options restored!."), QMessageBox::NoButton);
        Msg.setParent(this);
        Msg.addButton(tr("Confirm"), QMessageBox::YesRole);
        Msg.exec();
        return;
    }
    else
    {
        setAllConflicts(optionName,conflicts);
    }
}

void PropertyWindow::setAllConflicts(QString option, QMap<QString, QString> conflicts)
{
    for (auto i = m_itemMap->begin(); i != m_itemMap->end(); i++) {
        i.value()->showWarning(false);
    }

    //g_printerManger.getConflictResults(option, conflictsList); //获取当前修改项的冲突项

    if(conflicts.size())
    {
        for (auto i = m_itemMap->begin(); i != m_itemMap->end(); i++)//冲突项1置为红色
        {
            for(auto it : conflicts)
            {
                if (i.value()->getSecondComboBoxContent().contains(it))
                {
                    i.value()->showWarning(true);
                    break;
                }
            }
        }

        m_propertyListWindow->getAcceptButton()->setEnabled(false);
    }
    else
    {
        m_propertyListWindow->getAcceptButton()->setEnabled(true);
    }
}
void PropertyWindow::initConnect()
{   
    connect(m_navigationBar->listview(), &QListView::clicked, [=](const QModelIndex &index) {
        m_propertyListWindow->getStackedWidget()->setCurrentIndex(index.row());
        switch (index.row())
        {
        case 0:
            m_propertyListWindow->getNameLabel()->setText(tr("base"));
            m_propertyListWindow->getStackedWidget()->setCurrentIndex(0);
            break;
        case 1:
            m_propertyListWindow->getNameLabel()->setText(tr("advanced"));
            m_propertyListWindow->getStackedWidget()->setCurrentIndex(1);
            break;
        default:
            break;
        }
    });
    connect(m_propertyListWindow,  &PropertyListWindow::saveRequest,  this, &PropertyWindow::doSave);
    connect(m_propertyListWindow,  &PropertyListWindow::closeRequest, this, &kdk::KDialog::close);
}

void PropertyWindow::selectPPDDialogShow()
{
//    SelectPpdDialog ppdDialog(this);
    m_pSelectPPDDialog = new SelectPpdDialog(this);
    connect(m_pSelectPPDDialog,SIGNAL(chosenPPDName(QString)),this,SLOT(updatePPD(QString)));
    m_pSelectPPDDialog->onShow();
    m_pSelectPPDDialog->exec();
}

void PropertyWindow::doSave()
{
    for (auto i = m_itemMap->begin(); i != m_itemMap->end(); i++)
    {
        QString propertyName = i.key();
        QString propertyValue = i.value()->getProperty();
        if (!propertyName.compare("Name")||!propertyName.compare(tr("Name")))
        {
            m_currentPrinterInfo.name = propertyValue;
        }
        else if (!propertyName.compare("Location")||!propertyName.compare(tr("Location")))
        {
            m_currentPrinterInfo.location = propertyValue;
            g_printerManger.modifyLocation(m_currentPrinterInfo.location);
        }
        else if (!propertyName.compare("Status")||!propertyName.compare(tr("Status")))
        {
            m_currentPrinterInfo.connect_status = propertyValue;
        }
        else if (!propertyName.compare("Driver")||!propertyName.compare(tr("Driver")))
        {
            m_currentPrinterInfo.make_and_model = propertyValue;
        }
        else if (!propertyName.compare("URI")||!propertyName.compare(tr("URI")))
        {
            m_currentPrinterInfo.device_uri = propertyValue;
        }
        else
        {
            for (auto &it : m_currentPrinterInfo.flexibleOptions)
            {
                if(!propertyName.compare(it.keyword.displayName, Qt::CaseInsensitive) )
                {
                    it.current.name = i.value()->getSecondComboBoxContent();
                }
            }
        }
    }

    g_printerManger.endModifyAttr(m_currentPrinterInfo.name, true);
    qDebug() << "修改成功";
    emit MainWindow::getInstance()->updateMainWin();
    this->close();
}

void PropertyWindow::updatePPD(QString text)
{
    emit MainWindow::getInstance()->modifyPPD(text);
    QList<UkuiUsbPrinter> allPrintersVector;
    UkuiPrinterManager::getInstance().enumPrinters(allPrintersVector);
    for(auto printer : allPrintersVector)
    {
        if(printer.name == m_currentPrinterInfo.name)
        {
            m_currentPrinterInfo = printer;
        }
    }
    findItem(tr("Driver"))->setSecondProperty(m_currentPrinterInfo.make_and_model);

    return;
}

bool PropertyWindow::checkPrinterNameIsLegal(QString lineText)
{
    if(!lineText.compare(""))
    {
        m_propertyListWindow->getAcceptButton()->setEnabled(false);
        return false;
    }
    if(printerNameIsLegal(lineText) == false)
    {
        m_propertyListWindow->getAcceptButton()->setEnabled(false);
        QString warningMsg = tr("Printer Name Cannot Contains '/\\'\"?#', And More Than 0 Letter, Less Than 128 Letters !");
        QMessageBox Msg(QMessageBox::Warning,tr("Warning"),warningMsg,QMessageBox::NoButton);
        Msg.setParent(this);
        Msg.addButton(tr("Close"), QMessageBox::NoRole);
        Msg.exec();

        return false;
    }
    else
    {
        QList<UkuiUsbPrinter> allPrintersVector;
        g_printerManger.enumPrinters(allPrintersVector);
        for(auto it:allPrintersVector)
        {
            if(!lineText.compare(it.name,Qt::CaseSensitive))
            {
                QString warningMsg = tr("Exist Same Name Printer!");
                QMessageBox Msg(QMessageBox::Warning,tr("Warning"),warningMsg,QMessageBox::NoButton);
                Msg.setParent(this);
                Msg.addButton(tr("Close"), QMessageBox::NoRole);
                Msg.exec();

                m_propertyListWindow->getAcceptButton()->setEnabled(false);
                return false;
            }
            else if(!lineText.compare(it.name,Qt::CaseInsensitive))
            {
                QString warningMsg = tr("Printer Name Illegal!");
                QMessageBox Msg(QMessageBox::Warning,tr("Warning"),warningMsg,QMessageBox::NoButton);
                Msg.setParent(this);
                Msg.addButton(tr("Close"), QMessageBox::NoRole);
                Msg.exec();

                m_propertyListWindow->getAcceptButton()->setEnabled(false);
                return false;
            }
            else
            {
                continue;
            }
        }
        m_propertyListWindow->getAcceptButton()->setEnabled(true);
    }

    return true;
}

void PropertyWindow::getZhPropertyfromEn(SelectableProperty& enProperty)
{
    DictionaryForChinesePrinter dict;
    for (auto &cur: dict.getPropertyDict())
    {
        if (!(enProperty.keyword.displayName.trimmed()).compare(cur.at(0),Qt::CaseInsensitive))
        {
            enProperty.keyword.displayName = cur.at(1);
        }
        if (!(enProperty.current.displayName.trimmed()).compare(cur.at(0),Qt::CaseInsensitive))
        {
            enProperty.current.displayName = cur.at(1);
        }
        for (auto &it : enProperty.supported)
        {
            if (!(it.displayName.trimmed()).compare(cur.at(0),Qt::CaseInsensitive))
            {
                it.displayName = cur.at(1);
            }
        }
    }
    return ;
}

void PropertyWindow::setQSSFontSize(QFont curFont)
{

    double font18Size = curFont.pointSizeF()/15*16;

    QFont font18 = curFont;
    font18.setPointSizeF(font18Size);
    font18.setBold(true);
    m_propertyListWindow->getNameLabel()->setFont(font18);
}

ProperytItemWidget *PropertyWindow::createItem(int index, PropertyBoxStyle style, const QString &propertyName)
{
    if (propertyName.isEmpty() || findItem(propertyName) != nullptr) {
        return nullptr;
    }
    auto page = m_propertyListWindow->getListWidget(index);

    ProperytItemWidget *item = new ProperytItemWidget(propertyName,style,page);
    QListWidgetItem *listWidgetItem = new QListWidgetItem(page);
    listWidgetItem->setFlags(Qt::ItemIsSelectable);
    listWidgetItem->setSizeHint(QSize(this->height(), 44));
    page->addItem(listWidgetItem);
    page->setItemWidget(listWidgetItem, item);

    m_itemMap->insert(propertyName, item);

    return item;
}

ProperytItemWidget *PropertyWindow::findItem(const QString &propertyName)
{
    auto res = m_itemMap->find(propertyName);
    if (res == m_itemMap->end()) {
        return nullptr;
    }
    return res.value();
}

void PropertyWindow::addTab(const QString &name)
{
    auto item = new QStandardItem(name);
    m_navigationBar->addItem(item);
}