/**************************************************************************
** Piperka Client
** Copyright (C) 2019  Kari Pahula
**
** 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 2 of the License, 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, write to the Free Software Foundation, Inc.,
** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
**************************************************************************/

#include <QtNetwork/QNetworkReply>
#include <QtQml/QQmlContext>

#include "application.h"
#include "passwordvalidator.h"

Application::Application(QQmlContext *ctxt, QObject *parent)
    : QObject(parent)
    , m_user(m_download)
    , m_browse(m_sortManager)
    , m_updates(m_sortManager)
    , m_page(m_updates, m_user)
{
    qmlRegisterType<PasswordValidator>("net.piperka", 0, 1, "PasswordValidator");

    m_browse.setSource(&m_comics);
    m_updates.setSource(&m_comics);
    m_recommend.setSource(&m_comics);

    ctxt->setContextProperty("comicModel", &m_comics);
    ctxt->setContextProperty("browseModel", &m_browse);
    ctxt->setContextProperty("pageModel", &m_page);
    ctxt->setContextProperty("updatesModel", &m_updates);
    ctxt->setContextProperty("recommendModel", &m_recommend);
    ctxt->setContextProperty("user", &m_user);

    connect(&m_download, &Download::downloadSortComplete,
            &m_sortManager, &SortManager::sortDownloaded);

    // Make sure to reset updates stats after logout
    connect(&m_user, &User::loggedOut,
            &m_updates, &UpdatesModel::loggedOut);
    connect(&m_user, &User::loggedOut,
            &m_download, &Download::forgetUser);

    // Connect subscription events
    connect(&m_user, &User::newSubscription,
            &m_comics, &ComicModel::newSubscription);
    connect(&m_user, &User::refreshSubscription,
            &m_comics, &ComicModel::refreshSubscription);
    connect(&m_user, &User::newSubscription,
            &m_page, &PageModel::setSubscription);
    connect(&m_user, &User::subscriptionChange,
            &m_updates, &UpdatesModel::subscriptionChange);

    // Synchronize
    connect(&m_user, &User::synchronize,
            &m_comics, &ComicModel::downloadComicsListPrepare);
    connect(&m_user, &User::fetchSubscriptionsEnd,
            &m_comics, &ComicModel::pendingSubscriptionsComplete);

    // Comics list download
    connect(&m_comics, &ComicModel::downloadComicsListPrepare,
            &m_user, &User::networkActionBegin);
    connect(&m_download, &Download::downloadComicsListComplete,
            &m_user, &User::networkActionEnd);
    connect(&m_download, &Download::downloadComicsListUnchanged,
            &m_user, &User::networkActionEnd);
    connect(&m_comics, &ComicModel::downloadComicsListPrepare,
            &m_download, &Download::downloadComicsList);
    connect(&m_download, &Download::downloadComicsListComplete,
            &m_comics, &ComicModel::downloadComicsListComplete);
    connect(&m_download, &Download::downloadComicsListUnchanged,
            &m_comics, &ComicModel::downloadComicsListUnchanged);
    connect(&m_download, &Download::downloadComicsListError,
            &m_user, &User::syncError);

    // Browse page sort type loads
    connect(&m_browse, &BrowseModel::sortTypeChangePrepare,
            &m_user, &User::networkActionBegin);
    connect(&m_browse, &BrowseModel::sortTypeChanged,
            &m_user, &User::networkActionEnd);
    connect(&m_browse, &BrowseModel::sortTypeChangePrepare,
            &m_download, &Download::downloadSort);
    connect(&m_download, &Download::downloadSortComplete,
            &m_browse, &BrowseModel::sortDownloaded);

    // Updates page sort type loads
    connect(&m_updates, &UpdatesModel::sortTypeChangePrepare,
            &m_user, &User::networkActionBegin);
    connect(&m_updates, &UpdatesModel::sortTypeChanged,
            &m_user, &User::networkActionEnd);
    connect(&m_updates, &UpdatesModel::sortTypeChangePrepare,
            &m_download, &Download::downloadSort);
    connect(&m_download, &Download::downloadSortComplete,
            &m_updates, &UpdatesModel::sortDownloaded);

    // Page page page list loads
    connect(&m_page, &PageModel::loadPages,
            &m_download, &Download::downloadPages);
    connect(&m_download, &Download::downloadPagesComplete,
            &m_page, &PageModel::loadPagesComplete);
    connect(&m_page, &PageModel::loadPages, this,
            [=](){m_user.networkActionBegin();});
    connect(&m_download, &Download::downloadPagesComplete, this,
            [=](){m_user.networkActionEnd();});
    connect(&m_page, &PageModel::pagesLoaded,
            &m_user, &User::setCursor);

    // Recommend list loads
    connect(&m_recommend, &RecommendModel::loadRecommend,
            &m_download, &Download::downloadRecommend);
    connect(&m_download, &Download::downloadRecommendComplete,
            &m_recommend, &RecommendModel::loadRecommendComplete);
    connect(&m_recommend, &RecommendModel::loadRecommend, this,
            [=](){m_user.networkActionBegin();});
    connect(&m_download, &Download::downloadRecommendComplete, this,
            [=](){m_user.networkActionEnd();});

    // Errors for sort and page list downloads
    connect(&m_download, &Download::downloadSortError,
            &m_user, &User::genericNetworkError);
    connect(&m_download, &Download::downloadPagesError,
            &m_user, &User::genericNetworkError);
    connect(&m_download, &Download::downloadRecommendError,
            &m_user, &User::genericNetworkError);

    m_user.syncNow(true);
}

void Application::viewComplete()
{
    m_user.emitIfLoggedin();
}
