/*
 * Carla UI bridge code
 * Copyright (C) 2011-2012 Filipe Coelho <falktx@falktx.com>
 *
 * 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
 * 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.
 *
 * For a full copy of the GNU General Public License see the COPYING file
 */

#include "carla_bridge_client.h"

#ifdef BRIDGE_LV2_X11
#  error X11 UI uses Qt4
#endif

#include <gtk/gtk.h>
#include <QtCore/QSettings>

CARLA_BRIDGE_START_NAMESPACE

// -------------------------------------------------------------------------

class CarlaToolkitGtk2 : public CarlaToolkit
{
public:
    CarlaToolkitGtk2(const char* const title)
        : CarlaToolkit(title),
          settings("Cadence", "Carla-Gtk2UIs")
    {
        qDebug("CarlaToolkitGtk2::CarlaToolkitGtk2(%s)", title);

        window = nullptr;

        lastX = lastY = 0;
        lastWidth = lastHeight = 0;
    }

    ~CarlaToolkitGtk2()
    {
        qDebug("CarlaToolkitGtk2::~CarlaToolkitGtk2()");
    }

    void init()
    {
        qDebug("CarlaToolkitGtk2::init()");

        static int argc = 0;
        static char** argv = { nullptr };
        gtk_init(&argc, &argv);
    }

    void exec(CarlaClient* const client, const bool showGui)
    {
        qDebug("CarlaToolkitGtk2::exec(%p)", client);
        CARLA_ASSERT(client);

        m_client = client;

        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        gtk_container_add(GTK_CONTAINER(window), (GtkWidget*)client->getWidget());

        gtk_window_set_resizable(GTK_WINDOW(window), client->isResizable());
        gtk_window_set_title(GTK_WINDOW(window), m_title);

        gtk_window_get_position(GTK_WINDOW(window), &lastX, &lastY);
        gtk_window_get_size(GTK_WINDOW(window), &lastWidth, &lastHeight);

        if (settings.contains(QString("%1/pos_x").arg(m_title)))
        {
            lastX = settings.value(QString("%1/pos_x").arg(m_title), lastX).toInt();
            lastY = settings.value(QString("%1/pos_y").arg(m_title), lastY).toInt();
            gtk_window_move(GTK_WINDOW(window), lastX, lastY);

            if (client->isResizable())
            {
                lastWidth  = settings.value(QString("%1/width").arg(m_title), lastWidth).toInt();
                lastHeight = settings.value(QString("%1/height").arg(m_title), lastHeight).toInt();
                gtk_window_resize(GTK_WINDOW(window), lastWidth, lastHeight);
            }
        }

        g_timeout_add(50, gtk_ui_timeout, this);
        g_signal_connect(window, "destroy", G_CALLBACK(gtk_ui_destroy), this);

        if (showGui)
            show();
        else
            m_client->sendOscUpdate();

        // Main loop
        gtk_main();
    }

    void quit()
    {
        qDebug("CarlaToolkitGtk2::quit()");

        if (window)
        {
            gtk_widget_destroy(window);
            gtk_main_quit();

            window = nullptr;
        }

        m_client = nullptr;
    }

    void show()
    {
        qDebug("CarlaToolkitGtk2::show()");
        CARLA_ASSERT(window);

        if (window)
            gtk_widget_show_all(window);
    }

    void hide()
    {
        qDebug("CarlaToolkitGtk2::hide()");
        CARLA_ASSERT(window);

        if (window)
            gtk_widget_hide_all(window);
    }

    void resize(int width, int height)
    {
        qDebug("CarlaToolkitGtk2::resize(%i, %i)", width, height);
        CARLA_ASSERT(window);

        if (window)
            gtk_window_resize(GTK_WINDOW(window), width, height);
    }

    // ---------------------------------------------------------------------

protected:
    void handleDestroy()
    {
        qDebug("CarlaToolkitGtk2::handleDestroy()");

        window = nullptr;
        m_client = nullptr;

        settings.setValue(QString("%1/pos_x").arg(m_title), lastX);
        settings.setValue(QString("%1/pos_y").arg(m_title), lastY);
        settings.setValue(QString("%1/width").arg(m_title), lastWidth);
        settings.setValue(QString("%1/height").arg(m_title), lastHeight);
        settings.sync();
    }

    gboolean handleTimeout()
    {
        if (window)
        {
            gtk_window_get_position(GTK_WINDOW(window), &lastX, &lastY);
            gtk_window_get_size(GTK_WINDOW(window), &lastWidth, &lastHeight);
        }

        return m_client ? m_client->oscIdle() : false;
    }

    // ---------------------------------------------------------------------

private:
    GtkWidget* window;
    QSettings settings;

    gint lastX, lastY, lastWidth, lastHeight;

    static void gtk_ui_destroy(GtkWidget*, gpointer data)
    {
        CarlaToolkitGtk2* const _this_ = (CarlaToolkitGtk2*)data;
        _this_->handleDestroy();

        gtk_main_quit();
    }

    static gboolean gtk_ui_timeout(gpointer data)
    {
        CarlaToolkitGtk2* const _this_ = (CarlaToolkitGtk2*)data;
        return _this_->handleTimeout();
    }
};

// -------------------------------------------------------------------------

CarlaToolkit* CarlaToolkit::createNew(const char* const title)
{
    return new CarlaToolkitGtk2(title);
}

CARLA_BRIDGE_END_NAMESPACE
