/*
  Copyright (c) 2013-2016 Montel Laurent <montel@kde.org>

  This library is free software; you can redistribute it and/or modify it
  under the terms of the GNU Library General Public License as published by
  the Free Software Foundation; either version 2 of the License, or (at your
  option) any later version.

  This library 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 Library General Public
  License for more details.

  You should have received a copy of the GNU Library General Public License
  along with this library; see the file COPYING.LIB.  If not, write to the
  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  02110-1301, USA.

*/

#include "storageservicemanagermainwindow.h"
#include "storageservicetabwidget.h"
#include "storageserviceconfiguredialog.h"
#include "storageservicemanagermainwidget.h"
#include "storageservicemanagersettingsjob.h"
#include "storageservicemanagerglobalconfig.h"
#include "PimCommon/StorageServiceManager"
#include "PimCommon/StorageServiceProgressManager"
#include "PimCommon/StorageServiceJobConfig"
#include "PimCommon/StorageServiceAbstract"

#include "PimCommon/StorageServiceSettings"

#include <Libkdepim/ProgressStatusBarWidget>
#include <Libkdepim/StatusbarProgressWidget>

#include <KStandardAction>
#include <KLocalizedString>
#include <KActionCollection>
#include <KConfigGroup>
#include <QStatusBar>
#include <KMessageBox>
#include <knotifyconfigwidget.h>

#include <QPointer>
#include <QCloseEvent>
#include <QLabel>
#include "storageservicemanager_debug.h"
#include <KSharedConfig>
#include <QAction>
#include <QNetworkConfigurationManager>

StorageServiceManagerMainWindow::StorageServiceManagerMainWindow()
    : KXmlGuiWindow()
{
    StorageServiceManagerSettingsJob *settingsJob = new StorageServiceManagerSettingsJob;
    PimCommon::StorageServiceJobConfig *configJob = PimCommon::StorageServiceJobConfig::self();
    configJob->registerConfigIf(settingsJob);

    mStorageManager = new PimCommon::StorageServiceManager(this);
    connect(mStorageManager, &PimCommon::StorageServiceManager::servicesChanged, this, &StorageServiceManagerMainWindow::slotServicesChanged);
    mStorageServiceMainWidget = new StorageServiceManagerMainWidget;
    connect(mStorageServiceMainWidget, &StorageServiceManagerMainWidget::configureClicked, this, &StorageServiceManagerMainWindow::slotConfigure);
    connect(mStorageServiceMainWidget->storageServiceTabWidget(), &QTabWidget::currentChanged, this, &StorageServiceManagerMainWindow::slotUpdateActions);
    connect(mStorageServiceMainWidget->storageServiceTabWidget(), &StorageServiceTabWidget::updateStatusBarMessage, this, &StorageServiceManagerMainWindow::slotSetStatusBarMessage);
    connect(mStorageServiceMainWidget->storageServiceTabWidget(), &StorageServiceTabWidget::listFileWasInitialized, this, &StorageServiceManagerMainWindow::slotUpdateActions);
    connect(mStorageServiceMainWidget->storageServiceTabWidget(), &StorageServiceTabWidget::selectionChanged, this, &StorageServiceManagerMainWindow::slotUpdateActions);
    setCentralWidget(mStorageServiceMainWidget);

    mNetworkConfigurationManager = new QNetworkConfigurationManager();
    connect(mNetworkConfigurationManager, &QNetworkConfigurationManager::onlineStateChanged, this, &StorageServiceManagerMainWindow::slotSystemNetworkOnlineStateChanged);

    setupActions();
    setupGUI(Keys | StatusBar | Save | Create);
    readConfig();
    mStorageServiceMainWidget->storageServiceTabWidget()->setListStorageService(mStorageManager->listService());
    slotUpdateActions();
    initStatusBar();
    slotSystemNetworkOnlineStateChanged(mNetworkConfigurationManager->isOnline());
}

StorageServiceManagerMainWindow::~StorageServiceManagerMainWindow()
{
    delete mStorageServiceMainWidget;
    KSharedConfig::Ptr config = KSharedConfig::openConfig();

    KConfigGroup group = config->group(QStringLiteral("StorageServiceManagerMainWindow"));
    group.writeEntry("Size", size());
    qCDebug(STORAGESERVICEMANAGER_LOG) << " StorageServiceManagerMainWindow::~StorageServiceManagerMainWindow()";
    if (StorageServiceManagerGlobalConfig::self()->closeWallet()) {
        PimCommon::StorageServiceSettings::self()->closeWallet();
    }
    delete mNetworkConfigurationManager;
}

void StorageServiceManagerMainWindow::slotServicesChanged()
{
    mStorageServiceMainWidget->storageServiceTabWidget()->updateListService(mStorageManager->listService());
}

void StorageServiceManagerMainWindow::initStatusBar()
{
    mStatusBarInfo = new QLabel;
    statusBar()->insertWidget(0, mStatusBarInfo, 4);
    KPIM::ProgressStatusBarWidget *progressBar = new KPIM::ProgressStatusBarWidget(statusBar(), this, PimCommon::StorageServiceProgressManager::progressTypeValue());
    statusBar()->addPermanentWidget(progressBar->littleProgress(), 0);
}

void StorageServiceManagerMainWindow::slotSystemNetworkOnlineStateChanged(bool state)
{
    if (state) {
        mStorageServiceMainWidget->storageServiceTabWidget()->setNetworkIsDown(false);
        slotSetStatusBarMessage(i18n("Network connection is up."));
    } else {
        mStorageServiceMainWidget->storageServiceTabWidget()->setNetworkIsDown(true);
        slotSetStatusBarMessage(i18n("Network connection is down."));
    }
    slotUpdateActions();
}

void StorageServiceManagerMainWindow::slotUpdateActions()
{
    if (!mNetworkConfigurationManager->isOnline()) {
        mDownloadFile->setDisabled(true);
        mCreateFolder->setDisabled(true);
        mAccountInfo->setDisabled(true);
        mUploadFile->setDisabled(true);
        mDelete->setDisabled(true);
        mAuthenticate->setDisabled(true);
        mRefreshList->setDisabled(true);
        mShowLog->setDisabled(true);
        mRenameItem->setDisabled(true);
        mRefreshAll->setDisabled(true);
        mShutdownAllServices->setDisabled(true);
    } else {
        const PimCommon::StorageServiceAbstract::Capabilities capabilities = mStorageServiceMainWidget->storageServiceTabWidget()->capabilities();
        const bool listFolderWasLoaded = mStorageServiceMainWidget->storageServiceTabWidget()->listFolderWasLoaded();
        PimCommon::StorageServiceTreeWidget::ItemType type = mStorageServiceMainWidget->storageServiceTabWidget()->itemTypeSelected();
        mDownloadFile->setEnabled(listFolderWasLoaded && (capabilities & PimCommon::StorageServiceAbstract::DownloadFileCapability) && (type == PimCommon::StorageServiceTreeWidget::File));
        mCreateFolder->setEnabled(listFolderWasLoaded && (capabilities & PimCommon::StorageServiceAbstract::CreateFolderCapability));
        mAccountInfo->setEnabled(capabilities & PimCommon::StorageServiceAbstract::AccountInfoCapability);
        mUploadFile->setEnabled(capabilities & PimCommon::StorageServiceAbstract::UploadFileCapability);
        mDelete->setEnabled(listFolderWasLoaded && (capabilities & PimCommon::StorageServiceAbstract::DeleteFileCapability) &&
                            (type == PimCommon::StorageServiceTreeWidget::File || type == PimCommon::StorageServiceTreeWidget::Folder));
        mAuthenticate->setDisabled((capabilities & PimCommon::StorageServiceAbstract::NoCapability) || (mStorageServiceMainWidget->storageServiceTabWidget()->count() == 0));
        mRefreshList->setDisabled((capabilities & PimCommon::StorageServiceAbstract::NoCapability) || (mStorageServiceMainWidget->storageServiceTabWidget()->count() == 0));
        mRenameItem->setEnabled(listFolderWasLoaded && (capabilities & PimCommon::StorageServiceAbstract::RenameFileCapabilitity || capabilities & PimCommon::StorageServiceAbstract::RenameFolderCapability) &&
                                (type == PimCommon::StorageServiceTreeWidget::File || type == PimCommon::StorageServiceTreeWidget::Folder));

        const bool disabled = (mStorageServiceMainWidget->storageServiceTabWidget()->count() == 0);
        mShowLog->setDisabled(disabled);
        mRefreshAll->setDisabled(disabled);
        mShutdownAllServices->setDisabled(disabled);
        mLogout->setEnabled(listFolderWasLoaded);
    }
}

void StorageServiceManagerMainWindow::setupActions()
{
    KActionCollection *ac = actionCollection();
    KStandardAction::quit(this, &StorageServiceManagerMainWindow::close, ac);

    mAuthenticate = ac->addAction(QStringLiteral("authenticate"), mStorageServiceMainWidget->storageServiceTabWidget(), SLOT(slotAuthenticate()));
    mAuthenticate->setText(i18n("Authenticate..."));

    mCreateFolder = ac->addAction(QStringLiteral("create_folder"), mStorageServiceMainWidget->storageServiceTabWidget(), SLOT(slotCreateFolder()));
    mCreateFolder->setText(i18n("Create Folder..."));
    mCreateFolder->setIcon(QIcon::fromTheme(QStringLiteral("folder-new")));

    mRefreshList = ac->addAction(QStringLiteral("refresh_list"), mStorageServiceMainWidget->storageServiceTabWidget(), SLOT(slotRefreshList()));
    mRefreshList->setText(i18n("Refresh List"));
    mRefreshList->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh")));
    ac->setDefaultShortcut(mRefreshList, QKeySequence(Qt::Key_F5));

    mAccountInfo = ac->addAction(QStringLiteral("account_info"), mStorageServiceMainWidget->storageServiceTabWidget(), SLOT(slotAccountInfo()));
    mAccountInfo->setText(i18n("Account Info..."));

    mUploadFile = ac->addAction(QStringLiteral("upload_file"), mStorageServiceMainWidget->storageServiceTabWidget(), SLOT(slotUploadFile()));
    mUploadFile->setText(i18n("Upload File..."));

    mDelete = ac->addAction(QStringLiteral("delete"), mStorageServiceMainWidget->storageServiceTabWidget(), SLOT(slotDelete()));
    ac->setDefaultShortcut(mDelete, QKeySequence(Qt::Key_Delete));
    mDelete->setText(i18n("Delete..."));
    mDelete->setIcon(QIcon::fromTheme(QStringLiteral("edit-delete")));

    mDownloadFile = ac->addAction(QStringLiteral("download_file"), mStorageServiceMainWidget->storageServiceTabWidget(), SLOT(slotDownloadFile()));
    mDownloadFile->setText(i18n("Download File..."));
    mDownloadFile->setIcon(QIcon::fromTheme(QStringLiteral("download")));

    mShowLog = ac->addAction(QStringLiteral("show_log"), mStorageServiceMainWidget->storageServiceTabWidget(), SLOT(slotShowLog()));
    mShowLog->setText(i18n("Show Log..."));

    mLogout = ac->addAction(QStringLiteral("logout"), this, SLOT(slotLogout()));
    mLogout->setText(i18n("Logout"));

    mShutdownAllServices = ac->addAction(QStringLiteral("shutdown_all_services"), this, SLOT(slotShutdownAllServices()));
    mShutdownAllServices->setText(i18n("Shutdown All Services"));

    mRefreshAll = ac->addAction(QStringLiteral("refresh_all"), this, SLOT(slotRefreshAll()));
    mRefreshAll->setText(i18n("Refresh All"));
    ac->setDefaultShortcut(mRefreshAll, QKeySequence(Qt::CTRL + Qt::Key_F5));

    mRenameItem = ac->addAction(QStringLiteral("rename"), mStorageServiceMainWidget->storageServiceTabWidget(), SLOT(slotRename()));
    mRenameItem->setText(i18n("Rename..."));
    ac->setDefaultShortcut(mRenameItem, QKeySequence(Qt::Key_F2));

    KStandardAction::preferences(this, &StorageServiceManagerMainWindow::slotConfigure, ac);
    KStandardAction::configureNotifications(this, &StorageServiceManagerMainWindow::slotShowNotificationOptions, ac); // options_configure_notifications
}

void StorageServiceManagerMainWindow::slotShowNotificationOptions()
{
    KNotifyConfigWidget::configure(this);
}

void StorageServiceManagerMainWindow::slotLogout()
{
    mStorageServiceMainWidget->storageServiceTabWidget()->logout();
    slotUpdateActions();
}

void StorageServiceManagerMainWindow::closeEvent(QCloseEvent *e)
{
    if (mStorageServiceMainWidget->storageServiceTabWidget()->hasUploadDownloadProgress()) {
        if (KMessageBox::No == KMessageBox::warningYesNo(this, i18n("There is still upload or download in progress. Do you want to close anyway?"))) {
            e->ignore();
            return;
        }
    }
    e->accept();
}

void StorageServiceManagerMainWindow::slotConfigure()
{
    QPointer<StorageServiceConfigureDialog> dlg = new StorageServiceConfigureDialog(this);
    connect(dlg.data(), &StorageServiceConfigureDialog::serviceRemoved, this, &StorageServiceManagerMainWindow::slotServiceRemoved);
    dlg->setListService(mStorageManager->listService());
    if (dlg->exec()) {
        mStorageManager->setListService(dlg->listService());
        mStorageServiceMainWidget->storageServiceTabWidget()->updateListService(dlg->listService());
        dlg->writeSettings();
    }
    delete dlg;
}

void StorageServiceManagerMainWindow::slotServiceRemoved(const QString &serviceName)
{
    mStorageServiceMainWidget->storageServiceTabWidget()->serviceRemoved(serviceName);
    mStorageManager->removeService(serviceName);
}

void StorageServiceManagerMainWindow::readConfig()
{
    KSharedConfig::Ptr config = KSharedConfig::openConfig();
    KConfigGroup group = KConfigGroup(config, "StorageServiceManagerMainWindow");
    const QSize sizeDialog = group.readEntry("Size", QSize(800, 600));
    if (sizeDialog.isValid()) {
        resize(sizeDialog);
    }
}

void StorageServiceManagerMainWindow::slotSetStatusBarMessage(const QString &message)
{
    mStatusBarInfo->setText(message);
}

void StorageServiceManagerMainWindow::slotShutdownAllServices()
{
    mStorageServiceMainWidget->storageServiceTabWidget()->shutdownAllServices();
    slotUpdateActions();
}

void StorageServiceManagerMainWindow::slotRefreshAll()
{
    mStorageServiceMainWidget->storageServiceTabWidget()->refreshAll();
    slotUpdateActions();
}
