/*
   This file is part of the KDE project
   Copyright (C) 2004 Dirk Schmidt <fs@dirk-schmidt.net>
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.
 
   This library 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
   Library General Public License for more details.
 
   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
*/


#include <tqvbox.h>
#include <tqlayout.h>
#include <tqlineedit.h>

#include <tdeapplication.h>
#include <kdebug.h>
#include <tdeglobal.h>
#include <kinputdialog.h>
#include <tdelocale.h>
#include <tdemessagebox.h>
#include <kpushbutton.h>
#include <krun.h>
#include <tdeabc/stdaddressbook.h>
#include <tdeabc/distributionlist.h>

#include "addresspicker.h"
#include "KWMailMergeTDEABC.h"
#include "KWMailMergeTDEABCConfig.h"


KWMailMergeTDEABCConfig::KWMailMergeTDEABCConfig( TQWidget *parent, KWMailMergeTDEABC *db_)
        :KDialogBase( Plain, i18n( "Mail Merge - Editor" ),
                      Ok | Cancel, Ok, parent, "", true)
{
    _db = db_;

    (new TQVBoxLayout(plainPage()))->setAutoAdd(true);
    setMainWidget( _ui=new AddressPickerUI( plainPage() ) );

    updateAvailable();
    initSelectedAddressees();
    initSelectedLists();
    initSlotSignalConnections();
}


KWMailMergeTDEABCConfig::~KWMailMergeTDEABCConfig()
{
    ;
}


void KWMailMergeTDEABCConfig::acceptSelection()
{
    _db->clear();

    TQListViewItem* top = _ui->mSelectedView->firstChild();
    while(top)
    {
        kdDebug() << "acceptSelection(): " << top->text(0) << endl;
        if( top->text(0) == i18n("Distribution Lists") )
        {
            TQListViewItem* item = top->firstChild();
            while(item)
            {
                kdDebug() << "acceptSelection(): " << item->text(0) << endl;
                _db->addList( item->text(0) );
                item = item->nextSibling();
            }
        }
        else if( top->text(0) == i18n("Single Entries") )
        {
            TQListViewItem* item = top->firstChild();
            while(item)
            {
                kdDebug() << "acceptSelection(): " << item->text(0) << endl;
                _db->addEntry( item->text(-1) );
                item = item->nextSibling();
            }
        }
        top = top->nextSibling();
    }

}


void KWMailMergeTDEABCConfig::addSelectedContacts()
{
    TQListViewItemIterator it( _ui->mAvailableView, TQListViewItemIterator::Selected  );
    TQListViewItem* selected = _ui->mSelectedView->findItem(
                                  i18n("Single Entries"), 0, TQt::ExactMatch );
    TQListViewItem* selectedLists = _ui->mSelectedView->findItem(
                                       i18n("Distribution Lists"), 0, TQt::ExactMatch );
    while ( it.current() )
    {
        if( it.current()->depth() > 0 )
        {
            TQString uid = it.current()->text( -1 );
            kdDebug() << "addSelectedContacts(): uid :" << uid << endl;
            if( !uid.isEmpty() )
            {
                KWMailMergeTDEABCConfigListItem *item =
                    static_cast<KWMailMergeTDEABCConfigListItem*> ( it.current() );
                if( selected )
                {
                    selected->insertItem( item );
                    selected->setOpen( true );
                    destroyAvailableClones( uid );
                }
            }
            else if( it.current()->parent()->text(0) == i18n("Distribution Lists") )
            {
                if( selectedLists )
                {
                    selectedLists->insertItem( it.current() );
                    selectedLists->setOpen( true );
                }
            }
        }
        ++it;
    }
    _ui->mSelectedView->selectAll( false );
}


void KWMailMergeTDEABCConfig::destroyAvailableClones( const TQString& uid )
{
    if( uid.isEmpty() )
        return;

    TQListViewItemIterator it( _ui->mAvailableView  );

    while ( it.current() )
    {
        if( it.current()->depth() > 0)
        {
            if( it.current()->text(-1)== uid )
            {
                delete it.current();
            }
        }
        ++it;
    }
}


void KWMailMergeTDEABCConfig::filterChanged( const TQString& txt )
{
    kdDebug() << "KWMailMergeTDEABCConfig::filterChanged( " << txt << " )" << endl;

    bool showAll = txt.isEmpty();

    TQListViewItem* category = _ui->mAvailableView->firstChild();
    while(category)
    {
        if( category->text(0)!=i18n("Distribution Lists") )
        {
            TQListViewItem* item = category->firstChild();
            while(item)
            {
                if(showAll)
                {
                    item->setVisible( true );
                }
                else
                {
                    item->setVisible( item->text(0).contains( txt, false ) );
                }
                item = item->nextSibling();
            }
            category->setOpen( !showAll );
        }
        else
        {
            category->setVisible( showAll );
        }
        category = category->nextSibling();
    }
}


void KWMailMergeTDEABCConfig::initSelectedAddressees()
{
    TQStringList records = _db->singleRecords();

    TQListViewItem* category = _ui->mAvailableView->firstChild();
    TQListViewItem* selected = _ui->mSelectedView->findItem(
                                  i18n("Single Entries"), 0, TQt::ExactMatch );
    while ( category && (records.count()>0) )
    {
        if( category->text(0) != i18n("Distribution Lists") )
        {
            KWMailMergeTDEABCConfigListItem* item =
                static_cast<KWMailMergeTDEABCConfigListItem*> ( category->firstChild() );
            while( item && (records.count()>0) )
            {
                // Need some temporary item, because after selected->insertItem( item )
                // the item->nextSibling() is not the one we want.
                KWMailMergeTDEABCConfigListItem* nextItem =
                    static_cast<KWMailMergeTDEABCConfigListItem*> ( item->nextSibling() );

                for( TQStringList::Iterator itRecords = records.begin();
                        itRecords != records.end(); ++itRecords )
                {
                    TQString uid = *itRecords;
                    if( item->text(-1) == uid )
                    {
                        selected->insertItem( item );

                        // downsize records to speed up iterations
                        itRecords = records.remove( itRecords );
                        --itRecords;

                        destroyAvailableClones( uid );
                    }
                }
                item = nextItem;
            }
        }
        category = category->nextSibling();
    }
}


void KWMailMergeTDEABCConfig::initSelectedLists()
{
    TQStringList lists = _db->lists();

    kdDebug() << "::initSelectedLists()" << lists.join(",") << endl;

    TQListViewItem* l = _ui->mAvailableView->findItem(
                           i18n("Distribution Lists"), 0, TQt::ExactMatch );
    TQListViewItem* selected = _ui->mSelectedView->findItem(
                                  i18n("Distribution Lists"), 0, TQt::ExactMatch );

    TQListViewItem* item = ( l->firstChild() );
    while( item && (lists.count()>0) )
    {
        TQListViewItem* nextItem = item->nextSibling();

        for( TQStringList::Iterator itLists = lists.begin();
                itLists != lists.end(); ++itLists )
        {
            TQString id = *itLists;
            if( item->text(0) == id )
            {
                selected->insertItem( item );
                itLists = lists.remove( itLists );
                --itLists;
            }
        }
        item = nextItem;
    }
}


void KWMailMergeTDEABCConfig::initSlotSignalConnections()
{
    connect( this, TQ_SIGNAL( okClicked() ), TQ_SLOT( acceptSelection() ) );
    connect( _ui->mAddButton, TQ_SIGNAL( clicked() ), TQ_SLOT( addSelectedContacts() ) );
    connect( _ui->mAddressBook, TQ_SIGNAL( clicked() ), TQ_SLOT( launchAddressbook() ) );

    connect( _ui->mAvailableView, TQ_SIGNAL( doubleClicked( TQListViewItem *, const TQPoint &, int ) ),
             TQ_SLOT( addSelectedContacts() ) );

    connect( _ui->mFilterEdit, TQ_SIGNAL( textChanged(const TQString &) ),
             TQ_SLOT( filterChanged(const TQString &) ) );
    connect( _ui->mRemoveButton, TQ_SIGNAL( clicked() ), TQ_SLOT( removeSelectedContacts() ) );
    connect( _ui->mSaveList, TQ_SIGNAL( clicked() ), TQ_SLOT( saveDistributionList() ) );
    connect( _ui->mSelectedView, TQ_SIGNAL( doubleClicked( TQListViewItem *, const TQPoint &, int ) ),
             TQ_SLOT( removeSelectedContacts() ) );
}


void KWMailMergeTDEABCConfig::launchAddressbook() const
{
    kapp->startServiceByDesktopName( "kaddressbook", TQString() );
}



void KWMailMergeTDEABCConfig::removeContact( TQListViewItem* item )
{
    TQStringList& categories = _usedCategories;
    TQListViewItem* availableLists = _ui->mAvailableView->findItem(
                                        i18n("Distribution Lists"), 0, TQt::ExactMatch );
    if( item->depth() > 0 )
    {
        if( !item->text( -1 ).isEmpty() ) // remove selected single entry here
        {
            KWMailMergeTDEABCConfigListItem* rightItem =
                static_cast<KWMailMergeTDEABCConfigListItem*> ( item );

            TQStringList entryCategories = rightItem->addressee().categories();
            for ( TQStringList::Iterator itEntryCat = entryCategories.begin();
                    itEntryCat != entryCategories.end(); ++itEntryCat )
            {
                int i = categories.findIndex(*itEntryCat);
                if(  i == -1 )
                {
                    TQListViewItem* category = new TQListViewItem( _ui->mAvailableView,
                                              *itEntryCat );
                    categories.append( *itEntryCat );

                    KWMailMergeTDEABCConfigListItem* leftItem = new KWMailMergeTDEABCConfigListItem(
                                category, rightItem->addressee() );
                }
                else
                {
                    KWMailMergeTDEABCConfigListItem* leftItem = new
                            KWMailMergeTDEABCConfigListItem(
                                _ui->mAvailableView->findItem(
                                    *itEntryCat, 0,
                                    TQt::ExactMatch),
                                rightItem->addressee() );
                }
            }
            if( entryCategories.isEmpty() )
            {
                TQString noCat = i18n("no category");
                KWMailMergeTDEABCConfigListItem* leftItem = new KWMailMergeTDEABCConfigListItem(
                            _ui->mAvailableView->findItem(
                                noCat, 0, TQt::ExactMatch),
                            rightItem->addressee() );
            }
            delete item;
        }
        else if( item->parent()->text(0) == i18n("Distribution Lists") ) // remove a list
        {
            if( availableLists )
                availableLists->insertItem( item );
        }
    }
}

void KWMailMergeTDEABCConfig::removeSelectedContacts()
{
    TQListViewItemIterator it( _ui->mSelectedView, TQListViewItemIterator::Selected  );

    while( it.current() )
    {
        kdDebug() << "removeSelectedContacts(): text: " << it.current()->text(-1) << endl;
        removeContact( it.current() );
        ++it;
    }
    _ui->mAvailableView->selectAll( false );
}


void KWMailMergeTDEABCConfig::saveDistributionList()
{
    TDEABC::DistributionListManager dlm( TDEABC::StdAddressBook::self() );
    dlm.load();

    bool ok = false;
    TQString listName = KInputDialog::getText( i18n("New Distribution List"),
                       i18n("Please enter name:"),
                       TQString(), &ok,
                       this );
    if ( !ok || listName.isEmpty() )
        return;

    if ( dlm.list( listName ) )
    {
        KMessageBox::information( 0,
                                  i18n( "<qt>Distribution list with the given name <b>%1</b> "
                                        "already exists. Please select a different name.</qt>" )
                                  .arg( listName ) );
        return;
    }
    TDEABC::DistributionList *distList = new TDEABC::DistributionList( &dlm, listName );

    TQListViewItem* newListItem = new TQListViewItem( _ui->mSelectedView->findItem(
                                     i18n("Distribution Lists"),0 , TQt::ExactMatch), listName );

    TQListViewItem* category = _ui->mSelectedView->firstChild();
    while(category)
    {
        if( category->text(0)==i18n("Single Entries") )
        {
            KWMailMergeTDEABCConfigListItem* item =
                static_cast<KWMailMergeTDEABCConfigListItem*> ( category->firstChild() );

            while(item)
            {
                distList->insertEntry( item->addressee() );

                TDEABC::Addressee addr = item->addressee();
                TQString formattedName = addr.formattedName();
                TQListViewItem* newItem = new TQListViewItem(
                                             newListItem, item->addressee().formattedName() );
                newItem->setEnabled( false );

                item = static_cast<KWMailMergeTDEABCConfigListItem*>( item->nextSibling() );
            }

            TQListViewItemIterator it ( category->firstChild() );
            while( it.current() )
            {
                removeContact( it.current() );
                ++it;
            }
        }
        category = category->nextSibling();
    }

    dlm.save();
    newListItem->setOpen( true );
}


void KWMailMergeTDEABCConfig::updateAvailable()
{
    _ui->mAvailableView->clear();
    _ui->mAvailableView->setRootIsDecorated( true );

    //
    // First append the addressees.
    //
    TQListViewItem* noCategory = new TQListViewItem( _ui->mAvailableView,
                                i18n("no category") );

    TQStringList& categories = _usedCategories ;
    categories.clear();

    TDEABC::AddressBook *addressBook = TDEABC::StdAddressBook::self();
    for( TDEABC::AddressBook::Iterator itAddr = addressBook->begin();
            itAddr != addressBook->end(); ++itAddr )
    {

        TQStringList entryCategories = itAddr->categories();
        for ( TQStringList::Iterator itCat = entryCategories.begin();
                itCat != entryCategories.end(); ++itCat )
        {
            int i = categories.findIndex(*itCat);

            // Create category, if not yet in listview and append item to it.
            if(  i == -1 )
            {
                TQListViewItem* category = new TQListViewItem( _ui->mAvailableView, *itCat );
                categories.append( *itCat );

                KWMailMergeTDEABCConfigListItem* item = new KWMailMergeTDEABCConfigListItem(
                                                          category, *itAddr );
            }
            // Append item to existing category in listview.
            else
            {
                KWMailMergeTDEABCConfigListItem* item = new KWMailMergeTDEABCConfigListItem(
                                                          _ui->mAvailableView->findItem(
                                                              *itCat, 0, TQt::ExactMatch),
                                                          *itAddr );
            }

        }
        // If Addressee does not belong to any category, append it to "no category".
        if( entryCategories.isEmpty() )
        {
            KWMailMergeTDEABCConfigListItem* item = new KWMailMergeTDEABCConfigListItem(
                                                      noCategory, *itAddr );
        }
    }

    //
    // Now append the distribution lists
    //
    TDEABC::DistributionListManager dlm ( addressBook );
    dlm.load();

    TQStringList distributionLists = dlm.listNames();
    TQListViewItem* distributionListsItem = new TQListViewItem( _ui->mAvailableView,
                                           i18n("Distribution Lists") );

    TQStringList::Iterator itDistributionLists;

    for( itDistributionLists = distributionLists.begin();
            itDistributionLists != distributionLists.end(); ++itDistributionLists )
    {
        TDEABC::DistributionList* list = dlm.list( *itDistributionLists );

        TDEABC::DistributionList::Entry::List entries = list->entries();

        TQListViewItem* listItem = new TQListViewItem( distributionListsItem,
                                  *itDistributionLists );

        TDEABC::DistributionList::Entry::List::Iterator itList;
        for ( itList = entries.begin(); itList != entries.end(); ++itList )
        {
            // Create a normal TQListViewItem and disable it, because this is not a
            // distribution-list-editor. KAddressbook should be used instead.
            TQListViewItem* item = new TQListViewItem(
                                      listItem, (*itList).addressee.formattedName() );
            item->setEnabled( false );
        }

    }
}



KWMailMergeTDEABCConfigListItem::KWMailMergeTDEABCConfigListItem( TQListView *parent,
        const TDEABC::Addressee& addressEntry ) : TQListViewItem( parent )
{
    setText( 0, addressEntry.formattedName() );
    _addressEntry = addressEntry;
}

KWMailMergeTDEABCConfigListItem::KWMailMergeTDEABCConfigListItem( TQListViewItem *parent,
        const TDEABC::Addressee& addressEntry ) : TQListViewItem( parent )
{
    setText( 0, addressEntry.formattedName() );
    _addressEntry = addressEntry;
}

KWMailMergeTDEABCConfigListItem::~KWMailMergeTDEABCConfigListItem()
{}

TDEABC::Addressee KWMailMergeTDEABCConfigListItem::addressee() const
{
    return _addressEntry;
}

TQString KWMailMergeTDEABCConfigListItem::text( int column ) const
{
    if( column == -1 )
    {
        return _addressEntry.uid();
    }
    else
    {
        return TQListViewItem::text( column );
    }
}

#include "KWMailMergeTDEABCConfig.moc"
