/*
 *
 * Copyright (C) 2002 George Staikos <staikos@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 <qstring.h>
#include <qfile.h>

#include <assert.h>

#include <kdebug.h>
#include <klocale.h>
#include <kglobal.h>
#include <kstandarddirs.h>

#include "qtvision.h"
#include "channel.h"
#include "channelio.h"

#include "channelstore.h"
#include "channelstore.moc"

ChannelStore::ChannelStore( QtVision *qtv, QObject *parent, const char *name )
    : QObject( parent, name ),
      DCOPObject( "QtVisionChannelStoreIface" ),
      _qtv(qtv)
{
#ifdef RICH
    _file.setName("QtVisionChannels");
    _file.setFile("QtVisionChannels");
    _file.setType("text/plain");
#endif

    silentModifications = false;
    _channels.setAutoDelete(true);
}


ChannelStore::~ChannelStore()
{
}

DCOPRef ChannelStore::channelIfaceAt( int idx )
{
    return DCOPRef( channelAt(idx) );
}

void ChannelStore::clear()
{
    _channels.clear(); 
}

bool ChannelStore::reload()
{ 
    emit aboutToReload();
    clear();
    bool rc = load(_file); 
    return rc;
}

bool ChannelStore::load( const QString &file, const char *fmt ) {

    _file = file;
    if ( _file.isEmpty() ) {
        _file = KGlobal::dirs()->saveLocation("qtvision") + "channels.xml";
    }

    silentModifications = true;
    bool rc = ChannelIO::load( _qtv, this, _file, fmt );
    silentModifications = false;
    if (rc)
        loaded();
    return rc;
}

bool ChannelStore::save( const QString &file, const char *fmt ) {

    if (!file.isEmpty())
        _file = file;
   
    if ( _file.isEmpty() ) {
        _file = KGlobal::dirs()->saveLocation("qtvision") + "channels.xml";
    }

    silentModifications = true;
    bool rc = ChannelIO::save( _qtv, this, _file, fmt );
    silentModifications = false;
    if (rc)
        saved();
    return rc;
}

void ChannelStore::addChannel( Channel *channel )
{
    assert(channel);

    if ( channel->number() <= 0 ) {
	channel->setNumber( _channels.last() ? _channels.last()->number() + 1 : 2 );
    } else {
        // Don't allow duplicate channels by number.
        for (Channel *c = _channels.first(); c; c = _channels.next()) {
            if (c->number() == channel->number()) {
                _channels.remove(c);
                break;
            }
        }
    }

    if ( channel->name().isNull() || channel->name().isEmpty() )
	channel->setName( i18n("Channel %1").arg(channel->number()) );

    _channels.inSort( channel );
    if (!silentModifications)
        emit channelAdded(channel);
}

Channel* ChannelStore::addChannel( ulong freq )
{
    Channel *chan = new Channel( this );
    if (_channels.last()) {
       chan->setNumber( _channels.last()->number() + 1 );
    } else {
       chan->setNumber( 2 ); // Or should we start at 1?  What is more common?
    }
    chan->setFreq( freq );
    addChannel( chan );
    return chan;
}

void ChannelStore::addChannels( const ChannelStore& nstore)
{
    silentModifications = true;
    Channel* ch;
    for (QPtrListIterator<Channel> it(nstore._channels); (ch = it.current()) != 0; ++it) {
	Channel* channel = new Channel(this);
	channel->setName( ch->name() );
	channel->setFreq( ch->freq() );
	channel->setEnabled( ch->enabled() );
	channel->setNumber( 0 );
	addChannel(channel);
    }
    silentModifications = false;
    loaded();
}

Channel *ChannelStore::channelNumber(int n)
{
    Channel *c = 0;
    for (c = _channels.first(); c; c = _channels.next()) {
        if (c->number() == n)
            break;
    }
    return c;
}

void ChannelStore::renumber( int start )
{
    for ( Channel *c = _channels.first(); c; c = _channels.next() ) {
	c->setNumber(start++);
    }
    loaded();
}

void ChannelStore::renumber()
{
    renumber(2);
}

Channel *ChannelStore::channelAfter( Channel *channel )
{
    int rc = _channels.findRef(channel);
    if (rc == -1 || rc >= (int)_channels.count()-1)
        return _channels.at(0);

    return _channels.at(rc+1);
}

Channel *ChannelStore::channelBefore( Channel *channel )
{
    int rc = _channels.findRef(channel);
    if (rc == -1)
        return _channels.at(0);

    if (rc == 0)
        return _channels.at(_channels.count()-1);

    return _channels.at(rc-1);
}

int ChannelStore::removeChannelNumber( int n )
{
    for (Channel *c = _channels.first(); c; c = _channels.next()) {
        if (c->number() == n) {
            return removeChannel(c);
        }
    }
        
    return -1;
}

int ChannelStore::removeChannel( int idx )
{
    Channel *tmp = _channels.at(idx);
    int rc = _channels.remove(idx) ? 0 : -1;

    if (rc == 0 && !silentModifications)
        emit channelRemoved(tmp);
        
    return rc;
}

int ChannelStore::removeChannel( Channel *channel )
{
    Channel *tmp = channel;
    int rc = _channels.remove(channel) ? 0 : -1;

    if (rc == 0 && !silentModifications)
        emit channelRemoved(tmp);

    return rc;
}

