/****************************************************************************
**
** Copyright (C) 2012 Róbert Márki
**
** This file is part of Web Feeds.
**
** Web Feeds 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 3 of the License, or
** (at your option) any later version.
**
** Web Feeds 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 Web Feeds.  If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/

#ifndef NEWSBLURCLIENT_H
#define NEWSBLURCLIENT_H
#include <QObject>
#include <QSize>
#include <QNetworkAccessManager>
#include <QUrl>
#include "updatetreereply.h"
#include "storylistreply.h"
#include "feedstorylistreply.h"
#include "feedsearchresultsreply.h"
#include "unreadcountsreply.h"
#include "feedclassifiersreply.h"
#include <QAuthenticator>
#include "newsbluritem.h"
#include "feedclassifiers.h"
#include "savefeedclassifiersreply.h"
#include "markstoriesreadreply.h"
#include "webserviceclient.h"
#include "pageitem.h"

namespace NewsBlur
{
class StoryItem;
class NewsBlurClient : public WebServiceClient
{
    Q_OBJECT
public:
    enum RequestType
    {
        TpUnknown,
        TpUpdateTree,
        TpLoadNewFeedStories,
        TpLoadMoreFeedStories,
        TpMarkStoryRead,
        TpMarkStoriesRead,
        TpMarkStoryUnread,
        TpRefreshUnreadCounts,
        TpVerifyAccount,
        TpLoadMoreStarredStories,
        TpLoadNewStarredStories,
        TpSaveStory,
        TpUnsaveStory,
        TpMarkFeedRead,
        TpMarkFolderRead,
        TpMarkEverythingRead,
        TpRenameFeed,
        TpRenameFolder,
        TpDeleteFeed,
        TpDeleteFolder,
        TpMoveFeed,
        TpMoveFolder,
        TpAddFeed,
        TpAddFolder,
        TpFindFeed,
        TpLoadMoreRiverStories,
        TpUpdateRiverStories,
        TpFeedClassifiers,
        TpSaveClassifiers
    };
    NewsBlurClient(QObject* parent = 0);
    QSize preferredFaviconSize() const;
    void setPreferredFaviconSize(const QSize &size);

    UpdateTreeReplyPtr updateTree(const QStringList &faviconsToIgnore);
    FeedStoryListReplyPtr loadFeedStories(int feedId, int highestLoadedPage,
                                          bool shouldLoadClassifiers, const QStringList &childIdsToIgnore,                                          
                                          NewsBlurEnum::ClassificationFilter filter = NewsBlurEnum::CfNoFilter,
                                          int preferredStoryCount = 0);
    FeedStoryListReplyPtr loadNewFeedStories(int feedId, const QStringList &childIdsToIgnore);
    StoryListReplyPtr loadRiverStories(int highestLoadedPage,
                                       const QStringList &childIdsToIgnore, const QList<int> &feedIds,
                                       NewsBlurEnum::ClassificationFilter filter = NewsBlurEnum::CfNoFilter,
                                       int preferredStoryCount = 0);
    StoryListReplyPtr loadNewRiverStories(const QStringList &childIdsToIgnore, const QList<int>& feedIds,
                                          const QDateTime& latestStoryDate);
    StoryListReplyPtr loadStarredStories(int highestLoadedPage, const QStringList &childIdsToIgnore);
    StoryListReplyPtr loadNewStarredStories(const QStringList &childIdsToIgnore);
    WebServiceReplyPtr markStoryAsRead(int feedId, const QString& storyId);
    MarkStoriesReadReplyPtr markStoriesAsRead(const QHash<int, QStringList> storyIds);
    WebServiceReplyPtr markStoryAsUnread(int feedId, const QString& storyId);
    WebServiceReplyPtr saveStory(int feedId, const QString& storyId);
    WebServiceReplyPtr unSaveStory(const QString& storyId);
    WebServiceReplyPtr markFeedAsRead(int feedId);
    WebServiceReplyPtr markFolderAsRead(const QList<int>& feedIds);
    WebServiceReplyPtr markEverythingAsRead();
    WebServiceReplyPtr renameFeed(int feedId, const QString& name);
    WebServiceReplyPtr renameFolder(const QString parentFolder, const QString& folderName, const QString newFolderName);
    WebServiceReplyPtr deleteFeed(int feedId, const QString& parentFolder);
    WebServiceReplyPtr deleteFolder(const QString& folderName, const QString& parentFolder);
    WebServiceReplyPtr moveFeed(int feedId, const QString& parentFolder, const QString& newParentFolder);
    WebServiceReplyPtr moveFolder(const QString& folderName, const QString& parentFolder, const QString& newParentFolder);
    WebServiceReplyPtr addFeed(const QUrl& feedUrl, const QString& parentFolder);
    WebServiceReplyPtr addFolder(const QString& folderName, const QString& parentFolder);
    FeedSearchResultsReplyPtr findFeed(const QStringList& searchTerms);
    WebServiceReplyPtr verifyAccount(const QString& userName, const QString& password);
    UnreadCountsReplyPtr updateUnreadCounts();
    FeedClassifiersReplyPtr feedClassifiers(int feedId);
    SaveFeedClassifiersReplyPtr saveClassifiers(const FeedClassifiers& classifiers,
                                     int feedId, const QString& storyId = QString());

private:
    enum NetworkRequestType
    {
        RtLogin,
        RtLogout,
        RtFeeds,
        RtFeedStories,
        RtStatistics,
        RtMarkStoryRead,
        RtMarkFeedStoriesRead,
        RtMarkStoryUnread,
        RtRefreshUnreadCounts,
        RtStarredStories,
        RtFavicons,
        RtMarkStoryStarred,
        RtMarkStoryUnstarred,
        RtMarkFeedRead,
        RtMarkAllRead,
        RtRenameFeed,
        RtRenameFolder,
        RtDeleteFeed,
        RtDeleteFolder,
        RtMoveFeed,
        RtMoveFolder,
        RtAddFeed,
        RtAddFolder,
        RtFeedAutocomplete,
        RtRiverStories,
        RtFeedTrainer,
        RtSaveClassifiers
    };
    enum ClassifierTarget
    {
        CtFeed,
        CtTitle,
        CtAuthor,
        CtTag
    };
    QSize m_preferredFaviconSize;

    bool isLoggedIn() const;
    QMultiHash<int, FeedItemPtr> createFeedItems(const QVariantMap &feedMap) const;
    QList<PageItemPtr> createFolderItems(const QVariantList& folderList, PageItemPtr parentItem, QMultiHash<int, FeedItemPtr> *feedItems,
                                       QList<FolderItemPtr> *folderItems, QMultiHash<int, FeedItemPtr> *_allFeedItems = 0) const;
    QList<StoryItemPtr> createStoryItems(FeedItemPtr parentItem, const QVariantList &itemList);
    void createFeedItemClassifiers(const QVariantMap &classifiers, ClassifierHash *tagClassifiers,
                                   ClassifierHash *authorClassifiers, ClassifierHash *titleClassifiers,
                                   NewsBlurEnum::ClassifierValue *feedClassifier) const;
    QString classifierValueToParam(NewsBlurEnum::ClassifierValue value, ClassifierTarget target) const;
    QImage resizeFavicon(const QImage& favicon) const;

private slots:
    QNetworkReply* networkRequestFinished(QNetworkReply *networkReply,
                                          WebServiceReplyPtr webServiceReply, int networkRequestType);

signals:
    void authenticationRequired(QAuthenticator* auth);

private:
    static const char* s_serviceBaseUrl;
    static const char* s_loginPath;
    static const char* s_logoutPath;
    static const char* s_feedsPath;
    static const char* s_feedPath;
    static const char* s_feedStatisticsPath;
    static const char* s_markStoryReadPath;
    static const char* s_markStoryUnreadPath;
    static const char* s_refreshFeedsPath;
    static const char* s_starredStoriesPath;
    static const char* s_faviconsPath;
    static const char* s_markStoryStarredPath;
    static const char* s_markStoryUnstarredPath;
    static const char* s_markFeedReadPath;
    static const char* s_markAllReadPath;
    static const char* s_renameFeedPath;
    static const char* s_renameFolderPath;
    static const char* s_riverStoriesPath;
    static const char* s_deleteFeedPath;
    static const char* s_deleteFolderPath;
    static const char* s_moveFeedPath;
    static const char* s_moveFolderPath;
    static const char* s_addFolderPath;
    static const char* s_addUrlPath;
    static const char* s_feedAutocompletePath;
    static const char* s_feedTrainerPath;
    static const char* s_saveClassifiersPath;
    static const char* s_markFeedStoriesReadPath;

    static const char* s_userNameKeyName;
    static const char* s_passwordKeyName;

    static const char* s_userNameParameter;
    static const char* s_passwordParameter;
    static const char* s_pageParameter;
    static const char* s_feedIdParameter;
    static const char* s_storyIdParameter;
    static const char* s_feedsParameter;
    static const char* s_feedTitleParameter;
    static const char* s_folderNameParameter;
    static const char* s_inFolderParameter;
    static const char* s_newFolderNameParameter;
    static const char* s_toFolderParameter;
    static const char* s_parentFolderParameter;
    static const char* s_folderParameter;
    static const char* s_urlParameter;
    static const char* s_termParameter;
    static const char* s_likeFeedParameter;
    static const char* s_dislikeFeedParameter;
    static const char* s_removeLikeFeedParameter;
    static const char* s_removeDislikeFeedParameter;
    static const char* s_likeTitleParameter;
    static const char* s_dislikeTitleParameter;
    static const char* s_removeLikeTitleParameter;
    static const char* s_removeDislikeTitleParameter;
    static const char* s_likeTagParameter;
    static const char* s_dislikeTagParameter;
    static const char* s_removeLikeTagParameter;
    static const char* s_removeDislikeTagParameter;
    static const char* s_likeAuthorParameter;
    static const char* s_dislikeAuthorParameter;
    static const char* s_removeLikeAuthorParameter;
    static const char* s_removeDislikeAuthorParameter;
    static const char* s_feedStoriesParameter;

    static const char* s_feedTitleValue;
    static const char* s_negativeCountValue;
    static const char* s_positiveCountValue;
    static const char* s_neutralCountValue;
    static const char* s_tagsValue;
    static const char* s_authorsValue;
    static const char* s_titlesValue;
    static const char* s_feedsValue;
    static const char* s_negativeClassifierValue;
    static const char* s_positiveClassifierValue;
    static const char* s_neutralClassifierValue;
    static const char* s_idValue;
    static const char* s_storyFeedIdValue;
    static const char* s_storyTitleValue;
    static const char* s_readStatusValue;
    static const char* s_storyContentValue;
    static const char* s_storyPermalinkValue;
    static const char* s_storyDateValue;
    static const char* s_storyAuthorsValue;
    static const char* s_storyTagsValue;
    static const char* s_starredValue;
    static const char* s_intelligenceValue;
    static const char* s_authorValue;
    static const char* s_titleValue;
    static const char* s_feedValue;
    static const char* s_authenticatedValue;
    static const char* s_trueValue;
    static const char* s_foldersValue;
    static const char* s_starredCountValue;
    static const char* s_storiesValue;
    static const char* s_classifiersValue;
    static const char* s_resultValue;
    static const char* s_okValue;
    static const char* s_labelValue;
    static const char* s_valueValue;
    static const char* s_numSubscribersValue;
    static const char* s_numStoriesLastMonthValue;
    static const char* s_feedTagsValue;
    static const char* s_feedAuthorsValue;
    static const char* s_storyDateFormat;
    static const char* s_nullIconContents;
};
} // namespace NewsBlur
#endif // NEWSBLURCLIENT_H
