# -*- 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 import PluginImportException
from quodlibet.plugins.gstelement import GStreamerPlugin
from quodlibet import qltk
from quodlibet import config
from quodlibet.qltk import Icons

_PLUGIN_ID = "karaoke"

_SETTINGS = {
    "band": [_("Filter _band:"),
             _("The Frequency band of the filter"), 220.0],
    "width": [_("Filter _width:"),
              _("The Frequency width of the filter"), 100.0],
    "level": [_("_Level:"), _("Level of the effect"), 1.0],
}


def get_cfg(option):
    cfg_option = "%s_%s" % (_PLUGIN_ID, option)
    default = _SETTINGS[option][2]
    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(n_rows=3, n_columns=2)
        table.set_col_spacings(6)
        table.set_row_spacings(6)

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

        def scale_changed(scale, option):
            value = scale.get_value()
            set_cfg(option, value)
            self.emit("changed")

        max_values = [1.0, 441, 100]
        steps = [0.01, 10, 10]
        pages = [0.1, 50, 25]

        scales = {}
        for idx, key in enumerate(["level", "band", "width"]):
            max_value = max_values[idx]
            step = steps[idx]
            page = pages[idx]
            scale = Gtk.HScale(
                adjustment=Gtk.Adjustment.new(0, 0, max_value, step, page, 0))
            scales[key] = scale
            if step < 0.1:
                scale.set_digits(2)
            scale.add_mark(_SETTINGS[key][2], Gtk.PositionType.BOTTOM, None)
            labels[key].set_mnemonic_widget(scale)
            scale.set_value_pos(Gtk.PositionType.RIGHT)
            table.attach(scale, 1, 2, idx, idx + 1)
            scale.connect('value-changed', scale_changed, key)
            scale.set_value(get_cfg(key))

        def format_perc(scale, value):
            return _("%d %%") % (value * 100)
        scales["level"].connect('format-value', format_perc)

        def format_hertz(scale, value):
            return _("%d Hz") % value
        scales["band"].connect('format-value', format_hertz)
        scales["width"].connect('format-value', format_hertz)

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


class Karaoke(GStreamerPlugin):
    PLUGIN_ID = _PLUGIN_ID
    PLUGIN_NAME = _("Karaoke")
    PLUGIN_DESC = _("Removes main vocals from audio.")
    PLUGIN_ICON = Icons.AUDIO_INPUT_MICROPHONE

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

    @classmethod
    def update_element(cls, element):
        element.set_property("level", get_cfg("level"))
        element.set_property("filter-band", get_cfg("band"))
        element.set_property("filter-width", get_cfg("width"))

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


if not Karaoke.setup_element():
    raise PluginImportException(
        "GStreamer element 'audiokaraoke' missing (gst-plugins-good)")
