/****************************************************************************
**
** 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 GOOGLEREADERSERVICE_H
#define GOOGLEREADERSERVICE_H
#include <abstractfeedaggreagatorservice.h>
#include <QtPlugin>
#include <QDeclarativeImageProvider>
#include "pageitem.h"
#include <QMultiHash>
#include <QSystemAlignedTimer>
#include "feeditem.h"
#include "tagitem.h"
#include "folderitem.h"
#include "everythingtagitem.h"
#include "starredtagitem.h"
#include "rootitem.h"
#include "googlereaderclient.h"

namespace GoogleReader
{
#ifdef QTM_USE_NAMESPACE
QTM_USE_NAMESPACE
#endif
class ApplicationSettings;
class GoogleReaderService : public AbstractFeedAggreagatorService
{
    Q_OBJECT
    Q_INTERFACES(AbstractFeedAggreagatorService)
    Q_PROPERTY(bool busy READ isBusy WRITE setBusy NOTIFY busyChanged)
    Q_PROPERTY(int itemFilter READ itemFilter WRITE setItemFilter NOTIFY itemFilterChanged)
    Q_PROPERTY(int itemSortType READ itemSortType WRITE setItemSortType NOTIFY itemSortTypeChanged)
    Q_PROPERTY(QStringList availableTags READ availableTags NOTIFY availableTagsChanged)
    Q_PROPERTY(int unreadCountLimit READ unreadCountLimit NOTIFY unreadCountLimitChanged)
public:
    explicit GoogleReaderService(QObject *parent = 0);
    ~GoogleReaderService();

    void enable(PageItemPtr parentItem);
    void disable();
    QString serviceId() const;
    QStringList menuItems(PageItemPtr item) const;
    QStringList contextMenuItems(PageItemPtr item) const;
    bool isItemAcceptable(PageItemPtr item);
    QSet<QString> customItemTypeProperties() const;
    bool isBusy() const;
    void setBusy(bool busy);
    int itemFilter() const;
    void setItemFilter(int filterType);
    int itemSortType() const;
    void setItemSortType(int sortType);
    QStringList availableTags() const;
    int unreadCountLimit() const;

public slots:
    Q_INVOKABLE QString servicePageUrl() const;
    Q_INVOKABLE QString authenticationSheet() const;
    Q_INVOKABLE QString serviceName() const;
    Q_INVOKABLE QString serviceImageUrl() const;
    Q_INVOKABLE bool isAuthenticationDataSet() const;
    Q_INVOKABLE void clearAuthenticationData();
    Q_INVOKABLE PageItem* rootItem() const;

    Q_INVOKABLE void verifyAuthenticationData(const QString& userName, const QString& password);
    Q_INVOKABLE void abortVerification();
    Q_INVOKABLE void setAuthenticationData(const QString& userName, const QString& password);
    Q_INVOKABLE void refreshFeed(GoogleReader::FeedItem* feed);
    Q_INVOKABLE void starStory(GoogleReader::StoryItem* story);
    Q_INVOKABLE void unstarStory(GoogleReader::StoryItem* story);
    Q_INVOKABLE void markStoryUnread(GoogleReader::StoryItem* story);
    Q_INVOKABLE QString feedTitle(const QString& feedId) const;
    Q_INVOKABLE void markFeedAsRead(GoogleReader::ParentItem* item);
    Q_INVOKABLE void markEverythingAsRead();
    Q_INVOKABLE void setItemTags(GoogleReader::GoogleReaderItem* item, const QStringList& tags);
    Q_INVOKABLE void abortSettingItemTags(GoogleReader::GoogleReaderItem* item);
    Q_INVOKABLE void renameItem(GoogleReader::GoogleReaderItem* item, const QString& newName);
    Q_INVOKABLE void abortItemRename(GoogleReader::GoogleReaderItem* item);
    Q_INVOKABLE void deleteItem(GoogleReader::GoogleReaderItem* item);
    Q_INVOKABLE void findFeeds(const QString& searchTerm);
    Q_INVOKABLE void addFeed(const QString& url);
    Q_INVOKABLE void abortAddFeed();

private:
    RootItemPtr m_rootItem;
    GoogleReaderClient* m_client;
    QMultiHash<QString, FeedItemPtr> m_feedItems;
    QMultiHash<QString, TagItemPtr> m_tagItems;
    QMultiHash<QString, FolderItemPtr> m_folderItems;
    EverythingTagItemPtr m_everythingTagItem;
    StarredTagItemPtr m_starredTagItem;
    bool m_busy;
    bool m_unreadCountsOutOfDate;
    int m_unreadCountLimit;
#ifdef QTM_USE_NAMESPACE
    QSystemAlignedTimer m_unreadCountUpdateTimer;
#else
    QTimer m_unreadCountUpdateTimer;
#endif

    QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize);
    QString userName() const;
    void setUserName(const QString& userName);
    QString password() const;
    void setPassword(const QString& password);
    bool isRequestAllowed(GoogleReaderClient::RequestType type, GoogleReaderItemPtr relatedItem) const;
    void setItemUnreadCounts(const QHash<QString, int>& unreadCounts);
    void setUnreadCountLimit(int limit);
    void incrementUnreadCount(ParentItemPtr parentItem);
    void decrementUnreadCount(ParentItemPtr parentItem);

private slots:
    void onAccountVerificationCompleted(WebServiceReplyPtr reply, WebServiceReply::CompletedState state);
    void onItemActivated(PageItemPtr item);
    void onItemDeactivated(PageItemPtr item);
    void onMoreChildrenRequested(PageItemPtr parentItem);
    void onUnreadCountUpdateTimerTimeout();

    void onAuthenticationRequired(QAuthenticator* auth);
    void onRequestCompleted(WebServiceReplyPtr reply, WebServiceReply::CompletedState state);
    void onRequestFailed(WebServiceReplyPtr reply);
    void onRequestAborted(WebServiceReplyPtr reply);

    void updateTreeStructure();
    void updateUnreadCounts(bool resetTimer = true);
    void refreshFeed(FeedItemPtr feedItem);
    void loadFeedStories(FeedItemPtr feedItem);
    void markStoryRead(StoryItemPtr storyItem);

    void onUpdateTreeCompleted(WebServiceReplyPtr reply, WebServiceReply::CompletedState state);
    void onUpdateUnreadCountsFinished(WebServiceReplyPtr reply);
    void onLoadFeedStoriesFinished(WebServiceReplyPtr reply);
    void onStarStoryFinished(WebServiceReplyPtr reply);
    void onUnstarStoryFinished(WebServiceReplyPtr reply);
    void onMarkStoryReadFinished(WebServiceReplyPtr reply);
    void onMarkStoryUnreadFinished(WebServiceReplyPtr reply);
    void onMarkFeedAsReadFinished(WebServiceReplyPtr reply);
    void onMarkEverythingAsReadFinished(WebServiceReplyPtr reply);
    void onSettingStoryTagsCompleted(WebServiceReplyPtr reply, WebServiceReply::CompletedState state);
    void onSettingFeedTagsCompleted(WebServiceReplyPtr reply, WebServiceReply::CompletedState state);
    void onItemRenamingCompleted(WebServiceReplyPtr reply, WebServiceReply::CompletedState state);
    void onItemDeleteCompleted(WebServiceReplyPtr reply, WebServiceReply::CompletedState state);
    void onFindFeedsCompleted(WebServiceReplyPtr reply, WebServiceReply::CompletedState state);
    void onFeedAddingCompleted(WebServiceReplyPtr reply, WebServiceReply::CompletedState state);

signals:
    void accountVerificationComplete(int result);
    void busyChanged();
    void itemFilterChanged();
    void itemSortTypeChanged();
    void availableTagsChanged();
    void settingItemTagsFinished(int result);
    void itemRenamingFinished(int result);
    void feedSearchFinished(int result, QStringList titles, QStringList urls);
    void feedAddingFinished(int result);
    void unreadCountLimitChanged();

private:
    static const char* s_serviceName;
    static const char* s_serviceId;
    static const int s_unreadCountUpdateIntervalMinMs;
    static const int s_unreadCountUpdateIntervalMaxMs;
    static const int s_preferredStoryCount;

    static const char* s_serviceImageUrl;
    static const char* s_starGroupImageUrl;
    static const char* s_generalFeedImageUrl;
    static const char* s_folderImageUrl;
    static const char* s_tagImageUrl;

    static const char* s_userNameKey;
    static const char* s_passwordKey;
    static const char* s_itemFilterTypeKey;
    static const char* s_itemSortTypeKey;

    static const char* s_servicePageUrl;
    static const char* s_authenticationSheetUrl;

    static const char* s_busyPropertyName;
    static const char* s_starredBusyPropertyName;
    static const char* s_feedReadBusyPropertyName;
    static const char* s_editingBusyPropertyName;

    static const char* s_serviceIconId;
    static const char* s_folderIconId;
    static const char* s_feedIconId;
    static const char* s_starredTagIconId;
    static const char* s_tagIconId;

    static const char* s_sortSelectionMenuItemName;
    static const char* s_markStoryAsUnreadMenuItemName;
    static const char* s_editStoryTagsMenuItemName;
    static const char* s_shareStoryMenuItemName;
    static const char* s_starStoryMenuItemName;
    static const char* s_unstarStoryMenuItemName;
    static const char* s_renameMenuItemName;
    static const char* s_deleteMenuItemName;
    static const char* s_markAllAsReadMenuItemName;
    static const char* s_helpMenuItemName;
};
} // namespace GoogleReader
#endif // GOOGLEREADERSERVICE_H

