#include "mainprogram.h"

MainProgram::MainProgram(bool intel, QObject *parent) :
    QObject(parent),
    _mIntel(intel)
{
    _sessionDbus = new BluetoothDbus(this);
    _mConfig = new Config(this);
    initGSettingInfo();
    UI = TrayWidget::self(_sessionDbus, _mIntel);
    replyTimer = new QTimer(this);
    if (!_mIntel)
        UI->setWidgetPosition();

    //非华为机器才存在文件功能
    if(envPC != Environment::HUAWEI)
    {
        connect(_sessionDbus, &BluetoothDbus::receiveFilesSignal, this, &MainProgram::receiveFileSlot);
        connect(_sessionDbus, &BluetoothDbus::sendTransferDeviceMesgSignal, this, &MainProgram::sendTransferDeviceMesgSlot);
        connect(_sessionDbus, &BluetoothDbus::sendTransferFilesMesgSignal, this, &MainProgram::sendTransferFilesMesgSlot);
        connect(_sessionDbus, &BluetoothDbus::activeConnectionSignal, this, &MainProgram::activeConnectionSlot);
    }

    connect(_sessionDbus, &BluetoothDbus::showTrayWidgetUISignal, this, [=]() {
        UI->showUI();
    });
    connect(_sessionDbus, &BluetoothDbus::displayPasskeySignal, this, &MainProgram::displayPasskeySlot);
    connect(_sessionDbus, &BluetoothDbus::requestConfirmationSignal, this, &MainProgram::requestConfirmationSlot);
    connect(_sessionDbus, &BluetoothDbus::sessionDevPairSignal, this, [=](QString _name, bool paired) {
        Q_UNUSED(_name);
        Q_UNUSED(paired);
       UI->layoutAddOnePairedDev(_name, paired);
    });
    connect(_sessionDbus, &BluetoothDbus::devNameChangedSignal, this, [=]() {
       UI->updatePairedDev();
    });
    connect(_sessionDbus, &BluetoothDbus::devBatteryChangedSignal, this, [=]() {
       UI->updatePairedDev();
    });
}

MainProgram::~MainProgram()
{
}

static qint64 getFileSize(QString filename)
{
    QFileInfo info(filename);
    if (info.exists())
        return info.size();
    else
        return 0;
}

void MainProgram::initGSettingInfo()
{
    _mGsetting.clear();
    _mGsetting["switch"]                     = _mConfig->gsetting->get("switch");
    _mGsetting["finally-connect-the-device"] = _mConfig->gsetting->get("finally-connect-the-device");
    _mGsetting["adapter-address"]            = _mConfig->gsetting->get("adapter-address");
    _mGsetting["file-save-path"]             = _mConfig->gsetting->get("file-save-path");
    _mGsetting["adapter-address-list"]       = _mConfig->gsetting->get("adapter-address-list");

    if(_mConfig->gsetting->get("file-save-path").toString().isEmpty()){
        _mConfig->gsetting->set("file-save-path",QVariant::fromValue(QDir::homePath()));
    }

    connect(_mConfig->gsetting,SIGNAL(changed(QString)),this,SLOT(gsettingsChangedSlot(QString)));
}

void MainProgram::gsettingsChangedSlot(const QString &key)
{
    if (_mGsetting.contains("key")) {
        _mGsetting[key] = _mConfig->gsetting->get(key);
    }
}

void MainProgram::sendFiles(QString address, QString type) {
    _sessionDbus->sendFiles(address, selectedFiles.at(0) + QString("  ") + type);
}

void MainProgram::closeSession() {
    _sessionDbus->closeSession();
}

void MainProgram::receiveFileSlot(QString address, QString devname,
                                  QString filename, QString type,
                                  QString source, quint64 size)
{
    qDebug() << Q_FUNC_INFO << __LINE__;
    receiving_widget = new FileReceivingPopupWidget(address, devname, filename, type, source, size);
    qDebug() << Q_FUNC_INFO << __LINE__;
    connect(_sessionDbus, &BluetoothDbus::initTransferPathSignal, receiving_widget, &FileReceivingPopupWidget::initTransferPath);
    connect(receiving_widget, &FileReceivingPopupWidget::clearOldSession, _sessionDbus, &BluetoothDbus::clearOldSession);
    connect(_sessionDbus, &BluetoothDbus::fileReceiveMore, receiving_widget, &FileReceivingPopupWidget::updateUI);
    connect(_sessionDbus, &BluetoothDbus::obexAgentCanceledSignal, receiving_widget, &FileReceivingPopupWidget::cancelReceivingFiles);

    connect(receiving_widget, &FileReceivingPopupWidget::continueRecieveFilesRequest, this, [=] {
        _sessionDbus->continueRecieveFilesRequest();
    });

    connect(receiving_widget,&FileReceivingPopupWidget::accepted,this,[=]{
        qDebug() << Q_FUNC_INFO <<  __LINE__;
        _sessionDbus->replyFileReceiving(true);
        receiving_widget->configuration_transfer_progress_bar(size);
        connect(_sessionDbus,&BluetoothDbus::transferredChangedSignal,receiving_widget,&FileReceivingPopupWidget::update_transfer_progress_bar);
        connect(_sessionDbus,&BluetoothDbus::statusChangedSignal,receiving_widget,&FileReceivingPopupWidget::file_transfer_completed);
        connect(receiving_widget,&FileReceivingPopupWidget::cancel,this,[=]{
            _sessionDbus->cancelFileReceiving();
            receiving_widget->deleteLater();
            receiving_widget = nullptr;
            qDebug() << Q_FUNC_INFO << "cancel" <<  __LINE__;
        });
    });

    connect(receiving_widget,&FileReceivingPopupWidget::rejected,this,[=]{
        _sessionDbus->replyFileReceiving(false);
        receiving_widget->deleteLater();
        receiving_widget = nullptr;
    });

    kdk::UkuiStyleHelper::self()->removeHeader(receiving_widget);
    receiving_widget->show();
    Config::setKdkGeometry(receiving_widget->windowHandle(),
                   receiving_widget->width(),
                   receiving_widget->height(),
                   false);
}

void MainProgram::sendTransferDeviceMesgSlot(QString address)
{
    selectedFiles.clear();
    KyFileDialog fd;
    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);
        //华为990、9a0需要屏蔽最小系统挂载的目录
        if (fi.fileName() == "2691-6AB8")
             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);
                 //华为990、9a0需要屏蔽最小系统挂载的目录
                  if (fi.fileName() == "2691-6AB8")
                       continue;
                 mntUrlList << QUrl("file://" + fi.filePath());
             }
             fd.setSidebarUrls(list + mntUrlList);
             fd.update();
        });

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

    //自己QFileDialog的用法，这里只是列子
    //fd.setNameFilter(QLatin1String("All Files (*)"));

    fd.setDirectory(QStandardPaths::standardLocations(QStandardPaths::PicturesLocation).at(0));

    //这行要添加，设置左侧导航
    fd.setSidebarUrls(list + mntUrlList);
    fd.show();
    Config::setKdkGeometry(fd.windowHandle(),
                   fd.width(),
                   fd.height(),
                   true);
    if (fd.exec() == QDialog::Accepted) {
        qDebug()<<fd.selectedFiles()<<fd.filter()<<fd.selectedNameFilter() << fd.selectedUrls();
        selectedFiles = fd.selectedFiles();
    }

    if(selectedFiles.size() != 0){
        for (int i = 0; i < selectedFiles.size(); i++) {
            if (getFileSize(selectedFiles.at(i)) == 0) {
                QMessageBox *mbox = new QMessageBox(QMessageBox::Warning,tr("Warning"),tr("The selected file is empty, please select the file again !"),QMessageBox::Ok);
                mbox->show();
                Config::setKdkGeometry(mbox->windowHandle(),
                               mbox->width(),
                               mbox->height(),
                               true);
                mbox->exec();
                return;
            }
        }

        if (BluetoothFileTransferWidget::isShow == false) {
            fileSendWidget = new BluetoothFileTransferWidget(selectedFiles,_sessionDbus->getSendableDevices(),address);
            connect(_sessionDbus, &BluetoothDbus::initTransferPathSignal, fileSendWidget, &BluetoothFileTransferWidget::initTransferPath);
            connect(fileSendWidget,&BluetoothFileTransferWidget::sender_dev_name,this,&MainProgram::sendFiles);
            connect(fileSendWidget,&BluetoothFileTransferWidget::close_the_pre_session,this,&MainProgram::closeSession);
            connect(_sessionDbus,&BluetoothDbus::transferredChangedSignal,fileSendWidget,&BluetoothFileTransferWidget::set_m_progressbar_value);
            connect(_sessionDbus,&BluetoothDbus::statusChangedSignal,fileSendWidget,&BluetoothFileTransferWidget::get_transfer_status);
            connect(fileSendWidget,&BluetoothFileTransferWidget::continueSendFiles,_sessionDbus,&BluetoothDbus::continueSendFiles);
            kdk::UkuiStyleHelper::self()->removeHeader(fileSendWidget);
            fileSendWidget->show();
            Config::setKdkGeometry(fileSendWidget->windowHandle(), fileSendWidget->width(), fileSendWidget->height(), true);
        }
        else
        {
            qDebug() << Q_FUNC_INFO << fileSendWidget->get_send_data_state() << __LINE__;

            if (BluetoothFileTransferWidget::_SEND_FAILURE == fileSendWidget->get_send_data_state()   ||
                BluetoothFileTransferWidget::_SEND_COMPLETE == fileSendWidget->get_send_data_state()  )
            {
                _sessionDbus->closeSession();
                fileSendWidget->close();
                delete fileSendWidget;
                fileSendWidget = new BluetoothFileTransferWidget(selectedFiles,_sessionDbus->getSendableDevices(),address);
                connect(_sessionDbus, &BluetoothDbus::initTransferPathSignal, fileSendWidget, &BluetoothFileTransferWidget::initTransferPath);
                connect(fileSendWidget,&BluetoothFileTransferWidget::sender_dev_name,this,&MainProgram::sendFiles);
                connect(fileSendWidget,&BluetoothFileTransferWidget::close_the_pre_session,this,&MainProgram::closeSession);
                connect(_sessionDbus,&BluetoothDbus::transferredChangedSignal,fileSendWidget,&BluetoothFileTransferWidget::set_m_progressbar_value);
                connect(_sessionDbus,&BluetoothDbus::statusChangedSignal,fileSendWidget,&BluetoothFileTransferWidget::get_transfer_status);
                connect(fileSendWidget,&BluetoothFileTransferWidget::continueSendFiles,_sessionDbus,&BluetoothDbus::continueSendFiles);
                kdk::UkuiStyleHelper::self()->removeHeader(fileSendWidget);
                fileSendWidget->show();
                Config::setKdkGeometry(fileSendWidget->windowHandle(), fileSendWidget->width(), fileSendWidget->height(), true);
            } else {
                fileSendWidget->insertNewFileList(selectedFiles);
            }
        }
    }
}

void MainProgram::sendTransferFilesMesgSlot(QStringList targetList)
{
    qDebug() << "Select file:" << targetList;
    //selectedFiles = targetList;
    selectedFiles.clear();
    for (int i = 0 ; i < targetList.size() ; i++)
    {
        QString str = targetList.at(i);
        str = str.replace(QString("file://"), QString(""));
        selectedFiles.append(str);
    }
    qDebug() << "Select file:" << selectedFiles;
    if(selectedFiles.size() != 0){
        if (BluetoothFileTransferWidget::isShow == false) {
            fileSendWidget = new BluetoothFileTransferWidget(selectedFiles,_sessionDbus->getSendableDevices(),"");
            connect(_sessionDbus, &BluetoothDbus::initTransferPathSignal, fileSendWidget, &BluetoothFileTransferWidget::initTransferPath);
            connect(fileSendWidget,&BluetoothFileTransferWidget::sender_dev_name,this,&MainProgram::sendFiles);
            connect(fileSendWidget,&BluetoothFileTransferWidget::close_the_pre_session,this,&MainProgram::closeSession);
            connect(_sessionDbus,&BluetoothDbus::transferredChangedSignal,fileSendWidget,&BluetoothFileTransferWidget::set_m_progressbar_value);
            connect(_sessionDbus,&BluetoothDbus::statusChangedSignal,fileSendWidget,&BluetoothFileTransferWidget::get_transfer_status);
            connect(fileSendWidget,&BluetoothFileTransferWidget::continueSendFiles,_sessionDbus,&BluetoothDbus::continueSendFiles);
            kdk::UkuiStyleHelper::self()->removeHeader(fileSendWidget);
            fileSendWidget->show();
            Config::setKdkGeometry(fileSendWidget->windowHandle(), fileSendWidget->width(), fileSendWidget->height(), true);
        }
        else
        {
            if (BluetoothFileTransferWidget::_SEND_FAILURE == fileSendWidget->get_send_data_state()   ||
                BluetoothFileTransferWidget::_SEND_COMPLETE == fileSendWidget->get_send_data_state()  )
            {
                _sessionDbus->closeSession();
                fileSendWidget->close();
                delete fileSendWidget;
                fileSendWidget = new BluetoothFileTransferWidget(selectedFiles,_sessionDbus->getSendableDevices(),"");
                connect(_sessionDbus, &BluetoothDbus::initTransferPathSignal, fileSendWidget, &BluetoothFileTransferWidget::initTransferPath);
                connect(fileSendWidget,&BluetoothFileTransferWidget::sender_dev_name,this,&MainProgram::sendFiles);
                connect(fileSendWidget,&BluetoothFileTransferWidget::close_the_pre_session,this,&MainProgram::closeSession);
                connect(_sessionDbus,&BluetoothDbus::transferredChangedSignal,fileSendWidget,&BluetoothFileTransferWidget::set_m_progressbar_value);
                connect(_sessionDbus,&BluetoothDbus::statusChangedSignal,fileSendWidget,&BluetoothFileTransferWidget::get_transfer_status);
                connect(fileSendWidget,&BluetoothFileTransferWidget::continueSendFiles,_sessionDbus,&BluetoothDbus::continueSendFiles);
                kdk::UkuiStyleHelper::self()->removeHeader(fileSendWidget);
                fileSendWidget->show();
                Config::setKdkGeometry(fileSendWidget->windowHandle(), fileSendWidget->width(), fileSendWidget->height(), true);
            } else {
                fileSendWidget->insertNewFileList(selectedFiles);
            }
        }
    }
}

void MainProgram::displayPasskeySlot(QString name, QString passkey)
{
    qDebug() << Q_FUNC_INFO << name << passkey;
    if(m_Passkey == passkey)
        return;

    if(Keypincodewidget != nullptr){
        if (Keypincodewidget) {
            Keypincodewidget->updateUIInfo(name,passkey);
            return;
        }
    }

    Keypincodewidget = new PinCodeWidget(name,passkey,false);
    connect(Keypincodewidget, &PinCodeWidget::msgShowedOver, this, [=] {
       Keypincodewidget->deleteLater();
       Keypincodewidget = nullptr;
    });

    disconnect(_sessionDbus, &BluetoothDbus::pairAgentCanceledSignal, nullptr, nullptr);

    connect(_sessionDbus, &BluetoothDbus::pairAgentCanceledSignal, this, [=]() {
        if(nullptr != Keypincodewidget)
            Keypincodewidget->pairFailureShow();
        disconnect(_sessionDbus, &BluetoothDbus::pairAgentCanceledSignal, nullptr, nullptr);
    });
    connect(_sessionDbus, &BluetoothDbus::sessionDevPairSignal, Keypincodewidget, [=](QString _name, bool paired){
        qDebug() << Q_FUNC_INFO << __LINE__;
        if (name != _name || nullptr == Keypincodewidget)
            return;
        if (paired)
        {
            Keypincodewidget->setHidden(true);
            emit Keypincodewidget->msgShowedOver();
        }
    });
    //保持在最前
    kdk::UkuiStyleHelper::self()->removeHeader(Keypincodewidget);
    Keypincodewidget->show();
    Keypincodewidget->activateWindow();
    Config::setKdkGeometry(Keypincodewidget->windowHandle(),
                   Keypincodewidget->width(),
                   Keypincodewidget->height(),
                   true);
}

void MainProgram::requestConfirmationSlot(QString name, QString passkey)
{
    qDebug() << Q_FUNC_INFO << name << passkey;

    if(pincodewidget != nullptr){
        qDebug() << Q_FUNC_INFO << __LINE__;
        return;
    }
    m_Passkey = passkey;
    pincodewidget = new PinCodeWidget(name,passkey);
    connect(pincodewidget, &PinCodeWidget::msgShowedOver, this, [=] {
        if (pincodewidget != nullptr) {
            qDebug() << Q_FUNC_INFO << __LINE__;
            pincodewidget->deleteLater();
            pincodewidget = nullptr;
       }
    });
    connect(_sessionDbus, &BluetoothDbus::pairAgentCanceledSignal, this, [=]() {
        qDebug() << Q_FUNC_INFO << __LINE__;
        if (pincodewidget != nullptr) {
            if (pincodewidget->canceled)
                return;
            pincodewidget->canceled =  true;
            pincodewidget->pairFailureShow();
            pincodewidget = nullptr;
        }
    });

    connect(pincodewidget,&PinCodeWidget::accepted,this,[=]{
        _sessionDbus->replyRequestConfirmation(true);
    });

    connect(pincodewidget,&PinCodeWidget::rejected,this,[=]{
        _sessionDbus->replyRequestConfirmation(false);
    });
    connect(pincodewidget, &PinCodeWidget::destroyed, this, [=] {
        pincodewidget = nullptr;
    });

    //保持在最前
    kdk::UkuiStyleHelper::self()->removeHeader(pincodewidget);
    pincodewidget->show();
    pincodewidget->activateWindow();
    Config::setKdkGeometry(pincodewidget->windowHandle(),
                   pincodewidget->width(),
                   pincodewidget->height(),
                   true);
}

void MainProgram::activeConnectionSlot(QString address, QString name, QString type, int rssi, int timeout) {
    if (activeConnectionWidget != nullptr)
        return;
    activeConnectionWidget = new ActiveConnectionWidget(address, name, type, rssi);
    connect(activeConnectionWidget, &ActiveConnectionWidget::replyActiveConnection, this, [=](QString dev, bool v) {
        if (replyTimer->isActive())
            replyTimer->stop();
        _sessionDbus->activeConnectionReply(dev, v);
        disconnect(activeConnectionWidget, &ActiveConnectionWidget::replyActiveConnection, NULL, NULL);
        activeConnectionWidget = nullptr;
    });

    replyTimer->disconnect();
    connect(replyTimer, &QTimer::timeout, this, [=](){
        if (nullptr == activeConnectionWidget)
            return;
        disconnect(activeConnectionWidget, &ActiveConnectionWidget::replyActiveConnection, NULL, NULL);
        activeConnectionWidget->hide();
        activeConnectionWidget->deleteLater();
        activeConnectionWidget = nullptr;
    });

    kdk::UkuiStyleHelper::self()->removeHeader(activeConnectionWidget);
    activeConnectionWidget->show();
    Config::setKdkGeometry(activeConnectionWidget->windowHandle(),
                   activeConnectionWidget->width(),
                   activeConnectionWidget->height(),
                   false);
    replyTimer->start(timeout * 1000);
}
