/****************************************************************************
**
** 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/>.
****************************************************************************/

#include "feeditem.h"
#include "storyitem.h"

namespace NewsBlur
{
/*!
  \class FeedItem
  \brief The FeedItem class represents a feed item parent, which should only contain story items.
*/
/*!
  \property FeedItem::unreadCount
  The number of related unread stories with neutral classification.
*/
/*!
  \property FeedItem::posUnreadCount
  The number of related unread stories with positive classification.
*/
/*!
  \property FeedItem::negUnreadCount
  The number of related unread stories with negative classification.
*/
/*!
  \property FeedItem::unreadCountText
  The number of related unread stories in textual representation.
*/

/*!
  Constructs a FeedItem class with the given \a parent and \a service object.
*/
FeedItem::FeedItem(PageItemPtr parent, AbstractFeedAggreagatorService* service) :
    NewsBlurItem(parent, service),
    m_unreadCount(0),
    m_posUnreadCount(0),
    m_negUnreadCount(0),
    m_outOfDate(false)
{
    connect(this, SIGNAL(activityChanged()),
            this, SLOT(onActivityChanged()));
}

/*!
  Reimplemented from NewsBlurItem::itemType().
*/
NewsBlurItem::ItemType FeedItem::itemType() const
{
    return NewsBlurItem::FeedItem;
}

int FeedItem::unreadCount() const
{
    return m_unreadCount;
}

void FeedItem::setUnreadCount(int unreadCount)
{
    if(unreadCount < 0)
        unreadCount = 0;
    m_unreadCount = unreadCount;    
    updateUnreadCountText();
    emit unreadCountChanged();
    emit dataChanged(FeedItemWeakRef(this));
}

/*!
  Returns true if new stories have appeared at the beginning of the feed,
  otherwise returns false.
*/
bool FeedItem::isOutOfDate() const
{
    return m_outOfDate;
}

/*!
  \sa FeedItem::isOutOfDate
*/
void FeedItem::markAsOutOfDate(bool outOfDate)
{
    m_outOfDate = outOfDate;
}

/*!
  Returns the stories intelligence classifiers.
*/
FeedClassifiers FeedItem::classifiers() const
{
    return m_classifiers;
}

/*!
  \sa FeedItem::classifiers
*/
void FeedItem::setClassifiers(const FeedClassifiers &classifiers)
{
    m_classifiers = classifiers;
}

QString FeedItem::unreadCountText() const
{
    return m_unreadCountText;
}

void FeedItem::setUnreadCountText(const QString &text)
{
    m_unreadCountText = text;
    emit unreadCountTextChanged();
}

/*!
  Returns the number of child items that are acceptable by the given \a filter type.
*/
int FeedItem::filteredChildCount(NewsBlurEnum::ClassificationFilter filter) const
{
    int ret = childCount();
    if(filter != NewsBlurEnum::CfNoFilter)
    {
        ret = 0;
        for(int i = 0; i < childCount(); ++i)
        {
            StoryItemPtr storyItem = childItem(i).dynamicCast<class StoryItem>();
            if(storyItem
              && NewsBlurEnum::filterAcceptsClassification(filter, NewsBlurEnum::ClassifierValue(storyItem->itemClassification())))
                ++ret;
        }
    }
    return ret;
}

/*!
  Returns the last UTC date when the item has been activated.
*/
QDateTime FeedItem::lastAccessDate() const
{
    return m_lastAccessDate;
}

/*!
  Returns true if there are no unread stories related to this feed,
  otherwise returns false.
*/
bool FeedItem::isRead() const
{
    return ((unreadCount() <= 0)
            && (negUnreadCount() <= 0)
            && (posUnreadCount() <= 0));
}

/*!
  Sets the read status for all the child stories
  of the fead to \a read.
*/
void FeedItem::setChildrenRead(bool read)
{
    if(childCount())
    {
        foreach(PageItemPtr child, m_childItems)
        {
            StoryItemPtr story = child.staticCast<class StoryItem>();
            story->setReadWithoutNotify(read);
        }
        emit childrenDataChanged(FeedItemWeakRef(this));
    }
}

/*!
  Updates the FeedItem::unreadCountText property.
*/
void FeedItem::updateUnreadCountText()
{
    QString text;
    if(itemType() == NewsBlurItem::EverythingGroup)
    {
        QStringList unreadCounts;
        if(negUnreadCount() > 0)
            unreadCounts << QString("<span style=\"color:%1\">%2</span>").arg(NewsBlurEnum::s_negativeHighlightColor).arg(m_negUnreadCount);
        if(unreadCount() > 0)
            unreadCounts << QString("<span style=\"color:%1\">%2</span>").arg(NewsBlurEnum::s_highlightColor).arg(m_unreadCount);
        if(posUnreadCount() > 0)
            unreadCounts << QString("<span style=\"color:%1\">%2</span>").arg(NewsBlurEnum::s_positiveHighlightColor).arg(m_posUnreadCount);
        if(unreadCounts.count() > 0)
            text = QString(tr("%1 unread stories")).arg(unreadCounts.join("+"));
    }
    else if(itemType() == NewsBlurItem::StarredGroup)
    {
        if(m_unreadCount > 0)
            text = QString(tr("%1 saved stories")).arg(m_unreadCount);
    }
    setUnreadCountText(text);
}

/*!
  Updates the date when the feed actived.
  \sa FeedItem::lastAccessDate
*/
void FeedItem::onActivityChanged()
{
    if(isActive())
        m_lastAccessDate = QDateTime::currentDateTimeUtc();
}

int FeedItem::posUnreadCount() const
{
    return m_posUnreadCount;
}

void FeedItem::setPosUnreadCount(int unreadCount)
{
    if(unreadCount < 0)
        unreadCount = 0;
    m_posUnreadCount = unreadCount;    
    updateUnreadCountText();
    emit posUnreadCountChanged();
    emit dataChanged(FeedItemWeakRef(this));
}

int FeedItem::negUnreadCount() const
{
    return m_negUnreadCount;
}

void FeedItem::setNegUnreadCount(int unreadCount)
{
    if(unreadCount < 0)
        unreadCount = 0;
    m_negUnreadCount = unreadCount;
    updateUnreadCountText();
    emit negUnreadCountChanged();
    emit dataChanged(FeedItemWeakRef(this));
}
} // namespace NewsBlur
