#include "burnimage.h"
#include "ui_burnimage.h"
#include "burnimageisoitem.h"
#include "src/po/translation.h"
#include "src/frame/logger.h"
#include "src/frame/configuration.h"
#include "src/model/logicburnimage.h"
#include "src/model/menufactory.h"
#include "src/model/logicmain.h"

#include <QHBoxLayout>
#include <QFileDialog>
#include <QFileInfo>
#include <QFileSystemWatcher>
#include <QDebug>
#include <ukuistylehelper/ukuistylehelper.h>
#include <windowmanager/windowmanager.h>
BurnImage *BurnImage::m_oInstance = nullptr;
QMutex     BurnImage::m_oMutex;

BurnImage::BurnImage(QWidget *parent) :
    QWidget(parent),
    m_oListWidget(new QListWidget(this)),
    m_oListWidgetBurner(new QListWidget(this)),
    m_oUpdateTimer(new QTimer),
    ui(new Ui::BurnImage)
{
    this->setObjectName("kylin-burner_BurnImage");
    ui->setupUi(this);
    setAccessibleName();

    ui->title->setFocusPolicy(Qt::NoFocus);
    ui->title->setText(_("BurnImage"));
    ui->comboBoxBurner->setModel(m_oListWidgetBurner->model());
    ui->comboBoxBurner->setView(m_oListWidgetBurner);
    ui->comboBoxISO->setModel(m_oListWidget->model());
    ui->comboBoxISO->setView(m_oListWidget);
    ui->btnBrowseISO->setText(_("Browse"));
    ui->btnBurnerSetting->setText(_("Setting"));
    ui->labelISOTitle->setText(_("Please select ISO file which will to be burned"));
    ui->labelBurnerTitle->setText(_("Please select burner which will burned to"));

    m_oShowISO = new QWidget(ui->isoWidget);
    m_oShowISO->setMinimumSize(ui->isoWidget->size());
    m_oShowISO->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
    m_oIcon = new QLabel(m_oShowISO);
    m_oIcon->setFixedSize(25, 30);

    m_oDisplay = new QLabel(m_oShowISO);
    m_oDisplay->setFixedHeight(30);

    QHBoxLayout *showISOLay = new QHBoxLayout(m_oShowISO);
    showISOLay->setMargin(0);
    showISOLay->addWidget(m_oIcon);
    showISOLay->addWidget(m_oDisplay);
    QSpacerItem* spacer = new QSpacerItem(8,5,QSizePolicy::Fixed);
    showISOLay->addSpacerItem(spacer);
    showISOLay->addStretch(30);

    m_oShowISO->setFocusPolicy(Qt::NoFocus);
    m_oShowISO->setAttribute(Qt::WA_TransparentForMouseEvents, true);
    m_oShowBurner = new QWidget(ui->burnerWidget);
    m_oIconBurner = new QLabel(m_oShowBurner);

    m_oIconBurner->setFixedSize(25, 30);
    m_oDisplayBurner = new QLabel(m_oShowBurner);
    m_oDisplayBurner->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);

    QHBoxLayout *showBurnerLay = new QHBoxLayout(m_oShowBurner);
    showBurnerLay->setMargin(0);
    showBurnerLay->addWidget(m_oIconBurner);
    showBurnerLay->addWidget(m_oDisplayBurner);
    showBurnerLay->addStretch(15);
    m_oShowBurner->setFocusPolicy(Qt::NoFocus);
    m_oShowBurner->setAttribute(Qt::WA_TransparentForMouseEvents, true);

    slotChangeUIFontSize(LogicMain::instance()->GetSystemFontSize());
    connect(LogicMain::instance(),&LogicMain::systemFontSizeChanged,this,&BurnImage::slotChangeUIFontSize);

    connect(ui->btnBrowseISO, SIGNAL(clicked(bool)), this, SLOT(slotsBrowseISO()));
    connect(ui->comboBoxISO, SIGNAL(currentIndexChanged(int)), this, SLOT(slotsISOChange(int)));
    connect(ui->comboBoxBurner, SIGNAL(currentIndexChanged(int)), this, SLOT(slotsBurnerChange(int)));

    connect(BURNIMAGE, SIGNAL(newISOPath(QString)), this, SLOT(slotsNewISOPath(QString)));
    connect(this, SIGNAL(newISOPath(QString)), LogicBurnImage::instance(), SLOT(onNewISOPath(QString)));
    connect(LogicBurnImage::instance(), SIGNAL(enableBurner(bool)), ui->comboBoxBurner, SLOT(setEnabled(bool)));
    connect(LogicBurnImage::instance(), SIGNAL(enableBurner(bool)), ui->btnBurnerSetting, SLOT(setEnabled(bool)));
    connect(LogicBurnImage::instance(), SIGNAL(enableBurner(bool)), ui->btnBurnerSetting, SLOT(setEnabled(bool)));
    connect(LogicBurnImage::instance(), SIGNAL(enableBusness(bool)), this, SIGNAL(busness(bool)));
    connect(LogicBurnImage::instance(), SIGNAL(isoError(QString)), this, SLOT(slotsISOError(QString)));
    connect(LogicBurnImage::instance(), SIGNAL(burnerError(QString)), this, SLOT(slotsBurnerError(QString)));
    connect(LogicBurnImage::instance(), SIGNAL(ready(QString)), this, SLOT(slotsReady(QString)));
    connect(LogicBurnImage::instance(), SIGNAL(newBurner(QString,QString)), this, SLOT(slotsNewBurner(QString,QString)));
    connect(LogicBurnImage::instance(), SIGNAL(deleteBurner(int)), this, SLOT(slotsDeleteBurner(int)));
    connect(this, SIGNAL(newBurner(int)), LogicBurnImage::instance(), SLOT(onNewBurner(int)));
    connect(ui->btnBurnerSetting, SIGNAL(clicked(bool)), MenuFactory::instance(), SIGNAL(burnSetting(bool)));
    connect(m_oUpdateTimer, SIGNAL(timeout()), this, SLOT(slotsUpdateBurnerInfo()));
    LogicBurnImage::instance()->init();

    // hide the icon, add icon to combobox
    ui->labelLogoBurner->hide();
    ui->labelLogoISO->hide();
    m_oIcon->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
    m_oDisplay->setAlignment(Qt::AlignVCenter | Qt::AlignLeft);
    m_oIconBurner->setAlignment(Qt::AlignCenter | Qt::AlignVCenter | Qt::AlignHCenter);

    m_oUpdateTimer->start(1000);
}

BurnImage *BurnImage::instance()
{
    if (nullptr == m_oInstance)
    {
        QMutexLocker locker(&m_oMutex);
        if (nullptr == m_oInstance)
        {
            m_oInstance = new BurnImage();
        }
    }
    return m_oInstance;
}

void BurnImage::setAccessibleName()
{
    ui->btnBrowseISO->setAccessibleName("kylin-burner_QPushButton_BurnImage_btnBrowseISO");
    ui->btnBurnerSetting->setAccessibleName("kylin-burner_QPushButton_BurnImage_btnBurnerSetting");
    ui->burnerSelection->setAccessibleName("kylin-burner_QWidget_BurnImage_burnerSelection");
    ui->burnerWidget->setAccessibleName("kylin-burner_QWidget_BurnImage_burnerWidget");
    ui->comboBoxBurner->setAccessibleName("kylin-burner_QComboBox_BurnImage_comboBoxBurner");
    ui->comboBoxISO->setAccessibleName("kylin-burner_QComboBox_BurnImage_comboBoxISO");

    ui->isoSelection->setAccessibleName("kylin-burner_QWidget_BurnImage_isoSelection");
    ui->isoWidget->setAccessibleName("kylin-burner_QWidget_BurnImage_isoWidget");
    ui->labelBurnerTip->setAccessibleName("kylin-burner_QLabel_BurnImage_labelBurnerTip");
    ui->labelBurnerTitle->setAccessibleName("kylin-burner_QLabel_BurnImage_labelBurnerTitle");
    ui->labelISOTip->setAccessibleName("kylin-burner_QLabel_BurnImage_labelISOTip");
    ui->labelISOTitle->setAccessibleName("kylin-burner_QLabel_BurnImage_labelISOTitle");
    ui->labelLogoBurner->setAccessibleName("kylin-burner_QLabel_BurnImage_labelLogoBurner");
    ui->labelLogoISO->setAccessibleName("kylin-burner_QLabel_BurnImage_labelLogoISO");
    ui->title->setAccessibleName("kylin-burner_QLabel_BurnImage_title");
}

void BurnImage::update()
{
    BURNIMAGE->init();
}

void BurnImage::resizeEvent(QResizeEvent *event)
{
    int w;
    QListWidgetItem *listItem;
    BurnImageISOItem *item;

    m_oShowISO->setFixedWidth(ui->isoWidget->width() - 20);
    m_oShowBurner->setFixedWidth(ui->burnerWidget->width() - 20);
    w = ui->comboBoxISO->width();
    for (int i = 0; i < ui->comboBoxISO->count(); ++i)
    {
        listItem = m_oListWidget->item(i);
        item = qobject_cast<BurnImageISOItem *>(m_oListWidget->itemWidget(listItem));
        item->setFixedWidth(w);
    }
    for (int i = 0; i < ui->comboBoxBurner->count(); ++i)
    {
        listItem = m_oListWidgetBurner->item(i);
        item = qobject_cast<BurnImageISOItem *>(m_oListWidgetBurner->itemWidget(listItem));
        item->setFixedWidth(w);
    }
    QWidget::resizeEvent(event);
}

void BurnImage::slotsBrowseISO()
{
    QString path;
    QString isoPath;
    QFileDialog fd(this);
    QList<QUrl> list = fd.sidebarUrls();
    int sidebarNum = 8;//最大添加U盘数，可以自己定义
    QString home = QDir::homePath().section("/", -1, -1);
    QString mnt = "/media/" + home + "/";
    QDir mntDir(mnt);
    mntDir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
    QFileInfoList filist = mntDir.entryInfoList();
    QList<QUrl> mntUrlList;
    for (int i = 0; i < sidebarNum && i < filist.size(); ++i) {
        QFileInfo fi = filist.at(i);

        if (fi.fileName() == "2691-6AB8") /* 990 9a0 */
                 continue;

        mntUrlList << QUrl("file://" + fi.filePath());
    }

    QFileSystemWatcher fsw(&fd);
    fsw.addPath("/media/" + home + "/");
    connect(&fsw, &QFileSystemWatcher::directoryChanged, &fd,
            [=, &sidebarNum, &mntUrlList, &list, &fd](const QString path) {
        QDir wmntDir(path);
        wmntDir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
        QFileInfoList wfilist = wmntDir.entryInfoList();
        mntUrlList.clear();
        for (int i = 0; i < sidebarNum && i < wfilist.size(); ++i) {
            QFileInfo fi = wfilist.at(i);

            if (fi.fileName() == "2691-6AB8") /* 990 9a0 */
                     continue;

            mntUrlList << QUrl("file://" + fi.filePath());
        }
        fd.setSidebarUrls(list + mntUrlList);
        fd.update();
    });

    connect(&fd, &QFileDialog::finished, &fd, [=, &list, &fd]() {
        fd.setSidebarUrls(list);
    });

    if (m_oISOPaths.size() && ui->comboBoxISO->currentIndex() >= 0 &&
            ui->comboBoxISO->currentIndex() < m_oISOPaths.size())
        path = m_oISOPaths.at(ui->comboBoxISO->currentIndex());

    fd.setFileMode(QFileDialog::ExistingFiles);
    fd.setNameFilter("ISO(*.iso)");
    fd.setSidebarUrls(list + mntUrlList);
    kdk::UkuiStyleHelper::self()->removeHeader(&fd);
    fd.move(this->geometry().center()-fd.geometry().center());
    kdk::WindowManager::setGeometry(fd.windowHandle(),fd.geometry());
    if (fd.exec() != QDialog::Accepted) return;
    isoPath = fd.selectedFiles().at(0);
    if (isoPath.isEmpty()) return;
    if (-1 != m_oISOPaths.indexOf(isoPath)){
        ui->comboBoxISO->setCurrentIndex(m_oISOPaths.indexOf(isoPath));
    }
    else
        slotsNewISOPath(isoPath);
}

void BurnImage::slotsISOChange(int idx)
{
    int u;
    qreal size;
    QIcon icon;
    QFileInfo f;
    QString display;

    ui->labelISOTip->setText("");

    if (idx < 0)
    {
        ui->labelLogoISO->setPixmap(icon.pixmap(ui->labelLogoISO->size()));
        m_oIcon->setPixmap(icon.pixmap(m_oIcon->size()));
        m_oDisplay->setText("");
        return;
    }
    if (!m_oISOPaths.at(idx).isEmpty())
    {
        emit newISOPath(m_oISOPaths.at(idx));
        icon = QIcon::fromTheme("application-x-cd-image");
    }
    ui->labelLogoISO->setPixmap(icon.pixmap(ui->labelLogoISO->size()));
    m_oIcon->setPixmap(icon.pixmap(QSize(24, 24)));
    f.setFile(m_oISOPaths.at(idx));
    display = f.fileName();
    display.append("  ");
    size = f.size() * 1.0;
    u = -1;
    while (size > 1024.00)
    {
        ++u; size /= 1024.00;
    }
    display.append(QString("%1").arg(size, 0, 'f', 1));
    display.append(" ");
    switch (u)
    {
    case 0:
        display.append(_("KB"));
        break;
    case 1:
        display.append(_("MB"));
        break;
    case 2:
        display.append(_("GB"));
        break;
    default:
        display.append(_("B"));
        break;
    }

    m_oDisplay->setText(display);
    ui->comboBoxISO->setToolTip(display);
}

void BurnImage::slotsNewISOPath(QString path)
{
    BurnImageISOItem *item;
    QListWidgetItem  *listItem;

    m_oISOPaths << path;
    listItem = new QListWidgetItem(m_oListWidget);
    item = new BurnImageISOItem(path, this);
    item->setFixedWidth(ui->comboBoxISO->width());
    m_oListWidget->setItemWidget(listItem, item);
    ui->comboBoxISO->setCurrentIndex(m_oISOPaths.size() - 1);
    emit newISOPath(path);
}

void BurnImage::slotsISOError(QString err)
{
    QPalette pal = ui->labelISOTip->palette();
    pal.setColor(QPalette::WindowText, Qt::red);
    ui->labelISOTip->setPalette(pal);
    ui->labelISOTip->setText(err);
}

void BurnImage::slotsBurnerError(QString err)
{
    m_oIconBurner->hide();
    m_oDisplayBurner->setEnabled(false);
    ui->btnBurnerSetting->setEnabled(false);
    err = "   " + err;
    m_oDisplayBurner->setText(err);
    ui->labelBurnerTip->setText("");
}

void BurnImage::slotsReady(QString str)
{
#if 1
    QIcon icon;
    QString display;
    int idx = ui->comboBoxBurner->currentIndex();
    ui->labelBurnerTip->setText("");
    icon = BURNIMAGE->mediumIcon(idx);
    display = BURNIMAGE->display(idx);
    ui->labelLogoBurner->setPixmap(icon.pixmap(ui->labelLogoBurner->size()));
    m_oIconBurner->show();
    m_oIconBurner->setPixmap(icon.pixmap(QSize(24, 24)));
    m_oDisplayBurner->setText(display);
    ui->comboBoxBurner->setToolTip(display);
    ui->labelISOTip->setText("");
    ui->labelBurnerTip->setText(str);
    m_oDisplayBurner->setEnabled(true);
    ui->btnBurnerSetting->setEnabled(true);
#endif
}

void BurnImage::slotsNewBurner(QString display, QString tooltip)
{
    BurnImageISOItem *item;
    QListWidgetItem  *listItem;

    listItem = new QListWidgetItem(m_oListWidgetBurner);
    item = new BurnImageISOItem(display, this);
    item->setFixedWidth(ui->comboBoxBurner->width());
    item->setToolTip(tooltip);
    m_oListWidgetBurner->setItemWidget(listItem, item);
    ui->comboBoxBurner->setCurrentIndex(ui->comboBoxBurner->count() - 1);
    update();
}

void BurnImage::slotsDeleteBurner(int idx)
{
    BurnImageISOItem *item;
    QListWidgetItem  *listItem;

    listItem = m_oListWidgetBurner->item(idx);
    item = (BurnImageISOItem *)(m_oListWidgetBurner->itemWidget(listItem));
    m_oListWidgetBurner->takeItem(idx);
    delete listItem;
    delete item;
}

void BurnImage::slotsBurnerChange(int idx)
{
    QIcon icon;
    QString display;

    ui->labelBurnerTip->setText("");
    icon = BURNIMAGE->mediumIcon(idx);
    display = BURNIMAGE->display(idx);
    ui->labelLogoBurner->setPixmap(icon.pixmap(ui->labelLogoBurner->size()));
    m_oIconBurner->show();
    m_oIconBurner->setPixmap(icon.pixmap(QSize(24, 24)));
    m_oDisplayBurner->setText(display);
    ui->comboBoxBurner->setToolTip(display);
    emit newBurner(idx);
}

void BurnImage::slotsUpdateBurnerInfo()
{
    update();
}

void BurnImage::slotChangeUIFontSize(int fontSize)
{
    int scaleRatio = qAbs(fontSize - 10.0);
    QFont font = ui->title->font();
    font.setPixelSize(24 + scaleRatio);
    ui->title->setFont(font);

    font = ui->labelISOTitle->font();
    font.setPixelSize(14 + scaleRatio);

    ui->labelISOTip->setFont(font);
    ui->labelBurnerTip->setFont(font);
    ui->comboBoxBurner->setFont(font);
    ui->comboBoxISO->setFont(font);
    ui->btnBrowseISO->setFont(font);
    ui->btnBurnerSetting->setFont(font);


    font.setWeight(60);
    ui->labelISOTitle->setFont(font);
    ui->labelBurnerTitle->setFont(font);

    font.setPixelSize(14 + scaleRatio);
    m_oDisplay->setFont(font);

    m_oDisplayBurner->setFont(font);
}

BurnImage::~BurnImage()
{
    delete ui;

    for (int i = 0; i < m_oListWidgetBurner->count(); ++i)
    {
        QListWidgetItem *listItem = m_oListWidgetBurner->item(i);
        BurnImageISOItem *item = qobject_cast<BurnImageISOItem *>(m_oListWidgetBurner->itemWidget(listItem));
        if (item) {
            item->deleteLater();
        }
    }

    for (int i = 0; i < m_oListWidget->count(); ++i)
    {
        QListWidgetItem *listItem = m_oListWidget->item(i);
        BurnImageISOItem *item = qobject_cast<BurnImageISOItem *>(m_oListWidget->itemWidget(listItem));
        if (item) {
            item->deleteLater();
        }
    }
}
