/* This file is part of libhud-qt
 * Copyright 2013 Canonical Ltd.
 *
 * libhud-qt is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version 3,
 * as published by the Free Software Foundation.
 *
 * libhud-qt is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranties of
 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
 * PURPOSE.  See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "slider-parameter.h"

// needed for glib includes.
#undef signals
#include <libhud-2/hud.h>

using namespace Ubuntu::HUD;

class Ubuntu::HUD::SliderParameter::Private
{
public:
    float min;
    float max;
    float step;
    float value;
    bool live;
    QString label;

    GSimpleAction *simpleAction;
    GMenuItem *menuitem;

    static int actionNumber;
    static int generateActionNumber();

    static void action_activated(GSimpleAction *action,
                                 GVariant      *parameter,
                                 gpointer       user_data);
};

int SliderParameter::Private::actionNumber = 0;
int
SliderParameter::Private::generateActionNumber()
{
    // thread safety...
    return SliderParameter::Private::actionNumber++;
}

void
SliderParameter::Private::action_activated(GSimpleAction *simpleaction,
                                           GVariant      *parameter,
                                           gpointer       user_data)
{
    SliderParameter *that = qobject_cast<SliderParameter *>((QObject *)user_data);
    if (that == 0) {
        qWarning("CAST FAILED.");
        return;
    }

    float value = g_variant_get_double(parameter);
    that->setValue(value);
}


SliderParameter::SliderParameter(QObject *parent)
    : Parameter(parent)
{
    g_type_init();

    d = new Private;

    d->min = 0.0;
    d->max = 100.0;
    d->step = 1.0;
    d->value = 0.0;
    d->live = false;

    QString actionid = QString("action-qt-slider-param-") + QString::number(SliderParameter::Private::generateActionNumber());

    d->simpleAction = g_simple_action_new(qPrintable(actionid), G_VARIANT_TYPE_DOUBLE);
    g_signal_connect(G_OBJECT(d->simpleAction), "activate", G_CALLBACK(SliderParameter::Private::action_activated), this);

    d->menuitem = g_menu_item_new("", qPrintable(QString("hud.") + actionid));
    g_menu_item_set_attribute_value(d->menuitem, "parameter-type", g_variant_new_string("slider"));
    g_menu_item_set_attribute_value(d->menuitem, "min", g_variant_new_double(d->min));
    g_menu_item_set_attribute_value(d->menuitem, "max", g_variant_new_double(d->max));
    g_menu_item_set_attribute_value(d->menuitem, "step", g_variant_new_double(d->step));
    g_menu_item_set_attribute_value(d->menuitem, "value", g_variant_new_double(d->value));
    g_menu_item_set_attribute_value(d->menuitem, "live", g_variant_new_boolean(d->live));
    g_menu_item_set_attribute_value(d->menuitem, G_MENU_ATTRIBUTE_LABEL, g_variant_new_string(qPrintable(d->label)));
}

SliderParameter::~SliderParameter()
{
    delete d;
}


float
SliderParameter::minimumValue() const
{
    return d->min;
}

void
SliderParameter::setMinimumValue(float value)
{
    if (qFuzzyCompare(d->min, value))
        return;

    if (value > d->value) {
        d->value = value;
        emit valueChanged(value);
        g_menu_item_set_attribute_value(d->menuitem,
                                        "value",
                                        g_variant_new_double(value));
    }

    d->min = value;
    emit minimumValueChanged(value);
    g_menu_item_set_attribute_value(d->menuitem,
                                    "min",
                                    g_variant_new_double(value));
}

float
SliderParameter::maximumValue() const
{
    return d->max;
}

void
SliderParameter::setMaximumValue(float value)
{
    if (qFuzzyCompare(d->max, value))
        return;

    if (value < d->value) {
        d->value = value;
        emit valueChanged(value);
        g_menu_item_set_attribute_value(d->menuitem,
                                        "value",
                                        g_variant_new_double(value));
    }

    d->max = value;
    emit maximumValueChanged(value);
    g_menu_item_set_attribute_value(d->menuitem,
                                    "max",
                                    g_variant_new_double(value));
}

float
SliderParameter::stepSize() const
{
    return d->step;
}

void
SliderParameter::setStepSize(float value)
{
    if (qFuzzyCompare(d->step, value))
        return;

    d->step = value;
    emit stepSizeChanged(value);
    g_menu_item_set_attribute_value(d->menuitem,
                                    "step",
                                    g_variant_new_double(value));
}

float
SliderParameter::value() const
{
    return d->value;
}

void
SliderParameter::setValue(float value)
{
    if (qFuzzyCompare(d->value, value))
        return;

    d->value = value;
    emit valueChanged(value);
    g_menu_item_set_attribute_value(d->menuitem,
                                    "value",
                                    g_variant_new_double(value));
}

bool
SliderParameter::live() const
{
    return d->live;
}

void
SliderParameter::setLive(bool value)
{
    if (d->live == value)
        return;

    d->live = value;
    emit liveChanged(value);
    g_menu_item_set_attribute_value(d->menuitem,
                                    "live",
                                    g_variant_new_boolean(value));
}

QString
SliderParameter::label() const
{
    return d->label;
}

void
SliderParameter::setLabel(const QString &label)
{
    if (d->label == label)
        return;
    d->label = label;
    emit labelChanged(label);
    g_menu_item_set_attribute_value(d->menuitem,
                                    G_MENU_ATTRIBUTE_LABEL,
                                    g_variant_new_string(qPrintable(label)));
}

void
SliderParameter::magic(void **menuitem, void **gaction)
{
    *menuitem = d->menuitem;
    *gaction  = d->simpleAction;
}
