/*
 *
 * Copyright (C) 2002 George Staikos <staikos@kde.org>
 * Copyright (C) 2002 Rich Moore <rich@kde.org>
 *
 * 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., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */


#include <qobject.h>
#include <klocale.h>
#include <kdebug.h>
#include "channel.h"
#include "channelstore.h"

#include "channeleditor.h"
#include "channeleditor.moc"


#define CLI_RTTI 589425

int ChannelListItem::rtti() const {
   return CLI_RTTI;
}


ChannelListItem::ChannelListItem(KListView* parent, Channel* ch, bool sso)
                :KListViewItem(parent, QString::number(ch->number()), ch->name()),
                 c(ch), _showSelectedOnly(sso)
{
    if ( (!c->enabled()) && (_showSelectedOnly) )
        this->setVisible(false);
    
    connect(c, SIGNAL(changed()), this, SLOT(updateFields()));
}


ChannelListItem::~ChannelListItem() {
}


void ChannelListItem::updateFields() {
    if ( (!c->enabled()) && (_showSelectedOnly) )
        this->setVisible(false);
    else
        this->setVisible(true);

    if (c->name() != text(1))
        setText(1, c->name());
    
    if (QString::number(c->number()) != text(0))
        setText(0, QString::number(c->number()));
}


int ChannelListItem::compare(QListViewItem *i, int col, bool ascending) const {
int me, him;

        if (i->rtti() != CLI_RTTI)
            return KListViewItem::compare(i, col, ascending);

        switch (col) {
        case 0:
            me = c->number();
            him = static_cast<ChannelListItem*>(i)->c->number();

            if (me == him) return 0;

            return (ascending ? 1 : -1) * (me > him ? 1 : -1);
         break;
        default:
         break;
        }

return KListViewItem::compare(i, col, ascending);
}


ChannelEditor::ChannelEditor( QWidget *parent, const char *name, bool showSelectedOnly )
    : KListView( parent, name ? name : "channel_editor" ),
      cs(0), _showSelectedOnly(showSelectedOnly), prev(0)
{
    addColumn( "", -10 );
    addColumn( i18n("Name") );

    setResizeMode( LastColumn );
    setAllColumnsShowFocus( true );
    setColumnAlignment( 0, AlignCenter );
    setColumnAlignment( 1, AlignLeft );

    setItemsRenameable( true );
    setRenameable( 0, false );
    setRenameable( 1, true );

    connect( this, SIGNAL( itemRenamed(QListViewItem *, const QString &, int) ),
             this, SLOT( renameItem(QListViewItem *, const QString &, int) ) );
    connect( this, SIGNAL( selectionChanged(QListViewItem*) ),
             this, SLOT( requestChange(QListViewItem*) ) );
}

ChannelEditor::~ChannelEditor()
{
}

void ChannelEditor::setChannels( ChannelStore *chans )
{
    clear();
    cs = chans;
    createItems();
    connect(cs, SIGNAL(channelAdded(Channel*)), this, SLOT(reloadChannels()));
    connect(cs, SIGNAL(channelRemoved(Channel*)), this, SLOT(reloadChannels()));
    connect(cs, SIGNAL(aboutToReload()), this, SLOT(storeCurrentChannel()));
    connect(cs, SIGNAL(loaded()), this, SLOT(restoreCurrentChannel()));
}

void ChannelEditor::createItems()
{
    if ( !cs )
      return;

    for ( uint i = 0 ; i < cs->count(); i++ ) {
      Channel *c = cs->channelAt( i );
      if ( c )
        (void) new ChannelListItem( this, c, _showSelectedOnly );
    }
}

void ChannelEditor::renameItem( QListViewItem *item, const QString &str, int /*col*/ )
{
    if (!item || item->rtti() != CLI_RTTI)
        return;

    ChannelListItem *l = static_cast<ChannelListItem*>(item);
    l->c->setName( str );
    cs->save();
    emit channelModified( l->c );
}


void ChannelEditor::requestChange(QListViewItem *item)
{
    if (!item || item->rtti() != CLI_RTTI)
        return;

    ChannelListItem *l = static_cast<ChannelListItem*>(item);
    emit channelSelected(l->c);
}


void ChannelEditor::ensureSelected(Channel *ch) {
    ChannelListItem *x = static_cast<ChannelListItem*>(firstChild());

    while (x) {
        if (x->rtti() == CLI_RTTI && x->c == ch) {
            // Block signals here before selecting the current
            // channel inorder to avoid ::setChannel from being
            // invoked again...
            bool block = signalsBlocked();        
            blockSignals (true);
            setCurrentItem(x);
            ensureItemVisible(x);
            setSelected(x, true);
            repaintItem(x);
            x->setSelected(true);
            blockSignals (block);
            //kdDebug() << "Ensuring item is selected: " << x->c->number() << endl;
            return;
        }
        x = static_cast<ChannelListItem *>(x->nextSibling());
    }
}


void ChannelEditor::reloadChannels() {
    clear();
    createItems();
    //resize(columnWidth(0)+columnWidth(1)+8, height());
}


void ChannelEditor::slotSetShowSelectedOnly(bool sso)
{
    _showSelectedOnly = sso;
    storeCurrentChannel();

    // re-create items & restore selection
    restoreCurrentChannel();
    return;
} // showSelectedOnly


void ChannelEditor::storeCurrentChannel() {
    ChannelListItem* l = static_cast<ChannelListItem*>(currentItem());
    prev = l ? l->c->number() : 0;
}


void ChannelEditor::restoreCurrentChannel() {
    reloadChannels();
    if (prev != 0)
        ensureSelected(cs->channelNumber(prev));
}
