/* 
   Copyright (c) 2002 Malte Starostik <malte@kde.org>

   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; see the file COPYING.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/

#include <klocale.h>
#include <qtextstream.h>
#include <qfile.h>
#include <kdebug.h>

#include "channel.h"
#include "channelstore.h"

#include "channelioxawtv.h"
#include "frequencies.h"

struct ChannelIOFormatXawtv::ChannelInfo
{
	ChannelInfo() {}
	ChannelInfo( const QString& a_name ) : name( a_name ) {}
	QString name;
	QMap< QString, QString > params;
};

ChannelIOFormatXawtv::ChannelIOFormatXawtv(Kdetv *ktv, QObject *parent, const char *name)
    : KdetvChannelPlugin(ktv, "XawTV Channels", parent, name)
{
    _fmtName  = "xawtv";
	_menuName = i18n("XawTV");
	_flags    = FormatRead;
}

bool ChannelIOFormatXawtv::load(ChannelStore *store, ChannelFileMetaInfo *info,
                                const QString &filename, const QString& /* fmt */)
{
	QFile file(filename);
	if (!file.open(IO_ReadOnly)) {
	    return false;
	}

	// xawtv's config file is in INI-style format, yet we can't use KConfig since
	// the order of sections determines the channel numbers. Sigh.

	QTextStream ts( static_cast<QIODevice*>(&file) );
	QString section;

	// Store them here temporarily. Might be the [global] and/or [defaults]
	// sections come last in the file, so we can't translate channel => frequency
	// etc. before reading the whole file.
	QValueList< ChannelInfo > channels;
	QValueList< ChannelInfo >::Iterator channel = channels.end();
	while ( !ts.atEnd() )
        {
            QString line = ts.readLine();
            if ( line.startsWith("#include") ) {
                QString name = filename.section("/", 0, -2) + "/" + line.section("\"", 1, 1);
                if (!load(store, info, name, QString::null) ) {
                    return false;
                }
                continue;
            }
            if ( line.isEmpty() || line[ 0 ] == '#' || line[ 0 ] == '%' ) continue;
            if ( line[ 0 ] == '[' )
                {
                    int en = line.find( ']' );
                    if (en == -1) continue;
                    section = line.mid( 1, en - 1 );
                    if ( section == "defaults" || section == "global" || section == "launch" || section == "eventmap" )
                        channel = channels.end();
                    else channel = channels.append( ChannelInfo( section ) );
                    continue;
                }
            int en = line.find( '=' );
            if (en == -1) continue;
            QString key = line.left( en ).stripWhiteSpace();
            QString value = line.mid( en + 1 ).stripWhiteSpace(); // FIXME? should not strip trailing whitespace

            if ( channel == channels.end() )
                {
                    if ( section == "global" )
                        {
                            if ( key == "freqtab" ) setFrequencyTable( value );
                        }
                }
            else ( *channel ).params.replace( key, value );
        }

	for ( QValueList< ChannelInfo >::ConstIterator it = channels.constBegin();
          it != channels.constEnd();
          ++it )
        {
            Channel *channel = new Channel( store );
            channel->setName( (*it).name );
            unsigned long freq;
            if ( !( *it ).params[ "freq" ].isEmpty() )
                freq = ( *it ).params[ "freq" ].toULong();
            else
                freq = channelToFrequency( ( *it ).params[ "channel" ] );
            if ( !( *it ).params[ "fine" ].isEmpty() )
                freq += (unsigned long) 62.5 * ( *it ).params[ "fine" ].toLong();
            channel->setChannelProperty( "frequency", (Q_ULLONG)freq );
            if ( !( *it ).params[ "norm" ].isEmpty() )
                channel->setChannelProperty( "encoding", ( *it ).params[ "norm" ].lower() );
            if ( !( *it ).params[ "input" ].isEmpty() )
                channel->setChannelProperty( "source", ( *it ).params[ "input" ].lower() );
            store->addChannel( channel );
        }

	return true;
}

void ChannelIOFormatXawtv::setFrequencyTable( const QString& name )
{
	for ( CHANLISTS* list = chanlists; list->name; ++list )
		if ( name == list->name )
            {
                chanlist = list->list;
                chancount = list->count;
                return;
            }
	kdWarning() << "Unknown frequency table: " << name << endl;
}

unsigned long ChannelIOFormatXawtv::channelToFrequency( const QString& name )
{
	for ( int i = 0; i < chancount; ++i )
		if ( name == chanlist[ i ].name ) return chanlist[ i ].freq;
	kdWarning() << "Unknown channel name: " << name << endl;
	return 0;
}

extern "C" KDETV_EXPORT KdetvChannelPlugin* create_xawtvchannels(Kdetv *ktv)
{
	return new ChannelIOFormatXawtv(ktv, 0L, "XawTV Channel Plugin");
}

// vim: ts=4 sw=4 noet
