#include "filereceivingpopupwidget.h"
#include "config/xatom-helper.h"
#include "config/config.h"
#include <file-utils.h>
using namespace Peony;
FileReceivingPopupWidget::FileReceivingPopupWidget(QString address, QString devname,
                                                   QString filename, QString type,
                                                   QString root, quint64 size):
    target_address(address),
    target_name(devname),
    target_source(filename),
    target_type(type),
    root_address(root),
    target_size(size)
{
    if (envPC == Environment::LAIKA || envPC == Environment::MAVIS)
        isIntel = true;
    else
        isIntel = false;
    // 添加窗管协议
    MotifWmHints hints;
    hints.flags = MWM_HINTS_FUNCTIONS|MWM_HINTS_DECORATIONS;
    if (isIntel)
        hints.functions = MWM_FUNC_CLOSE;
    else
        hints.functions = MWM_FUNC_ALL;
    hints.decorations = MWM_DECOR_BORDER;
    XAtomHelper::getInstance()->setWindowMotifHint(this->winId(), hints);

    if(QGSettings::isSchemaInstalled("org.ukui.style")){
        StyleSettings = new QGSettings("org.ukui.style");
        connect(StyleSettings,&QGSettings::changed,this,&FileReceivingPopupWidget::GSettingsChanges);
    }
    this->setWindowIcon(QIcon::fromTheme("bluetooth"));
    this->setWindowTitle(tr("Bluetooth file transfer"));
    this->setAttribute(Qt::WA_DeleteOnClose);

    QPalette palette;
    if(StyleSettings->get("style-name").toString() == "ukui-default" || StyleSettings->get("style-name").toString() == "ukui-light"){
        palette.setColor(QPalette::Background,QColor(255,255,255));
    }else{
        palette.setColor(QPalette::Background,QColor(0,0,0));
    }
    this->setPalette(palette);

    if(QGSettings::isSchemaInstalled("org.ukui.bluetooth")){
        settings = new QGSettings("org.ukui.bluetooth");

        file_path = settings->get("file-save-path").toString();

        connect(settings, &QGSettings::changed,this,&FileReceivingPopupWidget::GSettings_value_chanage);
    }else{
        file_path = QDir::homePath();
    }

    file_source = new QLabel(this);
    file_source->setAlignment(Qt::AlignTop);
    QFont ft;
    ft.setPixelSize(14);
    QFont ft1;
    ft1.setPixelSize(18);

    QIcon fileicon = getFileIconFromType(target_type);
    file_icon = new QLabel(this);
    file_icon->setPixmap(fileicon.pixmap(64,64));
    file_icon->setAlignment(Qt::AlignCenter);

    QFontMetrics fontMetrics(file_source->font());
    QString fileName = fontMetrics.elidedText(target_source, Qt::ElideMiddle, 280);
    file_name = new QLabel(fileName,this);
    file_name->setToolTip(target_source);
    file_name->setFont(ft);
    file_name->setAlignment(Qt::AlignVCenter|Qt::AlignLeft);

    QString fileSizeStr;
    if (target_size != 0) {
        int unitcount = 0;   //将单位B转化为对应的KB、MB等单位
        double calc_size = target_size;
        while(calc_size >= 1024) {
            calc_size /= 1024;
            unitcount++;
        }
        fileSizeStr = QString::asprintf("%.1f", calc_size) + unitString[unitcount];
    } else
        fileSizeStr = QString(tr("Greater than 4GB"));

    file_size = new QLabel(this);
    file_size->setText(fileSizeStr);
    file_size->setFont(ft);
    file_size->setAlignment(Qt::AlignVCenter|Qt::AlignLeft);
    file_size->setWordWrap(true);

    transfer_progress = new QProgressBar(this);
    transfer_progress->setFixedHeight(15);
    transfer_progress->setTextVisible(false);
    transfer_progress->setVisible(false);

    cancel_btn = new QPushButton(tr("Cancel"),this);
    connect(cancel_btn,&QPushButton::clicked,this,[=]{
        Q_EMIT this->rejected();

        this->close();
    });

    accept_btn = new QPushButton(tr("Accept"),this);
    connect(accept_btn,&QPushButton::clicked,this,[=]{
        OnClickedAcceptBtn();
    });

    warn_icon = new QLabel(this);
    warn_icon->setPixmap(QIcon::fromTheme("kylin-dialog-warning").pixmap(22,22));
    if (warn_icon->pixmap()->isNull())
        warn_icon->setPixmap(QIcon::fromTheme("dialog-warning").pixmap(22,22));
    warn_icon->setVisible(false);

    view_btn = new QPushButton(tr("View"),this);
    view_btn->setVisible(false);

    receivedFiles.clear();
    receiveTimer = new QTimer(this);
    connect(receiveTimer,SIGNAL(timeout()), this, SLOT(transferCompelete()));

    if (isIntel)
        initIntelLayout();
    else
        initLayout();

    QDesktopWidget *desktop_widget = QApplication::desktop();
    desktop = desktop_widget->availableGeometry();
    qDebug() << Q_FUNC_INFO << this->width() << this->height();
    qDebug() << Q_FUNC_INFO <<desktop <<desktop.right() << desktop.bottom() << desktop.right()-this->width() << desktop.bottom()-this->height();
    this->move(QPoint(desktop.right()-this->width() - 4,desktop.bottom()-this->height() - 4));

    window_pop_up_animation();
    this->activateWindow();
    this->show();
    this->setFocusPolicy(Qt::NoFocus);
}

FileReceivingPopupWidget::~FileReceivingPopupWidget()
{
    delete settings;
}

void FileReceivingPopupWidget::initLayout() {
    this->setFixedSize(520,276);
    close_btn = new QPushButton(this);
    close_btn->setIcon(QIcon::fromTheme("window-close-symbolic"));
    close_btn->setProperty("isWindowButton", 0x2);
    close_btn->setProperty("useIconHighlightEffect", 0x8);
    close_btn->setFlat(true);

    icon_label = new QLabel(this);
    icon_label->setPixmap(QIcon::fromTheme("preferences-system-bluetooth").pixmap(22,22));

    window_Title = new QLabel(tr("Bluetooth File"),this);
    window_Title->setFixedSize(100,20);
    connect(close_btn,&QPushButton::clicked,this,[=]{
        Q_EMIT this->rejected();
        this->close();
    });

    close_btn->setGeometry(480,4,30,30);
    icon_label->setGeometry(8,8,22,22);
    window_Title->setGeometry(36, 9, 100, 20);
    view_btn->setGeometry(390,215,120,36);
    file_source->setGeometry(32,52,460,54);
    file_icon->setGeometry(32,104,64,64);
    file_name->setGeometry(112,111,293,28);
    file_size->setGeometry(112,136,293,20);
    transfer_progress->setGeometry(32,184,454,10);
    cancel_btn->setGeometry(278,215,96,36);
    accept_btn->setGeometry(390,215,96,36);
    warn_icon->setGeometry(32,54,22,22);

    double size = StyleSettings->get("system-font-size").toDouble() - 11;
    QFont ft;
    ft.setPixelSize(18 + size);
    file_source->setFont(ft);
    QString fileSource;
    QFontMetrics fontMetrics(file_source->font());
    QString fileName = fontMetrics.elidedText(target_source, Qt::ElideMiddle, 280);
    fileSource = fontMetrics.elidedText(QString(tr("File from \"")+target_name+tr("\", waiting for receive.")), Qt::ElideMiddle, file_source->width());
    file_source->setText(fileSource);
    file_source->setToolTip(target_name);
    file_name->setText(fileName);
    ft.setPixelSize(14 + size);
    file_name->setFont(ft);
    file_size->setFont(ft);
    window_Title->setFont(ft);
}

void FileReceivingPopupWidget::initIntelLayout() {
    this->setWindowFlags(Qt::Dialog);
    this->setFixedSize(478,280);
    QFont ft;
    ft.setPixelSize(16);
    file_size->setFont(ft);
    file_name->setFont(ft);
    QFontMetrics fontMetrics(file_source->font());
    QString filesource = fontMetrics.elidedText(QString(tr("File from \"")+target_name+tr("\", waiting for receive...")), Qt::ElideMiddle, file_source->width());
    file_source->setText(filesource);
    accept_btn->setGeometry(342,200,112,56);
    cancel_btn->setGeometry(214,200,112,56);
    file_name->setGeometry(104,75,293,23);
    file_size->setGeometry(104,107,293,23);
    view_btn->setGeometry(342,200,120,36);
    file_source->setGeometry(24,24,430,54);
    file_icon->setGeometry(24,71,64,64);
    transfer_progress->setGeometry(24,159,430,8);
    warn_icon->setGeometry(32,34,22,22);
}

void FileReceivingPopupWidget::updateUI(QString name, quint64 size, QString type) {
    if (isError)
        return;
    fileNums += 1;
    qDebug() << Q_FUNC_INFO << name << size << type;
    move_file();
    Q_EMIT continueRecieveFilesRequest();
    QFontMetrics fontMetrics(file_source->font());
    QString fileName = fontMetrics.elidedText(name, Qt::ElideMiddle, 280);
    QString fileSource = QString(tr("File from \"") +
                                 fontMetrics.elidedText(target_name, Qt::ElideMiddle, 240) +
                                 tr("\", is receiving... (has recieved ") +
                                 QString::number(fileNums) +
                                 tr(" files)"));

    QString fileSizeStr;
    if (size != 0) {
        int unitcount = 0;   //将单位B转化为对应的KB、MB等单位
        double calc_size = size;
        while(calc_size >= 1024) {
            calc_size /= 1024;
            unitcount++;
        }
        fileSizeStr = QString::asprintf("%.1f", calc_size) + unitString[unitcount];
    } else {
        fileSizeStr = QString(tr("Greater than 4GB"));
    }
    target_size = size;
    target_type = type;
    target_source = name;
    configuration_transfer_progress_bar(size);

    QIcon fileicon = getFileIconFromType(target_type);
    file_size->setText(fileSizeStr);
    file_icon->setPixmap(fileicon.pixmap(64,64));
    file_name->setText(fileName);
    file_name->setToolTip(name);
    file_source->setWordWrap(true);
    file_source->setText(fileSource);
    file_source->setToolTip(target_name);
    file_source->setGeometry(32,40,460,66);
    this->update();
}

void FileReceivingPopupWidget::configuration_transfer_progress_bar(quint64 value)
{
    transfer_progress->setMinimum(0);
    transfer_progress->setMaximum(value);
    transfer_progress->setValue(0);
}

void FileReceivingPopupWidget::window_pop_up_animation()
{
    qDebug() << Q_FUNC_INFO << desktop << desktop.right() << desktop.bottom() <<this->geometry();

//    QPropertyAnimation *window_action = new QPropertyAnimation(this,"geometry");
//    window_action->setDuration(100);
//    QRect this_rect = this->rect();
//    this_rect.setHeight(0);
//    this_rect.setWidth(0);
//    window_action->setStartValue(QRect(desktop.right()-1,desktop.bottom()-this->height(),desktop.right(),desktop.bottom()));
//    window_action->setEndValue(QRect(desktop.right()-this->width(),desktop.bottom()-this->height(),desktop.right(),desktop.bottom()));
//    window_action->setStartValue(QPoint(desktop.right()-1,desktop.bottom()-this->height()));
//    window_action->setEndValue(QPoint(desktop.right()-this->width(),desktop.bottom()-this->height()));
//    qDebug() << Q_FUNC_INFO << this_rect << this->geometry() << QRect(desktop.right()-1,desktop.bottom()-this->height(),desktop.right(),desktop.bottom()) <<QRect(desktop.right()-this->width(),desktop.bottom()-this->height(),desktop.right(),desktop.bottom());
    //    window_action->start();
}

bool FileReceivingPopupWidget::move_file()
{
    QString s = QDir::homePath()+"/.cache/obexd/"+target_source;
    QString d;


    if(!QFile::exists(file_path)){
        receivedFiles.append(target_source);
        int status;
        status = mkdir(file_path.toStdString().c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
        qDebug() << Q_FUNC_INFO << status;
        if(status == -1)
            return -1;
    }

    QString mDest = "file://" + file_path+"/"+target_source;
    while (FileUtils::isFileExsit(mDest)) {
        QStringList newUrl = mDest.split("/");
        newUrl.pop_back();
        newUrl.append(FileUtils::handleDuplicateName(FileUtils::urlDecode(mDest)));
        mDest = newUrl.join("/");
    }
    target_source = mDest.split("/").back();
    d = file_path+"/"+ target_source;
    receivedFiles.append(target_source);

    GError *error;
    GFile *source = g_file_new_for_path(s.toStdString().c_str());
    GFile *destination = g_file_new_for_path(d.toStdString().c_str());
    bool flag = g_file_move(source,destination,G_FILE_COPY_BACKUP,NULL,NULL,NULL,&error);
    qDebug() << Q_FUNC_INFO << "move file" << "target_path =" << d << " source_path =" << s << "flag =" << flag;
    return flag;
}

void FileReceivingPopupWidget::OnClickedAcceptBtn()
{
    transfer_progress->setVisible(true);
    accept_btn->setVisible(false);

    QParallelAnimationGroup *actions = new QParallelAnimationGroup(this);

    QPropertyAnimation *progress_action = new QPropertyAnimation(transfer_progress,"geometry");
    QRect transfer_progress_rect = transfer_progress->geometry();
    transfer_progress_rect.setWidth(0);
    progress_action->setStartValue(transfer_progress_rect);
    progress_action->setEndValue(transfer_progress->geometry());
    progress_action->setDuration(200);

    actions->addAnimation(progress_action);
    actions->start();
    connect(actions,&QParallelAnimationGroup::finished,this,[=]{
        this->accepted();
    });
}

void FileReceivingPopupWidget::update_transfer_progress_bar(quint64 value, QString path)
{
    if (path != _objectPath || target_size == 0)
        return;
    transfer_progress->setValue(value);
    transfer_progress->repaint();
}

void FileReceivingPopupWidget::transferCompelete() {
    if (!isIntel) {
        close_btn->disconnect();
        close_btn->connect(close_btn,&QPushButton::clicked,this,[=]{
            this->close();
        });
    }
    cancel_btn->setVisible(false);

    bool x = move_file();
    qDebug() << Q_FUNC_INFO << __LINE__ << x;
    if(x){
            QProcess *process = new QProcess(this);
            QString cmd = "peony";
            QStringList arg;
            qDebug() << Q_FUNC_INFO;
            arg <<  "--show-items";
            for (int i = 0; i < receivedFiles.size(); i++)
                 arg << file_path+"/"+receivedFiles.at(i);
            process->startDetached(cmd,arg);
            this->close();
    }
    Q_EMIT clearOldSession();
}

void FileReceivingPopupWidget::file_transfer_completed(QString status, QString dev, QString path)
{
    qDebug() << dev << path << _objectPath;
    if (path != _objectPath || isError)
        return;
    if (isCanceled) {
        this->close();
        this->deleteLater();
        return;
    }
    qDebug() << Q_FUNC_INFO <<status ;
    if(status == QString("Active")){
        if (receiveTimer->isActive()) {
            receiveTimer->stop();
        } else {
            QFontMetrics fontMetrics(file_source->font());
            QString fileSource;
            fileSource = fontMetrics.elidedText(QString(tr("File from \"")+target_name+tr("\", is receiving...")), Qt::ElideMiddle, file_source->width());
            file_source->setText(fileSource);
        }

        QString filePathName = QDir::homePath()+"/.cache/obexd/"+target_source;
        GError *error;
        qDebug() << Q_FUNC_INFO << filePathName;
        GFile *file = g_file_new_for_path(filePathName.toStdString().c_str());
        GFileInfo *file_info = g_file_query_info(file,"*",G_FILE_QUERY_INFO_NONE,NULL,&error);
        qDebug() << Q_FUNC_INFO  << g_file_info_get_size(file_info) << g_file_info_get_content_type(file_info);
        qDebug() << Q_FUNC_INFO << __LINE__;

        QString type = g_file_info_get_content_type(file_info);
        qDebug() << Q_FUNC_INFO << __LINE__;

        QIcon fileicon = getFileIconFromType(type);
        qDebug() << Q_FUNC_INFO << __LINE__;

        file_icon->setPixmap(fileicon.pixmap(64,64));
        this->update();

        cancel_btn->disconnect();
        cancel_btn->connect(cancel_btn,&QPushButton::clicked,this,[=]{
            Q_EMIT this->cancel();
            isCanceled = true;
        });
        if (!isIntel) {
            close_btn->disconnect();
            close_btn->connect(close_btn,&QPushButton::clicked,this,[=]{
                Q_EMIT this->cancel();
                isCanceled = true;
            });
            cancel_btn->setGeometry(390,215,96,36);
        }
        else
            cancel_btn->setGeometry(342,200,112,56);
    }else if(status == QString("Complete")){
        receiveTimer->start(2000);
        qDebug() << Q_FUNC_INFO << __LINE__ ;
    }else if(status == QString("Error")){
        accept_btn->setVisible(true);
        accept_btn->setText(tr("OK"));
        accept_btn->disconnect();
        accept_btn->connect(accept_btn,&QPushButton::clicked,this,[=]{
            this->close();
        });
        if (!isIntel) {
            close_btn->disconnect();
            close_btn->connect(close_btn,&QPushButton::clicked,this,[=]{
                this->close();
            });
        }
        cancel_btn->setVisible(false);
        view_btn->setVisible(false);
        transfer_progress->setVisible(false);
        file_icon->setVisible(false);
        file_name->setVisible(false);
        file_size->setVisible(false);

        file_source->setAlignment(Qt::AlignTop);
        file_source->setGeometry(62,52,430,60);
        QFontMetrics fontMetrics(file_source->font());
        QString fileSource = fontMetrics.elidedText(QString(tr("File from \"")+target_name+tr("\", received failed !")), Qt::ElideMiddle, file_source->width());
        file_source->setText(fileSource);
        warn_icon->setVisible(true);
        if (isIntel) {
            warn_icon->setFixedSize(64,64);
            warn_icon->setPixmap(QPixmap("/usr/share/ukui-bluetooth/file-transfer-failed.svg"));
            file_source->setText(tr("File Transmission Failed !"));
            file_source->setStyleSheet("QLabel{\
                                                font-family: NotoSansCJKsc;\
                                                font-size: 16px;\
                                                line-height: 19px;\
                                                text-align: center;\
                                                color: #FB5050;}");
            warn_icon->setGeometry(207,57,64,64);
            file_source->setGeometry(191,129,200,24);
        }
        this->activateWindow();
        this->show();
        isError = true;
    }
}

void FileReceivingPopupWidget::cancelReceivingFiles() {
    file_transfer_completed(QString("Error"), target_address, _objectPath);
}

void FileReceivingPopupWidget::GSettings_value_chanage(const QString &key)
{
    if(key == "file-save-path"){
        file_path = settings->get("file-save-path").toString();
    }
}

QIcon FileReceivingPopupWidget::getFileIconFromType(QString type) {
    QIcon fileicon;
    if (type.split("/").at(0) == "image"){
        fileicon = QIcon::fromTheme("image");
        if (fileicon.isNull()) {
            fileicon = QIcon::fromTheme("text");
        }
    }else if (type.split("/").at(0) == "video")
        fileicon = QIcon::fromTheme("video-x-generic");
    else if (type.split("/").at(0) == "audio" ||
             type.split("/").at(0) == "application" ||
             type.split("/").at(0) == "text" ||
             type.split("/").at(0) == "inode"){
        if (QIcon::hasThemeIcon(type.split("/").join("-"))) {
            fileicon = QIcon::fromTheme(type.split("/").join("-"));
        } else if (target_source.split(".").size() >= 2){
            if (fileicon.isNull())
                fileicon = QIcon::fromTheme(target_source.split(".").at(1));
            if (fileicon.isNull())
                fileicon = QIcon::fromTheme(QString("application-")+target_source.split(".").at(1));
            if (fileicon.isNull())
                fileicon = QIcon::fromTheme(QString("application-wps-office.")+target_source.split(".").at(1));
        }
    }

    if (fileicon.isNull() && !target_type.isEmpty()){
        QString icon = g_content_type_get_generic_icon_name(target_type.toUtf8().constData());
        fileicon = QIcon::fromTheme(icon);
    }
    if (fileicon.isNull()) {
        fileicon = QIcon::fromTheme("text");
    }
    return fileicon;
}

void FileReceivingPopupWidget::GSettingsChanges(const QString &key)
{
    qDebug() << Q_FUNC_INFO << key;
    if(key == "styleName"){
        QPalette palette;
        if(StyleSettings->get("style-name").toString() != "ukui-dark"){
            palette.setColor(QPalette::Background,QColor(255,255,255));
        }else{
            palette.setColor(QPalette::Background,QColor(0,0,0));
        }
        this->setPalette(palette);
        this->update();
    }
    if (key == "systemFontSize") {
        double size = StyleSettings->get("system-font-size").toDouble() - 11;
        QFont ft;
        ft.setPixelSize(18 + size);
        file_source->setFont(ft);
        QFontMetrics fontMetrics(file_source->font());
        QString fileName = fontMetrics.elidedText(target_source, Qt::ElideMiddle, 280);
        QString fileSource;
        if (!cancel_btn->isVisible()) {
            file_source->setAlignment(Qt::AlignTop);
            file_source->setGeometry(62,52,430,60);
            fileSource = fontMetrics.elidedText(QString(tr("File from \"")+target_name+tr("\", received failed !")), Qt::ElideMiddle, file_source->width());
        } else if (transfer_progress->isVisible()){
            fileSource = fontMetrics.elidedText(QString(tr("File from \"")+target_name+tr("\", is receiving...")), Qt::ElideMiddle, file_source->width());
        } else {
            if (isIntel)
                fileSource = fontMetrics.elidedText(QString(tr("File from \"")+target_name+tr("\", waiting for receive...")), Qt::ElideMiddle, file_source->width());
            else
                fileSource = fontMetrics.elidedText(QString(tr("File from \"")+target_name+tr("\", waiting for receive.")), Qt::ElideMiddle, file_source->width());
        }
        file_source->setText(fileSource);
        file_source->setToolTip(target_name);
        file_name->setText(fileName);
        ft.setPixelSize(14 + size);
        file_name->setFont(ft);
        file_size->setFont(ft);
        window_Title->setFont(ft);
    }
}

void FileReceivingPopupWidget::initTransferPath(QString path, bool isSend) {
    if (isSend)
        return;
    _objectPath = path;
    qDebug() << Q_FUNC_INFO << _objectPath;
}

QPushButton* FileReceivingPopupWidget::getButton() {
    switch (pressCnt) {
    case 1:
        if (!accept_btn->isVisible() || !cancel_btn->isVisible())
            ++pressCnt;
        if(accept_btn->isVisible())
            return accept_btn;
        else if (cancel_btn->isVisible()){
            return cancel_btn;
        }
        return nullptr;
    case 2:
        return cancel_btn;
    case 3:
        return close_btn;
    default:
        return nullptr;
    }
}

void FileReceivingPopupWidget::paintEvent(QPaintEvent *event) {
    QPainter pt(this);
    QColor color = QColor("#818181");
    pt.setPen(color);
    QPushButton *btn = getButton();
    if (btn == nullptr)
        return;
    QRect rect = btn->geometry();
    pt.setRenderHint(QPainter::Antialiasing);
    pt.drawRect(rect);
}

void FileReceivingPopupWidget::keyPressEvent(QKeyEvent *event) {
    QPushButton *bbtn = getButton();
    switch (event->key()) {
    case Qt::Key_Tab:
        qDebug() << "press Tab";
        ++pressCnt;
        if (pressCnt == 4)
            pressCnt = 1;
        this->update();
        break;
    case Qt::Key_Enter:
    case Qt::Key_Return:
        qDebug() << "press Enter";
        if (bbtn == nullptr)
            return;
        bbtn->clicked();
        break;
    case Qt::Key_Escape:
        qDebug() << "press Esc";
        if (pressCnt == 0)
            this->close();
        pressCnt = 0;
        this->update();
        break;
    default:
        break;
    }
}
