import subprocess
import psutil
import re
import os

from libqtile import widget, bar

#region Custom_Memory
class MemoryC(widget.base.ThreadPoolText):
    orientations = widget.base.ORIENTATION_HORIZONTAL
    defaults = [
        ("format", "{MemUsed}GB/{MemTotal}GB", "Formatting for field names."),
        ("update_interval", 1.0, "Update interval for the Memory"),
    ]

    def __init__(self, **config):
        super().__init__("", **config)
        self.add_defaults(MemoryC.defaults)

    def poll(self):
        mem = psutil.virtual_memory()
        swap = psutil.swap_memory()
        val = {}
        val["MemUsed"] = mem.used // 1024 // 1024 // 102.4 / 10
        val["MemTotal"] = mem.total // 1024 // 1024 // 102.4 / 10
        val["MemPercent"] = mem.percent
        val["MemFree"] = mem.free // 1024 // 1024 // 102.4 / 10
        val["Buffers"] = mem.buffers // 1024 // 1024 // 102.4 / 10
        val["Active"] = mem.active // 1024 // 1024 // 102.4 / 10
        val["Inactive"] = mem.inactive // 1024 // 1024 // 102.4 / 10
        val["Shmem"] = mem.shared // 1024 // 1024 // 102.4 / 10
        val["SwapTotal"] = swap.total // 1024 // 1024 // 102.4 / 10
        val["Swapfree"] = swap.free // 1024 // 1024 // 102.4 / 10
        val["SwapUsed"] = swap.used // 1024 // 1024 // 102.4 / 10
        val["SwapPercent"] = swap.percent
        return self.format.format(**val)
#endregion

#region Microphone_Widget
re_vol = re.compile(r'\[(\d?\d?\d?)%\]')
BUTTON_MUTE = 1
class Mic(widget.base._TextBox):
    """
    Custom Microphone widget
    """
    orientations = widget.base.ORIENTATION_HORIZONTAL
    defaults = [
        ("cardid", None, "Card Id"),
        ("device", "default", "Device Name"),
        ("channel", "Capture", "Channel"),
        ("padding", 3, "Padding left and right. Calculated if None."),
        ("update_interval", 0.2, "Update time in seconds."),
        ("theme_path", None, "Path of the icons"),
        ("emoji", False, "Use emoji to display volume states, only if ``theme_path`` is not set."
                         "The specified font needs to contain the correct unicode characters."),
        ("mute_command", None, "Mute command"),
        ("volume_app", None, "App to control volume"),
        ("volume_up_command", None, "Volume up command"),
        ("volume_down_command", None, "Volume down command"),
        ("get_volume_command", None, "Command to get the current volume"),
        ("step", 2, "Volume change for up an down commands in percentage."
                    "Only used if ``volume_up_command`` and ``volume_down_command`` are not set.")
    ]

    def __init__(self, **config):
        widget.base._TextBox.__init__(self, '0', width=bar.CALCULATED, **config)
        self.add_defaults(Mic.defaults)
        if self.theme_path:
            self.length_type = bar.STATIC
            self.length = 0
        self.surfaces = {}
        self.volume = None

    def timer_setup(self):
        self.timeout_add(self.update_interval, self.update)
        if self.theme_path:
            self.setup_images()

    def create_amixer_command(self, *args):
        cmd = ['amixer']
        cmd.extend([x for x in args])
        return cmd

    def button_press(self, x, y, button):
        if button == BUTTON_MUTE:
            if self.mute_command is not None:
                subprocess.call(self.mute_command, shell=True)
            else:
                subprocess.call(self.create_amixer_command('-q',
                                                           'sset',
                                                           self.channel,
                                                           'toggle'))
        self.draw()

    def update(self):
        vol = self.get_volume()
        if vol != self.volume:
            self.volume = vol
            # Update the underlying canvas size before actually attempting
            # to figure out how big it is and draw it.
            self._update_drawer()
            self.bar.draw()
        self.timeout_add(self.update_interval, self.update)

    def _update_drawer(self):
        if self.emoji:
            if self.volume > 0:
                self.text = ''
            elif self.volume <= 0:
                self.text = ''
        else:
            if self.volume == -1:
                self.text = 'M'
            else:
                self.text = '{}%'.format(self.volume)
    def get_volume(self):
        try:
            get_volume_cmd = self.create_amixer_command('sget',
                                                        self.channel)

            if self.get_volume_command:
                get_volume_cmd = self.get_volume_command

            mixer_out = self.call_process(get_volume_cmd)
        except subprocess.CalledProcessError:
            return -1

        if '[off]' in mixer_out:
            return -1

        volgroups = re_vol.search(mixer_out)
        if volgroups:
            return int(volgroups.groups()[0])
        else:
            # this shouldn't happen
            return -1

    def draw(self):
        if self.theme_path:
            self.drawer.draw(offsetx=self.offset, width=self.length)
        else:
            widget.base._TextBox.draw(self)

    def cmd_mute(self):
        # Emulate button press.
        self.button_press(0, 0, BUTTON_MUTE)
#endregion
