/*
 * albumart.cc
 * Copyright 2014 William Pitcock
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions, and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions, and the following disclaimer in the documentation
 *    provided with the distribution.
 *
 * This software is provided "as is" and without any warranty, express or
 * implied. In no event shall the authors be liable for any damages arising from
 * the use of this software.
 */

#include <QApplication>
#include <QLabel>
#include <QPixmap>

#include <libaudcore/drct.h>
#include <libaudcore/i18n.h>
#include <libaudcore/plugin.h>
#include <libaudcore/hook.h>
#include <libaudcore/templates.h>

#include <libaudqt/libaudqt.h>

class AlbumArtQt : public GeneralPlugin
{
public:
    static constexpr PluginInfo info = {
        N_("Album Art"),
        PACKAGE,
        nullptr, // about
        nullptr, // prefs
        PluginQtOnly
    };

    constexpr AlbumArtQt () : GeneralPlugin (info, false) {}
    void * get_qt_widget () override;
};

class ArtLabel : public QLabel
{
public:
    ArtLabel (QWidget * parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags ())
        : QLabel (parent, f)
    {
        init ();
    }

    ArtLabel (const QString & text, QWidget * parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags ())
        : QLabel (text, parent, f)
    {
        init ();
    }

    void update_art ()
    {
        origPixmap = QPixmap (audqt::art_request_current (0, 0));
        qreal r = qApp->devicePixelRatio ();
        origPixmap.setDevicePixelRatio (r);
        origSize = origPixmap.size ();
        drawArt ();
    }

    void clear ()
    {
        QLabel::clear ();
        origPixmap = QPixmap ();
    }

protected:
    void resizeEvent (QResizeEvent * event) override
    {
        QLabel::resizeEvent (event);

        QPixmap pm;
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
        pm = pixmap ();
#elif QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
        pm = pixmap (Qt::ReturnByValue);
#else
        if (const QPixmap * ptr = pixmap ())
            pm = *ptr;
#endif
        if (! origPixmap.isNull () && ! pm.isNull () &&
            (size ().width () <= origSize.width () + MARGIN ||
            size ().height () <= origSize.height () + MARGIN ||
            pm.size () != origSize))
        {
            drawArt ();
        }
    }

private:
    static constexpr int MARGIN = 4;

    const HookReceiver<ArtLabel>
        update_hook{"playback ready", this, & ArtLabel::update_art},
        clear_hook{"playback stop", this, & ArtLabel::clear};

    QPixmap origPixmap;
    QSize origSize;

    void init ()
    {
        clear ();
        setMinimumSize (MARGIN + 1, MARGIN + 1);
        setAlignment (Qt::AlignCenter);

        if (aud_drct_get_ready ())
            update_art ();
    }

    void drawArt ()
    {
        qreal r = qApp->devicePixelRatio ();
        QSize currentSize = size ();

        if (aud::abs (r - 1.0) <= 0.01 &&
            origSize.width () <= currentSize.width () - MARGIN &&
            origSize.height () <= currentSize.height () - MARGIN)
        {
            // If device pixel ratio is close to 1:1 (within 1%) and art is
            // smaller than widget, set pixels directly w/o scaling
            setPixmap (origPixmap);
        }
        else
        {
            // Otherwise scale image with device pixel ratio, but limit size to
            // widget dimensions.
            auto width = std::min (r * (currentSize.width () - MARGIN),
                                   r * origSize.width ());
            auto height = std::min (r * (currentSize.height () - MARGIN),
                                    r * origSize.height ());

            setPixmap (origPixmap.scaled (width, height, Qt::KeepAspectRatio,
                                          Qt::SmoothTransformation));
        }

#ifdef Q_OS_MAC
        repaint ();
#endif
    }
};

void * AlbumArtQt::get_qt_widget ()
{
    return new ArtLabel;
}

EXPORT AlbumArtQt aud_plugin_instance;
