// Copyright (c) 2000-2001 Brad Hughes <bhughes@trolltech.com>
//
// Use, modification and distribution is allowed without limitation,
// warranty, or liability of any kind.
//
#include <QStringList>
#include <QDir>
#include <stdio.h>
#include "audioparameters.h"
#include "qmmpsettings.h"
#include "buffer.h"
#include "volumehandler.h"
#include "qmmp.h"
#include "qmmpplugincache_p.h"
#include "output.h"

Output::Output()
{}

void Output::configure(quint32 freq, ChannelMap map, Qmmp::AudioFormat format)
{
    m_frequency = freq;
    m_chan_map = map;
    m_format = format;
    m_sample_size = AudioParameters::sampleSize(format);
}

AudioParameters Output::audioParameters() const
{
    return AudioParameters(m_frequency, m_chan_map, m_format);
}

quint32 Output::sampleRate() const
{
    return m_frequency;
}

int Output::channels() const
{
    return m_chan_map.count();
}

const ChannelMap &Output::channelMap() const
{
    return m_chan_map;
}

Qmmp::AudioFormat Output::format() const
{
    return m_format;
}

int Output::sampleSize() const
{
    return m_sample_size;
}

void Output::suspend()
{}

void Output::resume()
{}

void Output::setTrackInfo(const TrackInfo &info)
{
    Q_UNUSED(info);
}

Output::~Output()
{}

// static methods
QList<QmmpPluginCache*> *Output::m_cache = nullptr;

void Output::loadPlugins()
{
    if (m_cache)
        return;

    m_cache = new QList<QmmpPluginCache *>;
    QSettings settings;
    for(const QString &filePath : Qmmp::findPlugins(u"Output"_s))
    {
        QmmpPluginCache *item = new QmmpPluginCache(filePath, &settings);
        if(item->hasError())
        {
            delete item;
            continue;
        }
        m_cache->append(item);
    }
    QmmpPluginCache::cleanup(&settings);
}

Output *Output::create ()
{
    loadPlugins();
    Output *output = nullptr;
    if (m_cache->isEmpty ())
    {
        qCDebug(core) << "unable to find output plugins";
        return output;
    }
    OutputFactory *fact = Output::currentFactory();
    if (fact)
        output = fact->create ();
    return output;
}

QList<OutputFactory *> Output::factories()
{
    loadPlugins();
    QList<OutputFactory *> list;
    for(QmmpPluginCache *item : std::as_const(*m_cache))
    {
        if(item->outputFactory())
            list.append(item->outputFactory());
    }
    return list;
}

QString Output::file(const OutputFactory *factory)
{
    loadPlugins();
    for(const QmmpPluginCache *item : std::as_const(*m_cache))
    {
        if(item->shortName() == factory->properties().shortName)
            return item->file();
    }
    return QString();
}

void Output::setCurrentFactory(const OutputFactory *factory)
{
    loadPlugins();
    if (file(factory).isEmpty())
        return;
    QSettings settings;
    settings.setValue(u"Output/current_plugin"_s, factory->properties().shortName);
}

OutputFactory *Output::currentFactory()
{
    loadPlugins();

    QSettings settings;
#ifdef QMMP_DEFAULT_OUTPUT
    QString name = settings.value(u"Output/current_plugin"_s, QMMP_DEFAULT_OUTPUT).toString();
#else
#ifdef Q_OS_LINUX
    QString name = settings.value(u"Output/current_plugin"_s, u"alsa"_s).toString();
#elif defined Q_OS_WIN
    QString name = settings.value(u"Output/current_plugin"_s, u"wasapi"_s).toString();
#elif defined Q_OS_MAC
    QString name = settings.value(u"Output/current_plugin"_s, u"qtmultimedia"_s).toString();
#else
    QString name = settings.value(u"Output/current_plugin"_s, u"oss4"_s).toString();
#endif
#endif //QMMP_DEFAULT_OUTPUT
    for(QmmpPluginCache *item : std::as_const(*m_cache))
    {
        if (item->shortName() == name && item->outputFactory())
            return item->outputFactory();
    }
    if(!m_cache->isEmpty())
        return m_cache->at(0)->outputFactory();
    return nullptr;
}
