import sys
import json
import time

import core.theme
import core.event

class i3(object):
    def __init__(self, theme=core.theme.Theme(), config=None):
        self._modules = []
        self._status = {}
        self._theme = theme
        self._config = config
        core.event.register('start', self.draw, 'start')
        core.event.register('update', self.draw, 'statusline')
        core.event.register('stop', self.draw, 'stop')

    def theme(self, new_theme=None):
        if new_theme:
            self._theme = new_theme
        return self._theme

    def modules(self, modules=None):
        if not modules:
            return self._modules
        self._modules = modules if isinstance(modules, list) else [ modules ]

    def draw(self, what, args=None):
        cb = getattr(self, what)
        data = cb(args) if args else cb()
        if 'data' in data:
            sys.stdout.write(json.dumps(data['data']))
        if 'suffix' in data:
            sys.stdout.write(data['suffix'])
        sys.stdout.write('\n')
        sys.stdout.flush()

    def start(self):
        return {
            'data': { 'version': 1, 'click_events': True },
            'suffix': '\n[',
        }

    def stop(self):
        return { 'suffix': '\n]' }

    def __pad(self, module, widget, full_text):
        padding = self._theme.padding()
        if not full_text: return padding
        return '{}{}{}'.format(padding, full_text, padding)

    def __decorate(self, module, widget, full_text):
        return '{}{}{}'.format(
            self.__pad(module, widget, self._theme.prefix(widget)),
            full_text,
            self.__pad(module, widget, self._theme.suffix(widget))
        )

    def __common_attributes(self, module, widget):
        return {
            'separator': self._theme.default_separators(),
            'separator_block_width': self._theme.separator_block_width(),
            'border_top': self._theme.border_top(),
            'border_left': self._theme.border_left(),
            'border_right': self._theme.border_right(),
            'border_bottom': self._theme.border_bottom(),
            'instance': widget.id(),
            'name': module.id(),
        }

    def __separator(self, module, widget):
        if not self._theme.separator():
            return []
        attr = self.__common_attributes(module, widget)
        attr.update({
            'full_text': self._theme.separator(),
            'color': self._theme.bg(widget),
            'background': self._theme.bg('previous'),
            '_decorator': True,
        })
        return [attr]

    def __main(self, module, widget, text):
        attr = self.__common_attributes(module, widget)
        attr.update({
            'full_text': self.__decorate(module, widget, text),
            'color': self._theme.fg(widget),
            'background': self._theme.bg(widget),
            'min_width': widget.get('theme.minwidth'),
        })
        return [attr]

    def widgets(self, module):
        widgets = []
        for widget in module.widgets():
            widgets += self.__separator(module, widget)
            widgets += self.__main(module, widget, self._status[widget])
            core.event.trigger('next-widget')
        return widgets

    def update(self, affected_modules=None):
        for module in self._modules:
            if affected_modules and not module.id() in affected_modules:
                continue
            module.update_wrapper()
            for widget in module.widgets():
                self._status[widget] = widget.full_text()

    def statusline(self):
        widgets = []
        for module in self._modules:
            widgets += self.widgets(module)
        return {
            'data': widgets,
            'suffix': ','
        }

    def wait(self, interval):
        time.sleep(interval)

# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4