/*
 * Copyright (C) 2023, KylinSoft Co., Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 *
**/
#include "printer.h"

#include "ukcccommon.h"
using namespace ukcc;

#include <QtPrintSupport/QPrinterInfo>
#include <QProcess>
#include <cups/cups.h>

#include <QDebug>
#include <QMouseEvent>
#include <QThread>
#include <QDBusConnection>
#include "usbthread.h"

#define ITEMFIXEDHEIGH 58
#define UEVENT_BUFFER_SIZE 2048

#define PRINTER_PATH "/com/redhat/PrinterSpooler"
#define PRINTER_SERVICE  "com.redhat.PrinterSpooler"

Printer::Printer() : mFirstLoad(true)
{
    pluginName = tr("Printer");
    pluginType = DEVICES;
}

Printer::~Printer()
{
    if (!mFirstLoad) {
    }
}

QString Printer::plugini18nName()
{
    return pluginName;
}

int Printer::pluginTypes()
{
    return pluginType;
}

QWidget *Printer::pluginUi()
{
    if (mFirstLoad) {
        mFirstLoad = false;
        pluginWidget = new QWidget;
        pluginWidget->setAttribute(Qt::WA_DeleteOnClose);

        initUi(pluginWidget);
        refreshPrinterDevSlot();

        if (!QDBusConnection::systemBus().connect(QString(), PRINTER_PATH, PRINTER_SERVICE, "PrinterAdded", this, SIGNAL(addsignal(QString)))) {
            qDebug()<<"failed to add D-Bus signal receiver(addprinter)";
        }
        if (!QDBusConnection::systemBus().connect(QString(), PRINTER_PATH, PRINTER_SERVICE, "PrinterRemoved", this, SIGNAL(removesignal(QString)))) {
            qDebug()<<"failed to add D-Bus signal receiver(removeprinter)";
        }

        // 监听打印机增删信号
         connect(this, &Printer::addsignal, [=](const QString &printerName){
             qDebug()<<"addPrinter : "<<printerName;
             QTimer::singleShot(1000, this, [=]() {
                 refreshPrinterDevSlot();
             });
         });
         connect(this, &Printer::removesignal, [=](const QString &printerName){
             qDebug()<<"removePrinter : "<<printerName;
             refreshPrinterDevSlot();
         });
    }
    return pluginWidget;
}

const QString Printer::name() const
{
    return QStringLiteral("Printer");
}

bool Printer::isShowOnHomePage() const
{
    return false;
}

QIcon Printer::icon() const
{
    return QIcon::fromTheme("printer-symbolic");
}

bool Printer::isEnable() const
{
    return true;
}

void Printer::initUi(QWidget *widget)
{
    QVBoxLayout *verticaLyt = new QVBoxLayout(widget);
    verticaLyt->setSpacing(8);
    verticaLyt->setContentsMargins(0, 0, 0, 0);
    mPrinterLabel = new TitleLabel;
    mPrinterLabel->setText(tr("Printers"));

    mPrinterWidget = new SettingGroup(widget);
    initComponent();
    mPrinterWidget->addWidget(mAddWidget);

    verticaLyt->addWidget(mPrinterLabel);
    verticaLyt->addWidget(mPrinterWidget);;
    verticaLyt->addStretch();
}

void Printer::initPrinterUi()
{
    QString info = getPrinterInfo();
    mPrinterWidget->removeWidget(mAddWidget);
    clearAutoItem();
    for (auto printer : mPrinters) {
        UkccFrame *printerBtnFrame = new UkccFrame;
        printerBtnFrame->setLineWidth(0);
        QHBoxLayout *hLyt = new QHBoxLayout(printerBtnFrame);
        hLyt->setContentsMargins(0, 0, 0, 0);
        PrinterBtn *mPriterBtn = new PrinterBtn(printer, printerBtnFrame);
        hLyt->addWidget(mPriterBtn);
        mPrinterWidget->addWidget(printerBtnFrame);
        connect(mPriterBtn, &QPushButton::clicked, this, [=]() {
            runExternalApp();
        });
    }
    mPrinterWidget->addWidget(mAddWidget);


}

void Printer::initComponent()
{
    mAddWidget = new UkccFrame;
    mAddWidget->setLineWidth(0);
    QHBoxLayout *hLyt = new QHBoxLayout(mAddWidget);
    hLyt->setContentsMargins(0, 0, 0, 0);
    //~ contents_path /Printer/Add
    AddButton *addBtn = new AddButton(pluginWidget);
    hLyt->addWidget(addBtn);
    connect(addBtn, &AddButton::clicked, this, &Printer::runExternalApp);

}

void Printer::refreshPrinterDevSlot()
{
    cups_dest_t *dests;
    int num_dests = cupsGetDests(&dests);
    cups_dest_t *dest;
    int i;
    mPrinterList.clear();
    mPrinters.clear();
    for (i = num_dests, dest = dests; i > 0; i --, dest ++) {
        // 获取打印机状态，3为空闲，4为忙碌，5为不可用
        const char *value = cupsGetOption("printer-state", dest->num_options, dest->options);
        qDebug()<<dest->name<<"----------------"<<value;
        if (value == nullptr)
            continue;
        // 标志位flag用来判断该打印机是否可用
        bool flag = (atoi(value) == 5 ? true : false);

        if (flag) {
            if (mPrinterList.contains(QString(dest->name))) {
                mPrinterList.removeOne(QString(dest->name));
                for (int i = 0; i < mPrinters.count(); i++) {
                    if (mPrinters.at(i).name == QString(dest->name)) {
                        mPrinters.remove(i);
                        break;
                    }
                }

            }
        } else {
            if (!mPrinterList.contains(QString(dest->name))) {
                PrinterInfo printer;
                printer.name = QString(dest->name);
                mPrinterList.append(QString(dest->name));
                for (auto k = 0; k < dest->num_options; k++) {
                    if (QString::compare(dest->options[k].name, "device-uri") == 0) {
                        printer.uri = dest->options[k].value;
                    }
                }
                mPrinters.append(printer);
            }
        }
    }
    cupsFreeDests(num_dests, dests);

    initPrinterUi();
}

void Printer::runExternalApp()
{
    UkccCommon::buriedSettings(name(), "open system-config-printer", QString("clicked"));
    if (UkccCommon::isTablet() || UkccCommon::isWayland()) {
        QDBusInterface ifc("com.kylin.AppManager",
                           "/com/kylin/AppManager",
                           "com.kylin.AppManager",
                           QDBusConnection::sessionBus());

        ifc.call("LaunchApp", "/usr/share/applications/kylin-printer.desktop");
    } else {
        QString cmd = "kylin-printer";
        QProcess process(this);
        process.startDetached(cmd);
    }
}

void Printer::clearAutoItem()
{
    if (mPrinterWidget->layout() != NULL) {
        QLayoutItem *item;
        while ((item = mPrinterWidget->layout()->takeAt(0)) != NULL)
        {
            delete item->widget();
            delete item;
            item = nullptr;
        }
    }
}

QString Printer::getPrinterInfo()
{
    QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
    env.insert("LANG","en_US");
    QProcess *process = new QProcess;
    process->setProcessEnvironment(env);
    process->start("lpstat -v");
    process->waitForFinished();

    QByteArray ba = process->readAllStandardOutput();

    delete process;
    return QString(ba.data());
}
