// -*- 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 <QList>

#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)
{
    QList<PluginDesc*>& channelPlugins(ktv->pluginFactory()->channelPlugins());

    for (QList<PluginDesc*>::iterator it = channelPlugins.begin();
         it != channelPlugins.end(); ++it) {
        kDebug() << "Found a plugin:";
        kDebug() << (*it)->name;
        kDebug() << (*it)->author;
        kDebug() << (*it)->comment;
        KdetvChannelPlugin *f = ktv->pluginFactory()->getChannelPlugin((*it));
        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;
    }
    kDebug() << "returning csv for format";
    return findFormat(ktv, "csv", flags);
}

void ChannelIO::registerFormat( Kdetv *ktv, KdetvChannelPlugin *format )
{
    kDebug() << format->objectName();
    formats(ktv)->append( format );
}

KdetvChannelPluginList *ChannelIO::formats(Kdetv* ktv)
{
    if ( !channel_io_formats ) {
        kDebug() << "Creating format list";

        channel_io_formats = new KdetvChannelPluginList;
        registerFormats(ktv);
    }
    return channel_io_formats;
}

KdetvChannelPlugin *ChannelIO::findFormat( Kdetv *ktv, const QString& fmt, int flags )
{
    kDebug() << fmt << ", flags=" << flags;

    //
    // 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) ) {
                kDebug() << "io " << io->objectName() << " can read " << fmt;
                return io;
            }
        }
        if ( flags & Format::FormatWrite ) {
            if ( io->canWrite(fmt) ) {
                kDebug() << "io " << io->objectName() << " can write " << fmt;
                return io;
            }
        }
    }

    kWarning() << "failed for " << fmt;
    return 0;
}

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

    Format *io = (!fmt.isEmpty() ? findFormat( ktv, fmt, Format::FormatRead )
                  : guessFormat(ktv, filename, Format::FormatRead));
    if ( !io )
        return false;

    kDebug() << "using format '" << io->objectName() << "'";
    return io->load( store, info, filename, fmt );
}

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

    Format *io = findFormat( ktv, fmt, Format::FormatWrite );
    if ( !io )
        return false;

    kDebug() << "using format '" << io->objectName() << "'";
    return io->save( store, info, filename, fmt );
}


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

    Format *io = findFormat( ktv, fmt, Format::FormatRead );
    if ( !io )
        return false;

    kDebug() << "using format '" << io->objectName() << "'";
    return io->load( store, info, dev, fmt );
}

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

    Format *io = findFormat( ktv, fmt, Format::FormatWrite );
    if ( !io )
        return false;

    kDebug() << "using format '" << io->objectName() << "'";
    return io->save( store, info, dev, fmt );
}

