#!/usr/bin/env python
# vim: fileencoding=utf-8 ft=python et sw=4 ts=4 sts=4 tw=79

from __future__ import (
    generators, division, absolute_import, with_statement, print_function
)

import urwid
# from twisted.internet import reactor
from twisted.internet.task import LoopingCall
from twisted.internet.utils import getProcessOutput


pane_format = 'session_name window_index pane_id pane_title'.split()

# TODO: use tmux in command mode:
# tmux -L tst -C a -t 0 \; refresh-client -C 256,128


def exit_program(button):
    raise urwid.ExitMainLoop()


class TST(object):
    """
    Vertical tree-style-tabs alike for tmux.
    """

    def __init__(self, sockname='tst'):
        self.sockname = sockname
        self._redraw_pending = False

        self.head = [urwid.Text('TST'), urwid.Divider()]
        self.body = urwid.SimpleFocusListWalker(self.head)

        self.main = urwid.Padding(urwid.ListBox(self.body), left=2, right=2)
        self.top = urwid.Overlay(
            self.main,
            urwid.SolidFill(u'\N{MEDIUM SHADE}'),
            align='center', width=('relative', 60),
            valign='middle', height=('relative', 60),
            min_width=20, min_height=9
        )

    def call_tmux(self, *args):
        """
        Run tmux executable with socket option set.
        """
        return getProcessOutput('/usr/bin/tmux', ('-L', self.sockname) + args)

    def get_panes(self):
        """
        Call tmux to get list of panes.
        """
        return self.call_tmux(*'list-panes -a -F'.split() + ['|'.join((
            '#{%s}' % i for i in pane_format
        ))]).addCallback(self.got_panes)

    def got_panes(self, s):
        """
        Process list of panes and update TST accordingly.
        """
        buttons = []
        for line in s.split('\n'):
            if not line:
                continue
            d = dict(zip(pane_format, line.split('|')))
            b = urwid.Button('%(pane_id)s %(pane_title)s' % d,
                             self.clicked,
                             d['window_index'])
            buttons.append(urwid.AttrMap(b, None, focus_map='reversed'))
        self.body[2:] = buttons
        # self.mainloop.draw_screen()
        self.redraw()

    def redraw(self):
        """
        Schedule window redraw at closest idle time.
        """
        if self._redraw_pending:
            return
        self._redraw_pending = True
        self.reactor.callLater(0, self._do_redraw)

    def _do_redraw(self):
        self._redraw_pending = False
        self.mainloop.draw_screen()

    def clicked(self, button, window):
        self.call_tmux('select-window', '-t', window)

    def run(self, reactor=None):
        """
        Run the TST application.
        """

        if reactor is None:
            from twisted.internet import reactor
        self.reactor = reactor

        self.get_panes()
        self.paneloop = LoopingCall(self.get_panes)
        self.paneloop.start(1)
        self.mainloop = urwid.MainLoop(
            self.main,
            palette=[('reversed', 'standout', '')],
            event_loop=urwid.TwistedEventLoop(reactor)
        )
        self.mainloop.run()


if __name__ == '__main__':
    TST().run()