# pylint: disable=C0111,R0903

"""Display and run a Pomodoro timer.
Left click to start timer, left click again to pause.
Right click will cancel the timer.

Parameters:
    * pomodoro.work: The work duration of timer in minutes (defaults to 25)
    * pomodoro.break: The break duration of timer in minutes (defaults to 5)
    * pomodoro.format: Timer display format with "%m" and "%s" for minutes and seconds (defaults to "%m:%s")
                       Examples: "%m min %s sec", "%mm", "", "timer"
    * pomodoro.notify: Notification command to run when timer ends/starts (defaults to nothing)
                       Example: 'notify-send "Time up!"'. If you want to chain multiple commands,
                       please use an external wrapper script and invoke that. The module itself does
                       not support command chaining (see https://github.com/tobi-wan-kenobi/bumblebee-status/issues/532
                       for a detailled explanation)
"""

from __future__ import absolute_import
import datetime
from math import ceil

import bumblebee.input
import bumblebee.output
import bumblebee.engine

class Module(bumblebee.engine.Module):
    def __init__(self, engine, config):
        widgets = bumblebee.output.Widget(full_text=self.text)

        super(Module, self).__init__(engine, config, widgets)

        # Parameters
        self._work_period = int(self.parameter("work", 25))
        self._break_period = int(self.parameter("break", 5))
        self._time_format = self.parameter("format", "%m:%s")
        self._notify_cmd = self.parameter("notify", "")

        # TODO: Handle time formats more gracefully. This is kludge.
        self.display_seconds_p = False
        self.display_minutes_p = False
        if "%s" in self._time_format:
            self.display_seconds_p = True
        if "%m" in self._time_format:
            self.display_minutes_p = True

        self.remaining_time = datetime.timedelta(minutes=self._work_period)

        self.time = None
        self.pomodoro = { "state":"OFF", "type": ""}
        self._text = self.remaining_time_str() + self.pomodoro["type"]

        engine.input.register_callback(self, button=bumblebee.input.LEFT_MOUSE,
                                       cmd=self.timer_play_pause)
        engine.input.register_callback(self, button=bumblebee.input.RIGHT_MOUSE,
                                       cmd=self.timer_reset)
        
    def remaining_time_str(self):

        if self.display_seconds_p and self.display_minutes_p:
            minutes, seconds = divmod(self.remaining_time.seconds, 60)
        if not self.display_seconds_p:
            minutes = ceil(self.remaining_time.seconds / 60)
            seconds = 0 
        if not self.display_minutes_p:
            minutes = 0
            seconds = self.remaining_time.seconds

        minutes = "{:2d}".format(minutes)
        seconds = "{:02d}".format(seconds)
        return self._time_format.replace("%m",minutes).replace("%s",seconds)+" "

    def text(self, widget):
        return "{}".format(self._text) 
        
    def update(self, widget):
        if self.pomodoro["state"] == "ON":
            timediff = (datetime.datetime.now() - self.time)
            if timediff.seconds >= 0:
                self.remaining_time -= timediff
                self.time = datetime.datetime.now()

            if self.remaining_time.total_seconds() <= 0:
                self.notify()
                if self.pomodoro["type"] == "Work":
                    self.pomodoro["type"] = "Break"
                    self.remaining_time = datetime.timedelta(minutes=self._break_period)
                elif self.pomodoro["type"] == "Break":
                    self.pomodoro["type"] = "Work"
                    self.remaining_time = datetime.timedelta(minutes=self._work_period)

        self._text = self.remaining_time_str() + self.pomodoro["type"]
    
    def notify(self):
        if self._notify_cmd:
            bumblebee.util.execute(self._notify_cmd)

    def timer_play_pause(self, widget):
        if self.pomodoro["state"] == "OFF":
            self.pomodoro = {"state": "ON", "type": "Work"}
            self.remaining_time = datetime.timedelta(minutes=self._work_period)
            self.time = datetime.datetime.now()
        elif self.pomodoro["state"] == "ON":
            self.pomodoro["state"] = "PAUSED"
            self.remaining_time -= (datetime.datetime.now() - self.time)
            self.time = datetime.datetime.now()
        elif self.pomodoro["state"] == "PAUSED":
            self.pomodoro["state"] = "ON"
            self.time = datetime.datetime.now()

    def timer_reset(self, widget):
        if self.pomodoro["state"] == "ON" or self.pomodoro["state"] == "PAUSED":
            self.pomodoro = {"state":"OFF", "type": "" }
            self.remaining_time = datetime.timedelta(minutes=self._work_period)

    def state(self, widget):
        state = [];
        state.append(self.pomodoro["state"].lower())
        if self.pomodoro["state"] == "ON" or self.pomodoro["state"] == "OFF":
            state.append(self.pomodoro["type"].lower())

        return state
