/******************************************************************************
 *
 *  Copyright 2008 Szymon Tomasz Stefanek <pragma@kvirc.net>
 *
 *  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 "core/aggregation.h"

#include <QDataStream>

#include <klocale.h>

using namespace MessageList::Core;

static const int gAggregationCurrentVersion = 0x1009; // increase if you add new fields of change the meaning of some


Aggregation::Aggregation(
        const QString &name,
        const QString &description,
        Grouping grouping,
        GroupExpandPolicy groupExpandPolicy,
        Threading threading,
        ThreadLeader threadLeader,
        ThreadExpandPolicy threadExpandPolicy,
        FillViewStrategy fillViewStrategy, bool readOnly
        )
    : OptionSet( name, description, readOnly ),
      mGrouping( grouping ),
      mGroupExpandPolicy( groupExpandPolicy ),
      mThreading( threading ),
      mThreadLeader( threadLeader ),
      mThreadExpandPolicy( threadExpandPolicy ),
      mFillViewStrategy( fillViewStrategy )
{
}

Aggregation::Aggregation(
        const Aggregation &opt
        )
    : OptionSet( opt ),
      mGrouping( opt.mGrouping ),
      mGroupExpandPolicy( opt.mGroupExpandPolicy ),
      mThreading( opt.mThreading ),
      mThreadLeader( opt.mThreadLeader ),
      mThreadExpandPolicy( opt.mThreadExpandPolicy ),
      mFillViewStrategy( opt.mFillViewStrategy )
{
}

Aggregation::Aggregation()
    : OptionSet(),
      mGrouping( NoGrouping ),
      mGroupExpandPolicy( NeverExpandGroups ),
      mThreading( NoThreading ),
      mThreadLeader( TopmostMessage ),
      mThreadExpandPolicy( NeverExpandThreads ),
      mFillViewStrategy( FavorInteractivity )
{
}

bool Aggregation::load( QDataStream &stream )
{
    int val;

    stream >> val;
    if ( val != gAggregationCurrentVersion )
        return false; // b0rken (invalid version)

    stream >> val;
    mGrouping = (Grouping)val;
    switch( mGrouping )
    {
    case NoGrouping:
    case GroupByDate:
    case GroupByDateRange:
    case GroupBySenderOrReceiver:
    case GroupBySender:
    case GroupByReceiver:
        // ok
        break;
    default:
        // b0rken
        return false;
        break;
    }

    stream >> val; // Formerly contained group sorting
    stream >> val; // Formerly contained group sorting direction

    stream >> val;
    mGroupExpandPolicy = (GroupExpandPolicy)val;
    switch( mGroupExpandPolicy )
    {
    case NeverExpandGroups:
    case ExpandRecentGroups:
    case AlwaysExpandGroups:
        // ok
        break;
    default:
        // b0rken
        return false;
        break;
    }

    stream >> val;
    mThreading = (Threading)val;
    switch( mThreading )
    {
    case NoThreading:
    case PerfectOnly:
    case PerfectAndReferences:
    case PerfectReferencesAndSubject:
        // ok
        break;
    default:
        // b0rken
        return false;
        break;
    }

    stream >> val;
    mThreadLeader = (ThreadLeader)val;
    switch( mThreadLeader )
    {
    case MostRecentMessage:
    case TopmostMessage:
        // ok
        // FIXME: Should check that thread leaders setting matches grouping and threading settings.
        break;
    default:
        // b0rken
        return false;
        break;
    }

    stream >> val;
    mThreadExpandPolicy = (ThreadExpandPolicy)val;
    switch( mThreadExpandPolicy )
    {
    case NeverExpandThreads:
    case ExpandThreadsWithNewMessages:
    case ExpandThreadsWithUnreadMessages:
    case ExpandThreadsWithUnreadOrImportantMessages:
    case AlwaysExpandThreads:
        // ok
        break;
    default:
        // b0rken
        return false;
        break;
    }

    stream >> val; // Formely contained message sorting
    stream >> val; // Formely contained message sort direction

    stream >> val;
    mFillViewStrategy = (FillViewStrategy)val;
    switch( mFillViewStrategy )
    {
    case FavorSpeed:
    case FavorInteractivity:
    case BatchNoInteractivity:
        // ok
        break;
    default:
        // b0rken
        return false;
        break;
    }

    return true;
}

void Aggregation::save( QDataStream &stream ) const
{
    stream << (int)gAggregationCurrentVersion;
    stream << (int)mGrouping;
    stream << 0; // Formerly group sorting
    stream << 0; // Formerly group sort direction
    stream << (int)mGroupExpandPolicy;
    stream << (int)mThreading;
    stream << (int)mThreadLeader;
    stream << (int)mThreadExpandPolicy;
    stream << 0; // Formerly message sorting
    stream << 0; // Formerly message sort direction
    stream << (int)mFillViewStrategy;
}

QList< QPair< QString, int > > Aggregation::enumerateGroupingOptions()
{
    QList< QPair< QString, int > > ret;
    ret.append( QPair< QString, int >( i18nc( "No grouping of messages", "None" ), NoGrouping ) );
    ret.append( QPair< QString, int >( i18n( "By Exact Date (of Thread Leaders)" ), GroupByDate ) );
    ret.append( QPair< QString, int >( i18n( "By Smart Date Ranges (of Thread Leaders)" ), GroupByDateRange ) );
    ret.append( QPair< QString, int >( i18n( "By Smart Sender/Receiver" ), GroupBySenderOrReceiver ) );
    ret.append( QPair< QString, int >( i18n( "By Sender" ), GroupBySender ) );
    ret.append( QPair< QString, int >( i18n( "By Receiver" ), GroupByReceiver ) );
    return ret;
}


QList< QPair< QString, int > > Aggregation::enumerateGroupExpandPolicyOptions( Grouping g )
{
    QList< QPair< QString, int > > ret;
    if ( g == NoGrouping )
        return ret;
    ret.append( QPair< QString, int >( i18n( "Never Expand Groups" ), NeverExpandGroups ) );
    if ( ( g == GroupByDate ) || ( g == GroupByDateRange ) )
        ret.append( QPair< QString, int >( i18n( "Expand Recent Groups" ), ExpandRecentGroups ) );
    ret.append( QPair< QString, int >( i18n( "Always Expand Groups" ), AlwaysExpandGroups ) );
    return ret;
}

QList< QPair< QString, int > > Aggregation::enumerateThreadingOptions()
{
    QList< QPair< QString, int > > ret;
    ret.append( QPair< QString, int >( i18nc( "No threading of messages", "None" ), NoThreading ) );
    ret.append( QPair< QString, int >( i18n( "Perfect Only" ), PerfectOnly ) );
    ret.append( QPair< QString, int >( i18n( "Perfect and by References" ), PerfectAndReferences ) );
    ret.append( QPair< QString, int >( i18n( "Perfect, by References and by Subject" ), PerfectReferencesAndSubject ) );
    return ret;
}

QList< QPair< QString, int > > Aggregation::enumerateThreadLeaderOptions( Grouping g, Threading t )
{
    QList< QPair< QString, int > > ret;
    if ( t == NoThreading )
        return ret;
    ret.append( QPair< QString, int >( i18n( "Topmost Message" ), TopmostMessage ) );
    if ( ( g != GroupByDate ) && ( g != GroupByDateRange ) )
        return ret;
    ret.append( QPair< QString, int >( i18n( "Most Recent Message" ), MostRecentMessage ) );
    return ret;
}

QList< QPair< QString, int > > Aggregation::enumerateThreadExpandPolicyOptions( Threading t )
{
    QList< QPair< QString, int > > ret;
    if ( t == NoThreading )
        return ret;
    ret.append( QPair< QString, int >( i18n( "Never Expand Threads" ), NeverExpandThreads ) );
    ret.append( QPair< QString, int >( i18n( "Expand Threads With Unread Messages" ), ExpandThreadsWithUnreadMessages ) );
    ret.append( QPair< QString, int >( i18n( "Expand Threads With Unread or Important Messages" ), ExpandThreadsWithUnreadOrImportantMessages ) );
    ret.append( QPair< QString, int >( i18n( "Always Expand Threads" ), AlwaysExpandThreads ) );
    return ret;
}

QList< QPair< QString, int > > Aggregation::enumerateFillViewStrategyOptions()
{
    QList< QPair< QString, int > > ret;
    ret.append( QPair< QString, int >( i18n( "Favor Interactivity" ), FavorInteractivity ) );
    ret.append( QPair< QString, int >( i18n( "Favor Speed" ), FavorSpeed ) );
    ret.append( QPair< QString, int >( i18n( "Batch Job (No Interactivity)" ), BatchNoInteractivity ) );
    return ret;
}

