/****************************************************************************
**
** 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 GOOGLEREADERCLIENT_H
#define GOOGLEREADERCLIENT_H
#include "webserviceclient.h"
#include <QAuthenticator>
#include <QNetworkReply>
#include "updatetreereply.h"
#include "unreadcountsreply.h"
#include "storylistreply.h"
#include "editreply.h"
#include "feedsearchresultsreply.h"

namespace GoogleReader
{
class GoogleReaderClient : public WebServiceClient
{
    Q_OBJECT
public:
    enum RequestType
    {
        TpVerifyAccount,
        TpUpdateTree,
        TpUpdateUnreadCounts,
        TpLoadFeedStories,
        TpStarStory,
        TpUnstarStory,
        TpMarkStoryRead,
        TpMarkStoryUnread,
        TpMarkFeedAsRead,
        TpEditStoryTags,
        TpEditFeedTags,
        TpRenameFeed,
        TpRenameTag,
        TpDeleteFeed,
        TpDeleteTag,
        TpFindFeeds,
        TpAddFeed
    };
    explicit GoogleReaderClient(QObject *parent = 0);
    bool isLoggedIn() const;
    WebServiceReplyPtr verifyAccount(const QString& userName, const QString& password);
    void logout();
    UpdateTreeReplyPtr updateTree();
    UnreadCountsReplyPtr updateUnreadCounts();
    StoryListReplyPtr loadFeedStories(const QString& feedId, GoogleReaderEnum::ItemFilterType itemFilter,
                                      GoogleReaderEnum::ItemSortType itemSort, int preferredStoryCount,
                                      const QString& continuation, quint64 startTime = 0);
    EditReplyPtr starStory(const QString& feedId, const QString& storyId);
    EditReplyPtr unstarStory(const QString& feedId, const QString& storyId);
    EditReplyPtr markStoryRead(const QString& feedId, const QString& storyId, bool keptUnread);
    EditReplyPtr markStoryUnread(const QString& feedId, const QString& storyId);
    EditReplyPtr markFeedAsRead(const QString& feedId);
    EditReplyPtr markEverythingAsRead();
    EditReplyPtr setStoryTags(const QString& feedId, const QString& storyId,
                                   const QStringList& newTags, const QStringList& currentTags);
    EditReplyPtr setFeedTags(const QString& feedId, const QString& feedTitle,
                                  const QStringList& newTags, const QStringList& currentTags);
    EditReplyPtr renameTag(const QString& tagId, const QString& newName);
    EditReplyPtr renameFeed(const QString& feedId, const QString& newName);
    EditReplyPtr deleteTag(const QString& tagId);
    EditReplyPtr deleteFeed(const QString& feedId, const QString& feedTitle);
    EditReplyPtr addFeed(const QString& feedUrl);
    FeedSearchResultsReplyPtr findFeeds(const QString& searchTerm);

signals:
    void authenticationRequired(QAuthenticator* auth);

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

private:
    enum NetworkRequestType
    {
        NrtLogin,
        NrtLogout,
        NrtSubscriptions,
        NrtTags,
        NrtUnreadCounts,
        NrtFavicon,
        NrtListPreferences,
        NrtLoadFeedStories,
        NrtEditToken,
        NrtEditTag,
        NrtMarkAllAsRead,
        NrtEditSubscription,
        NrtRenameTag,
        NrtDisableTag,
        NrtFindFeeds,
        NrtAddFeed
    };    
    QString m_authId;

    QNetworkReply *sendRequest(int requestTypeId, const QString &path = QString(),
                               const StringPairList &parameters = StringPairList(),
                               const StringPairList &additionalHeaders = StringPairList());
    QString currentTimestamp() const;

    QMultiHash<QString, TagItemPtr> createTagItems(const QVariantList& tagList) const;
    QMultiHash<QString, FeedItemPtr> createFeedItems(const QVariantList& feedList,
                                                     QMultiHash<QString, QString> *feedCategories) const;
    FeedItemPtr createFeedItem(const QVariantMap& feedMap) const;    
    QStringList categoryIdList(const QVariantList& categoryList) const;
    QHash<QString, int> createIdUnreadCounts(const QVariantList& unreadCountList) const;
    QHash<QString, QStringList> createItemOrderingHash(const QVariantMap &preferenceMap);
    QString generalItemId(const QByteArray &itemId) const;
    QString toPlainText(const QString& richText) const;
    QString sortTypeString(GoogleReaderEnum::ItemSortType sortType) const;
    QString filterTypeString(GoogleReaderEnum::ItemFilterType filterType) const;
    QString tagIdFromTitle(const QString& title) const;
    QString tagTitleFromId(const QString& id) const;
    QString feedIconUrl(const QString& feedUrl) const;
    static bool itemSortLessThan(const GoogleReaderItemPtr& item1, const GoogleReaderItemPtr& item2);
    static int itemSortId(const GoogleReaderItemPtr& item);

private:
    static const char* s_baseUrl;
    static const char* s_secureBaseUrl;
    static const char* s_faviconUrl;
    static const char* s_loginPath;
    static const char* s_logoutPath;
    static const char* s_subscriptionsPath;
    static const char* s_tagsPath;
    static const char* s_unreadCountsPath;
    static const char* s_listPreferencePath;
    static const char* s_feedStoriesPath;
    static const char* s_editTokenPath;
    static const char* s_editTagPath;
    static const char* s_markAllAsReadPath;
    static const char* s_editSubscriptionPath;
    static const char* s_renameTagPath;
    static const char* s_disableTagPath;
    static const char* s_findFeedsUrl;
    static const char* s_addFeedPath;
    static const char* s_sessionIdName;
    static const char* s_authIdName;
    static const char* s_sessionCookiePath;
    static const char* s_sessionCookieDomain;
    static const char* s_authHeaderName;
    static const char* s_authHeaderValuePrefix;

    static const char* s_everythingTagId;
    static const char* s_starredTagId;
    static const char* s_rootItemId;

    static const char* s_readStateId;
    static const char* s_keptUnreadStateId;
    static const char* s_starredStateId;
    static const char* s_readingListStateId;

    static const char* s_sortByNewestValue;
    static const char* s_sortByOldestValue;
    static const char* s_sortByMagicValue;

    static const char* s_serviceParameter;
    static const char* s_serviceValue;
    static const char* s_emailParameter;
    static const char* s_passwordParameter;
    static const char* s_outputParameter;
    static const char* s_outputParameterValue;
    static const char* s_timestampParemeter;
    static const char* s_clientParameter;
    static const char* s_clientParameterValue;
    static const char* s_maxNumberOfResultsParameter;
    static const char* s_excludeTargetParameter;
    static const char* s_sortOrderParameter;
    static const char* s_continuationParameter;
    static const char* s_startTimeParameter;
    static const char* s_editTokenParameter;
    static const char* s_streamIdParameter;
    static const char* s_itemIdParameter;
    static const char* s_addTagParameter;
    static const char* s_removeTagParameter;
    static const char* s_streamTitleParameter;
    static const char* s_actionParameter;
    static const char* s_actionParameterEditValue;
    static const char* s_actionParameterSubscribeValue;
    static const char* s_actionParameterUnsubscribeValue;
    static const char* s_destParameter;
    static const char* s_feedSearchApiVersionParameter;
    static const char* s_feedSearchApiVersionParameterValue;
    static const char* s_feedSearchApiQueryParameter;
    static const char* s_quickAddParameter;

    static const char* s_idValue;
    static const char* s_countValue;
    static const char* s_titleValue;
    static const char* s_categoriesValue;
    static const char* s_subscriptionsValue;
    static const char* s_tagsValue;
    static const char* s_htmlUrlValue;
    static const char* s_unreadCountsValue;
    static const char* s_sortIdValue;
    static const char* s_streamPreferencesValue;
    static const char* s_subscriptionOrderingValue;
    static const char* s_valueValue;
    static const char* s_continuationValue;
    static const char* s_itemsValue;
    static const char* s_summaryValue;
    static const char* s_contentsValue;
    static const char* s_alternateValue;
    static const char* s_typeValue;
    static const char* s_alternateTypeValue;
    static const char* s_hrefValue;
    static const char* s_publishedValue;
    static const char* s_timestampValue;
    static const char* s_authorValue;
    static const char* s_originValue;
    static const char* s_streamIdValue;
    static const char* s_startTimeValue;
    static const char* s_readStateLockedValue;
    static const char* s_trueValue;
    static const char* s_responseDataValue;
    static const char* s_entriesValue;
    static const char* s_urlValue;
    static const char* s_numberOfResultsValue;
    static const char* s_maxValue;
    static const char* s_okReplyValue;
    static const char* s_tagIdPrefix;
    static const char* s_tagIdPattern;
    static const char* s_stateIdPattern;
    static const char* s_feedIdPrefix;
    static const int s_itemIdLength;
    static const int s_timeStampLength;
};
} // namespace GoogleReader
#endif // GOOGLEREADERCLIENT_H
