# -*- coding: utf-8 -*-
# Copyright 2012 Christoph Reiter
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation

from gi.repository import Gst, Gtk, GObject

from quodlibet.plugins.gstelement import GStreamerPlugin
from quodlibet import qltk
from quodlibet import config
from quodlibet.util import gobject_weak


_PLUGIN_ID = "compressor"

_SETTINGS = {
    "threshold": [_("_Threshold:"),
                  _("Threshold until the filter is activated"), 1.0],
    "ratio": [_("R_atio:"), _("Compression ratio"), 1.0],
}


def get_cfg(option):
    cfg_option = "%s_%s" % (_PLUGIN_ID, option)
    default = _SETTINGS[option][2]

    if option == "threshold":
        return config.getfloat("plugins", cfg_option, default)
    elif option == "ratio":
        return config.getfloat("plugins", cfg_option, default)


def set_cfg(option, value):
    cfg_option = "%s_%s" % (_PLUGIN_ID, option)
    if get_cfg(option) != value:
        config.set("plugins", cfg_option, value)


class Preferences(Gtk.VBox):
    __gsignals__ = {
        'changed': (GObject.SignalFlags.RUN_LAST, None, tuple()),
    }

    def __init__(self):
        super(Preferences, self).__init__(spacing=12)

        table = Gtk.Table(2, 2)
        table.set_col_spacings(6)
        table.set_row_spacings(6)

        labels = {}
        for idx, key in enumerate(["threshold", "ratio"]):
            text, tooltip = _SETTINGS[key][:2]
            label = Gtk.Label(label=text)
            labels[key] = label
            label.set_tooltip_text(tooltip)
            label.set_alignment(0.0, 0.5)
            label.set_padding(0, 6)
            label.set_use_underline(True)
            table.attach(label, 0, 1, idx, idx + 1,
                         xoptions=Gtk.AttachOptions.FILL |
                         Gtk.AttachOptions.SHRINK)

        threshold_scale = Gtk.HScale(
            adjustment=Gtk.Adjustment(0, 0, 1, 0.01, 0.1))
        threshold_scale.set_digits(2)
        labels["threshold"].set_mnemonic_widget(threshold_scale)
        threshold_scale.set_value_pos(Gtk.PositionType.RIGHT)

        def format_perc(scale, value):
            return _("%d %%") % (value * 100)
        threshold_scale.connect('format-value', format_perc)
        table.attach(threshold_scale, 1, 2, 0, 1)

        def threshold_changed(scale):
            value = scale.get_value()
            set_cfg("threshold", value)
            self.emit("changed")
        threshold_scale.connect('value-changed', threshold_changed)
        threshold_scale.set_value(get_cfg("threshold"))

        ratio_scale = Gtk.HScale(adjustment=Gtk.Adjustment(0, 0, 1, 0.01, 0.1))
        ratio_scale.set_digits(2)
        labels["ratio"].set_mnemonic_widget(ratio_scale)
        ratio_scale.set_value_pos(Gtk.PositionType.RIGHT)
        table.attach(ratio_scale, 1, 2, 1, 2)

        def ratio_changed(scale):
            value = scale.get_value()
            set_cfg("ratio", value)
            self.emit("changed")
        ratio_scale.connect('value-changed', ratio_changed)
        ratio_scale.set_value(get_cfg("ratio"))

        self.pack_start(qltk.Frame(_("Preferences"), child=table),
                        True, True, 0)


class Compressor(GStreamerPlugin):
    PLUGIN_ID = _PLUGIN_ID
    PLUGIN_NAME = _("Audio Compressor")
    PLUGIN_DESC = _("Change the amplitude of all samples above a specific "
                    "threshold with a specific ratio.")
    PLUGIN_ICON = "audio-volume-high"

    @classmethod
    def setup_element(cls):
        return Gst.ElementFactory.make('audiodynamic', cls.PLUGIN_ID)

    @classmethod
    def update_element(cls, element):
        element.set_property("characteristics", "soft-knee")
        element.set_property("mode", "compressor")
        element.set_property("ratio", get_cfg("ratio"))
        element.set_property("threshold", get_cfg("threshold"))

    @classmethod
    def PluginPreferences(cls, window):
        prefs = Preferences()
        gobject_weak(prefs.connect, "changed", lambda *x: cls.queue_update())
        return prefs
