#include <QWidget>
#include <QHBoxLayout>
#include <QHeaderView>
#include "custom_message_box.h"

#include "device_monitor.h"
#include "mainwindow.h"
#include "size_para.h"
#include "custom_list_view.h"
#include "job_manager_window.h"

JobManagerModel::JobManagerModel(QStandardItemModel *parent)
    : QStandardItemModel(parent)
{
    this->setRowCount(0);
    this->setColumnCount(jobList.size());
    for (int i = 0; i < jobList.size(); i++) {
        setHeaderData(i, Qt::Horizontal, jobList.at(i));
    }
}

QString JobManagerModel::getJobTitleTranslation(const QString &title)
{
    if (title == "Test Page") {
        return tr("Test Page");
    }
    if (title == "untitled") {
        return tr("untitled");
    }
    return title;
}

bool JobManagerModel::addJob(const PrintJob &job)
{
    int i = 0;
    // 在表头插，这样最前面的就是最新的
    this->insertRow(0);
    this->setData(index(0, i++), QString::number(job.id));
    this->setData(index(0, i++), job.user == "unknown" ? tr("unknown") : job.user);
    this->setData(index(0, i++), getJobTitleTranslation(job.title));
    this->setData(index(0, i++), job.printerName);
    this->setData(index(0, i++), QString::number(job.size)+"kb");
    this->setData(index(0, i++), job.createTime);
    this->setData(index(0, i++), jobStatusStrList.at(job.jobState));
    return true;
}

// ToDo: 接口先留出来
void JobManagerModel::resetFont(QFont font)
{
    for (int i = 0; i < this->rowCount(); i++) {
        for (int j = 0; j < this->columnCount(); j++) {
            this->item(i,j)->setFont(font);
        }
    }
    return ;
}

JobManagerModel::~JobManagerModel()
{

}





// JobMenu
int menuflag = 0;
JobMenu *menuptr = nullptr;
JobMenu::JobMenu(QWidget *parent)
    : QMenu(parent)
{
    menuflag = 1;
    menuptr = this;
    QList<QAction *> actions;
    this->m_actionCancel = new QAction(this);
    this->m_actionCancel->setText(tr("Cancel print"));
    this->m_actionDelete = new QAction(this);
    this->m_actionDelete->setText(tr("Delete print"));
    this->m_actionHold = new QAction(this);
    this->m_actionHold->setText(tr("Hold print"));
    this->m_actionRelease = new QAction(this);
    this->m_actionRelease->setText(tr("Release print"));
    this->m_actionRepint = new QAction(this);
    this->m_actionRepint->setText(tr("Repaint"));
    this->m_actionMove= new QAction(this);
    this->m_actionMove->setText(tr("Use other printer..."));
    {
        m_moveMenu = new QMenu();
        QList<QAction *> actions;
        QList<DeviceInformation> lis;
        lis = DeviceMonitor::getInstance()->getAllPrinterWithPDD(false);
        for (auto info : lis) {
            QAction *act = new QAction(m_moveMenu);
            act->setText(info.name);
            actions << act;
        }
        m_moveMenu->addActions(actions);
        m_actionMove->setMenu(m_moveMenu);
        this->addMenu(m_moveMenu);
    }
    // QMenu = new moveMenu();
    actions << this->m_actionCancel
            << this->m_actionDelete
            << this->m_actionHold
            << this->m_actionRelease
            << this->m_actionRepint
            << this->m_actionMove
            ;
    
    this->addActions(actions);
}

JobMenu::~JobMenu()
{
    menuflag = 0;
    menuptr = nullptr;
}




// JobManagerWindow


JobManagerWindow::JobManagerWindow(QString printerName, UkuiQueueStatus status, QWidget *parent)
    : kdk::KDialog(parent), 
      m_printerName(printerName), 
      m_status(status)
{
    QString makeObjectName = printerName == "" ? QString("job list") : printerName + " " + QString("job list");
    this->setObjectName(makeObjectName);
    MainWindow *p = MainWindow::getInstance();
    m_mainWidCenterPos = QPoint(p->mapToGlobal(QPoint(0,0)).x() + p->width()/2, p->mapToGlobal(QPoint(0,0)).y() + p->height()/2);
    this->initUi();
    this->initConnect();
    this->updateModel(false);
    this->initTimer();
    this->setWindowModality(Qt::ApplicationModal);
    // this->setWindowFlags(Qt::Tool);
    // UKUI_WIN_CONTROL_PROTOOL(this->winId());
}

JobManagerWindow::~JobManagerWindow()
{

}

void lsjobs(const QList<PrintJob> &jobs)
{
    static int i = 0;
    printf("------%d---------\n", i++);
    printf("/*****************************************/\n");
    for (auto job : jobs) {
        printf("%d\n", job.id);
        printf("%d\n", job.jobState);
    }
    printf("/*****************************************/\n");
}

void JobManagerWindow::updateModel(bool needCompare)
{
    QList<PrintJob> tjobs;
    getJobs(tjobs, m_printerName, m_status);
    // if( needCompare != compareJobs(this->jobs, tjobs)) {
    //     lsjobs(this->jobs);
    //     lsjobs(tjobs);
    // }
    if (needCompare == false || compareJobs(this->m_jobs, tjobs)== false) {
        // if (menuflag && menuptr != nullptr) {
        //     menuptr->close();
        // }
        m_model->removeRows(0, m_model->rowCount());
        m_jobs.clear();
        m_jobs = tjobs;
        for (auto job : this->m_jobs) {
            this->m_model->addJob(job);
        }
    }
}

bool JobManagerWindow::compareJobs(const QList<PrintJob> &a, const QList<PrintJob> &b) const
{
    if (a.size() != b.size()) return false;
    for (int i = 0; i < a.size(); i++) {
        PrintJob aa = a.at(i);
        PrintJob bb = b.at(i);
        if (
            aa.id          != bb.id
         || aa.jobState    != bb.jobState
        ) {
            return false;
        }
    }
    return true;
}

void JobManagerWindow::getJobs(QList<PrintJob> &jobls, const QString &printerName, const UkuiQueueStatus &status)
{
    
    if (printerName.isEmpty()) {
        m_printerList = DeviceMonitor::getInstance()->getAllPrinterWithPDD(false);
        for (auto info : m_printerList) {
            UkuiPrinterManager::getInstance().getPrintQueue(info.name, status, jobls);
        }
    }
    else {
        UkuiPrinterManager::getInstance().getPrintQueue(printerName, status, jobls);
    }
    return ;
}

void JobManagerWindow::initView()
{
    m_view.reset(new CustomListView());

    // 设置右键触发customContextMenuRequested信号
    m_view.get()->setContextMenuPolicy(Qt::CustomContextMenu);

    // 最后一格拉伸到最后
    // m_view.get()->horizontalHeader()->setStretchLastSection(true);
    // this->view->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);

    this->m_model = new JobManagerModel();
    m_view.get()->setModel(this->m_model);
}

void JobManagerWindow::initTimer()
{
    this->m_timer = new QTimer(this);
    connect(this->m_timer, &QTimer::timeout, this, [=](){
        emit updateModel(true);
    });
    this->m_timer->start(1000);
}

void JobManagerWindow::initUi()
{
    this->setWindowTitle(m_printerName.isEmpty() ? tr("Printer") : m_printerName);
    this->setWindowIcon(QIcon::fromTheme("kylin-printer"));
    this->setMinimumSize(820,420);
    this->initView();
    this->initMenu();
    this->maximumButton()->show();
    this->minimumButton()->show();

    QHBoxLayout *layout = new QHBoxLayout();
    layout->addWidget(m_view.get());
    layout->setContentsMargins(24,16,24,24);
    this->mainWidget()->setLayout(layout);

    this->move(m_mainWidCenterPos - this->rect().center());
}

void JobManagerWindow::initConnect()
{
    connect(m_view.get(), &QTableView::customContextMenuRequested, this, &JobManagerWindow::ShowContextMenu);
}

void JobManagerWindow::initMenu()
{
    // menu = new JobMenu(this);
}

void JobManagerWindow::ShowContextMenu(const QPoint& pos)
{
    this->m_selectList = m_view.get()->selectionModel()->selectedIndexes();
    // selectList = this->view->selectionModel()->selectedRows(0);
    // qDebug() << this->selectList.size();
    // for(auto select : this->selectList) {
    //     qDebug() << select.row()<<" "<<select.data().toString();
    // }
    // qDebug() << pos;
    // index = view->indexAt(view->mapFromGlobal(QCursor::pos()));
    // qDebug() << index.row() << index.column();
    JobMenu menu;
    connect(&menu, &QMenu::triggered, this, &JobManagerWindow::triggerMenu);
    int idx = -1;
    // 多行暂不处理
    if ((m_view.get()->indexAt(pos).row() < 0 && this->m_selectList.size() == 0)
     || (this->m_selectList.size() / jobList.size() != 1)) {
        ;
    }
    else if (this->m_selectList.size() / jobList.size() == 1) {
        QString stu = this->m_selectList.at(6).data().toString();
        idx = jobStatusStrList.indexOf(stu);
        // qDebug() << stu << " " << idx;
    }
    this->setMenuActionEnabled(menu, idx);
	menu.exec(QCursor::pos());
}

void JobManagerWindow::setMenuActionEnabled(JobMenu &menu, const int &status)
{
    // qDebug () << status;
    menu.m_actionCancel->setEnabled(false);
    menu.m_actionDelete->setEnabled(false);
    menu.m_actionHold->setEnabled(false);
    menu.m_actionRelease->setEnabled(false);
    menu.m_actionRepint->setEnabled(false);
    menu.m_actionMove->setEnabled(false);

    // qDebug () << status;

    switch (status)
    {
    case -1:
        break;
    case IPP_JSTATE_PENDING:
        menu.m_actionCancel->setEnabled(true);
        menu.m_actionHold->setEnabled(true);
        menu.m_actionMove->setEnabled(true);
        break;
    case IPP_JSTATE_HELD:
        menu.m_actionCancel->setEnabled(true);
        menu.m_actionRelease->setEnabled(true);
        break;
    case IPP_JSTATE_PROCESSING:
        menu.m_actionCancel->setEnabled(true);
        break;
    case IPP_JSTATE_STOPPED:
        break;
    case IPP_JSTATE_CANCELED:
        menu.m_actionDelete->setEnabled(true);
        break;
    case IPP_JSTATE_ABORTED:
        break;
    case IPP_JSTATE_COMPLETED:
        menu.m_actionDelete->setEnabled(true);
        menu.m_actionRepint->setEnabled(true);
        break;
    default:
        break;
    }
    return ;
}

bool JobManagerWindow::getJob(PrintJob &job, const int &id) const
{
    for (auto j : this->m_jobs) {
        if (j.id == id) {
            job = j;
            return true;
        }
    }
    return false;
}

void JobManagerWindow::triggerMenu(QAction *action)
{
    QString str = action->text();
    // qDebug() << str;
    int clickOk = 0;
    for (int i = 0; i < m_selectList.size(); i+= jobList.size()) {
        int jobId = m_selectList.at(i).data().toInt();
        PrintJob inJobs;
        if (!getJob(inJobs, jobId)) {
            break;
        }
        QString printerName = m_selectList.at(i + 3).data().toString();
        int jobState = jobStatusStrList.indexOf(m_selectList.at(i + 6).data().toString());
        if (printerName != inJobs.printerName
         || jobState != inJobs.jobState) {
            break;
        }
        clickOk = 1;
        if(tr("Cancel print") == str) {
            UkuiPrinterManager::getInstance().cancelJob(printerName, jobId);
        }
        else if(tr("Delete print") == str) {
            UkuiPrinterManager::getInstance().deleteJob(printerName, jobId);
        }
        else if(tr("Hold print") == str) {
            UkuiPrinterManager::getInstance().holdJob(jobId);
        }
        else if(tr("Release print") == str) {
            UkuiPrinterManager::getInstance().releaseJob(jobId);
        }
        else if(tr("Repaint") == str) {
            UkuiPrinterManager::getInstance().restartJob(jobId);
        }
        // move to 指定打印机
        else {
            if (printerName == str) {
                clickOk = -1;
                break;
            }
            UkuiPrinterManager::getInstance().moveJob(printerName, str, jobId);
        }
    }
    if (clickOk == 1) {
        updateModel(false);
    }
    else if (clickOk == 0){
        CustomMessageBox Msg(CustomMessageBox::Warning, tr("Warning"), tr("Set error: Job status has been updated!"), CustomMessageBox::NoButton);
        Msg.setParent(this);
        Msg.addButton(tr("Sure"), CustomMessageBox::YesRole);
        Msg.exec();
    }
    else if (clickOk == -1) {
        CustomMessageBox Msg(CustomMessageBox::Warning, tr("Warning"), tr("Cannot move job to itself!"), CustomMessageBox::NoButton);
        Msg.setParent(this);
        Msg.addButton(tr("Sure"), CustomMessageBox::YesRole);
        Msg.exec();
    }
    else {
        qDebug() << "Some error in triggerMenu!";
    }
    return ;
}

void JobManagerWindow::showThis()
{
    if (this->isHidden()) {
        this->show();
    }
    else {
        this->activateWindow();
    }
}

void JobManagerWindow::hideThis()
{
    if (this->isHidden()) {
        return ;
    }
    else {
        this->hide();
    }
}

JobManagerWindow *JobManagerWindow::getInstance(QString printerName, UkuiQueueStatus status, QWidget *parent)
{
    QString makeObjectName = printerName == "" ? QString("job list") : printerName + " " + QString("job list");
    QWidgetList lswid = QApplication::allWidgets();
    for (auto wid : lswid) {
        // qDebug () << wid->objectName();
        if (wid->objectName() == makeObjectName) {
            return static_cast<JobManagerWindow *>(wid);
        }
    }
    JobManagerWindow *p = new JobManagerWindow(printerName, status, parent);
    return p;
}
