// -*- c++ -*-

/*
 *
 * Copyright (C) 2002 Richard 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., 51 Franklin Steet, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include <kdebug.h>
#include <qmap.h>

#include "channel.h"
#include "channelstore.h"
#include "channelio.h"
#include "kdetvchannelplugin.h"

#include "kdetv.h"

#include "pluginfactory.h"

//
// ChannelIO
//

static KdetvChannelPluginList *channel_io_formats = 0;
static QMap<QString, QString>* _fileFormatsRead = 0;
static QMap<QString, QString>* _fileFormatsWrite = 0;

ChannelIO::~ChannelIO()
{
    if (channel_io_formats != 0) {
        for ( Format *io = channel_io_formats->first(); io; io = channel_io_formats->next() ) {
            io->destroy();
        }
        channel_io_formats->clear();
    }
    channel_io_formats = 0;
    
    if (fileFormatsRead  != 0) delete _fileFormatsRead;
    _fileFormatsRead = 0;
    if (fileFormatsWrite != 0) delete _fileFormatsWrite;
    _fileFormatsWrite = 0;
}


void ChannelIO::registerFormats(Kdetv *ktv)
{
    QPtrList<PluginDesc>& channelPlugins(ktv->pluginFactory()->channelPlugins());
    
    for (PluginDesc *plug = channelPlugins.first(); plug;
         plug = channelPlugins.next()) {
        kdDebug() << "Found a plugin:" << endl;
        kdDebug() << plug->name << endl;
        kdDebug() << plug->author << endl;
        kdDebug() << plug->comment << endl;
        KdetvChannelPlugin *f = ktv->pluginFactory()->getChannelPlugin(plug);
        if (f)
            registerFormat(ktv, f);
    }
}

const QMap<QString, QString>& ChannelIO::fileFormatsRead(Kdetv* ktv)
{
    if (_fileFormatsRead == 0) {
        _fileFormatsRead = new QMap<QString, QString>;
        
        KdetvChannelPluginList* plugins = formats(ktv);
        for (KdetvChannelPlugin* p = plugins->first();
             p;
             p = plugins->next()) {
            if (p->canRead(p->formatName())) {
                (*_fileFormatsRead)[p->menuName()] = p->formatName();
            }
        }
    }
    return *_fileFormatsRead;
}

const QMap<QString, QString>& ChannelIO::fileFormatsWrite(Kdetv* ktv)
{
    if (_fileFormatsWrite == 0) {
        _fileFormatsWrite = new QMap<QString, QString>;
        
        KdetvChannelPluginList* plugins = formats(ktv);
        for (KdetvChannelPlugin* p = plugins->first();
             p;
             p = plugins->next()) {
            if (p->canWrite(p->formatName())) {
                (*_fileFormatsWrite)[p->menuName()] = p->formatName();
            }
        }
    }
    return *_fileFormatsWrite;
}

KdetvChannelPlugin* ChannelIO::guessFormat( Kdetv *ktv, const QString &filename, int flags )
{
    FormatList *formatList = formats(ktv);
    
    for ( Format *io = formatList->first(); io; io = formatList->next() ) {
        if (io->handlesFile(filename, flags))
            return io;
    }
    kdDebug() << "ChannelIO::guessFormat(...) returning csv for format" << endl;
    return findFormat(ktv, "csv", flags);
}

void ChannelIO::registerFormat( Kdetv *ktv, KdetvChannelPlugin *format )
{
    kdDebug() << "ChannelIO::registeringFormat(...) " << format->name() << endl;
    formats(ktv)->append( format );
}

KdetvChannelPluginList *ChannelIO::formats(Kdetv* ktv)
{
    if ( !channel_io_formats ) {
        kdDebug() << "ChannelIO::formats() Creating format list" << endl;
        
        channel_io_formats = new KdetvChannelPluginList;
        registerFormats(ktv);
    }
    return channel_io_formats;
}

KdetvChannelPlugin *ChannelIO::findFormat( Kdetv *ktv, const QString& fmt, int flags )
{
    kdDebug() << "ChannelIO::findFormat(...) " << fmt << ", flags=" << flags << endl;
    
    //
    // Search for a matching handler
    //
    FormatList *formatList = formats(ktv);
    
    for ( Format *io = formatList->first(); io; io = formatList->next() ) {
        if ( flags & Format::FormatRead ) {
            if ( io->canRead(fmt) ) {
                kdDebug() << "ChannelIO::findFormat(...) io " << io->name() << " can read " << fmt << endl;
                return io;
            }
        }
        if ( flags & Format::FormatWrite ) {
            if ( io->canWrite(fmt) ) {
                kdDebug() << "ChannelIO::findFormat(...) io " << io->name() << " can write " << fmt << endl;
                return io;
            }
        }
    }
    
    kdWarning() << "ChannelIO::findFormat(...) failed for " << fmt << endl;
    return 0;
}

bool ChannelIO::load( Kdetv *ktv, ChannelStore *store,
                      KdetvChannelPlugin::ChannelFileMetaInfo *info,
                      const QString &filename, const QString& fmt )
{
    kdDebug() << "ChannelIO::load(...) file='" << filename << "' format='" << fmt << "'" << endl;
    
    Format *io = (!fmt.isEmpty() ? findFormat( ktv, fmt, Format::FormatRead )
                  : guessFormat(ktv, filename, Format::FormatRead));
    if ( !io )
        return false;
    
    kdDebug() << "ChannelIO::load(...) using format '" << io->name() << "'" << endl;
    return io->load( store, info, filename, fmt );
}

bool ChannelIO::save( Kdetv *ktv, ChannelStore *store,
                      KdetvChannelPlugin::ChannelFileMetaInfo *info,
                      const QString &filename, const QString& fmt )
{
    kdDebug() << "ChannelIO::save(...) file='" << filename << "' format='" << fmt << "'" << endl;

    Format *io = findFormat( ktv, fmt, Format::FormatWrite );
    if ( !io )
        return false;
    
    kdDebug() << "ChannelIO::save(...) using format '" << io->name() << "'" << endl;
    return io->save( store, info, filename, fmt );
}


bool ChannelIO::load( Kdetv *ktv, ChannelStore *store,
                      KdetvChannelPlugin::ChannelFileMetaInfo *info,
                      QIODevice *dev, const QString& fmt )
{
    kdDebug() << "ChannelIO::load(...) format='" << fmt << "'" << endl;
    
    Format *io = findFormat( ktv, fmt, Format::FormatRead );
    if ( !io )
        return false;
    
    kdDebug() << "ChannelIO::load(...) using format '" << io->name() << "'" << endl;
    return io->load( store, info, dev, fmt );
}

bool ChannelIO::save( Kdetv *ktv, ChannelStore *store,
                      KdetvChannelPlugin::ChannelFileMetaInfo *info,
                      QIODevice*dev, const QString& fmt )
{
    kdDebug() << "ChannelIO::save(...) format='" << fmt << "'" << endl;

    Format *io = findFormat( ktv, fmt, Format::FormatWrite );
    if ( !io )
        return false;
    
    kdDebug() << "ChannelIO::save(...) using format '" << io->name() << "'" << endl;
    return io->save( store, info, dev, fmt );
}

