text: import time
  
  from i3pystatus import IntervalModule
  from i3pystatus.core.command import execute
  from i3pystatus.core.util import TimeWrapper
  
  
  class TimerState:
      stopped = 0
      running = 1
      overflow = 2
  
  
  class Timer(IntervalModule):
      """
      Timer module to remind yourself that there probably is something else you
      should be doing right now.
  
      Main features include:
  
      - Set custom time interval with click events.
      - Different output formats triggered when remaining time is less than `x`
        seconds.
      - Execute custom python function or external command when timer overflows
        (or reaches zero depending on how you look at it).
  
      .. rubric:: Available formatters
  
      Time formatters are available to show the remaining time.
      These include ``%h``, ``%m``, ``%s``, ``%H``, ``%M``, ``%S``.
      See :py:class:`.TimeWrapper` for detailed description.
  
      The ``format_custom`` setting allows you to display different formats when
      certain amount of seconds is remaining.
      This setting accepts list of tuples which contain time in seconds,
      format string and color string each.
      See the default settings for an example:
  
      - ``(0, "+%M:%S", "#ffffff")`` - Use this format after overflow. White text
        with red background set by the urgent flag.
      - ``(60, "-%M:%S", "#ffa500")`` - Change color to orange in last minute.
      - ``(3600, "-%M:%S", "#00ff00")`` - Hide hour digits when remaining time is
        less than one hour.
  
      Only first matching rule is applied (if any).
  
      .. rubric:: Callbacks
  
      Module contains three mouse event callback methods:
  
      - :py:meth:`.start` - Default: Left click starts (or adds) 5 minute
        countdown.
      - :py:meth:`.increase` - Default: Upscroll/downscroll increase/decrease time
        by 1 minute.
      - :py:meth:`.reset` - Default: Right click resets timer.
  
      Two new event settings were added:
  
      - ``on_overflow`` - Executed when remaining time reaches zero.
      - ``on_reset`` - Executed when timer is reset but only if overflow occured.
  
      These settings accept either a python callable object or a string with shell
      command.
      Python callbacks should be non-blocking and without any arguments.
  
      Here is an example that plays a short sound file in 'loop' every 60 seconds
      until timer is reset.
      (``play`` is part of ``SoX`` - the Swiss Army knife of audio manipulation)
  
      ::
  
          on_overflow = "play -q /path/to/sound.mp3 pad 0 60 repeat -"
          on_reset = "pkill -SIGTERM -f 'play -q /path/to/sound.mp3 pad 0 60 repeat -'"
  
      """
  
      interval = 1
  
      on_leftclick = ["start", 300]
      on_rightclick = "reset"
      on_upscroll = ["increase", 60]
      on_downscroll = ["increase", -60]
  
      settings = (
          ("format", "Default format that is showed if no ``format_custom`` "
           "rules are matched."),
          ("format_stopped", "Format showed when timer is inactive."),
          "color",
          "color_stopped",
          "format_custom",
          ("overflow_urgent", "Set urgent flag on overflow."),
          "on_overflow",
          "on_reset",
      )
  
      format = '-%h:%M:%S'
      format_stopped = "T"
      color = "#00ff00"
      color_stopped = "#ffffff"
      format_custom = [
          (0, "+%M:%S", "#ffffff"),
          (60, "-%M:%S", "#ffa500"),
          (3600, "-%M:%S", "#00ff00"),
      ]
      overflow_urgent = True
      on_overflow = None
      on_reset = None
  
      def init(self):
          self.compare = 0
          self.state = TimerState.stopped
          if not self.format_custom:
              self.format_custom = []
  
      def run(self):
          if self.state is not TimerState.stopped:
              diff = self.compare - time.time()
  
              if diff < 0 and self.state is TimerState.running:
                  self.state = TimerState.overflow
                  if self.on_overflow:
                      if callable(self.on_overflow):
                          self.on_overflow()
                      else:
                          execute(self.on_overflow)
  
              fmt = self.format
              color = self.color
              for rule in self.format_custom:
                  if diff < rule[0]:
                      fmt = rule[1]
                      color = rule[2]
                      break
              urgent = self.overflow_urgent and self.state is TimerState.overflow
  
              self.output = {
                  "full_text": format(TimeWrapper(abs(diff), fmt)),
                  "color": color,
                  "urgent": urgent,
              }
          else:
              self.output = {
                  "full_text": self.format_stopped,
                  "color": self.color_stopped,
              }
  
      def start(self, seconds=300):
          """
          Starts timer.
          If timer is already running it will increase remaining time instead.
  
          :param int seconds: Initial time.
          """
          if self.state is TimerState.stopped:
              self.compare = time.time() + abs(seconds)
              self.state = TimerState.running
          elif self.state is TimerState.running:
              self.increase(seconds)
  
      def increase(self, seconds):
          """
          Change remainig time value.
  
          :param int seconds: Seconds to add. Negative value substracts from
           remaining time.
          """
          if self.state is TimerState.running:
              new_compare = self.compare + seconds
              if new_compare > time.time():
                  self.compare = new_compare
  
      def reset(self):
          """
          Stop timer and execute ``on_reset`` if overflow occured.
          """
          if self.state is not TimerState.stopped:
              if self.on_reset and self.state is TimerState.overflow:
                  if callable(self.on_reset):
                      self.on_reset()
                  else:
                      execute(self.on_reset)
              self.state = TimerState.stopped
  