#
# Albow - Layout widgets
#

from pygame import Rect
from widget import Widget


class RowOrColumn(Widget):
    _is_gl_container = True
    focusable = False

    def __init__(self, size, items, kwds):
        align = kwds.pop('align', 'c')
        self.spacing = spacing = kwds.pop('spacing', 10)
        expand = kwds.pop('expand', None)
        if isinstance(expand, int):
            expand = items[expand]

        #-# Translation live update preparation
        self.expand = expand
        self.align = align
        self._size = size
        #-#

        #if kwds:
        #    raise TypeError("Unexpected keyword arguments to Row or Column: %s"
        #        % kwds.keys())
        Widget.__init__(self, **kwds)
    #-# Translation live update preparation
        self.calc_size(items)

    def calc_size(self, _items=None):
        if _items:
            items = _items
        else:
            items = self.subwidgets
        expand = self.expand
        align = self.align
        size = self._size
        spacing = self.spacing
    #-#

        # If the 'expand' value is in 'h' or 'v', resize the widgets according
        # to the larger one.
        if type(expand) in (str, unicode):
            w = 'n'
            h = 'n'
            if 'h' in expand:
                # Expand horizontally
                w = max([a.width for a in items])
            if 'v' in expand:
                # Expand vertically
                h = max([a.height for a in items])
            if w != 'n' and h == 'n':
                for item in items:
                    item.width = w
            elif w == 'n' and h != 'n':
                for item in items:
                    item.height = h
            elif w != 'n' and h != 'n':
                for item in items:
                    item.width = w
                    item.height = h

        d = self.d
        longways = self.longways
        crossways = self.crossways
        axis = self.axis
        k, attr2, attr3 = self.align_map[align]
        w = 0
        length = 0
        if items:
            if isinstance(expand, int):
                expand = items[expand]
            elif not expand:
                expand = items[-1]
        move = ''
        for item in items:
            r = item.rect
            w = max(w, getattr(r, crossways))
            if item is expand:
                item.set_resizing(axis, 's')
                move = 'm'
            else:
                item.set_resizing(axis, move)
                length += getattr(r, longways)
        if size is not None:
            n = len(items)
            if n > 1:
                length += spacing * (n - 1)
            setattr(expand.rect, longways, max(1, size - length))
        h = w * k // 2
        m = self.margin
        px = h * d[1] + m
        py = h * d[0] + m
        sx = spacing * d[0]
        sy = spacing * d[1]
        for item in items:
            setattr(item.rect, attr2, (px, py))
            #-# Translation live update preparation
            if _items:
                self.add(item)
            #-#
            p = getattr(item.rect, attr3)
            px = p[0] + sx
            py = p[1] + sy
        self.shrink_wrap()

    def call_handler(self, name, *args):
        # Automatically call the parent *_action methods
        if Widget.call_handler(self, name, *args) == 'pass':
            return self.call_parent_handler(name, *args)

#---------------------------------------------------------------------------


class Row(RowOrColumn):
    d = (1, 0)
    axis = 'h'
    longways = 'width'
    crossways = 'height'
    align_map = {
        't': (0, 'topleft', 'topright'),
        'c': (1, 'midleft', 'midright'),
        'b': (2, 'bottomleft', 'bottomright'),
    }

    def __init__(self, items, width=None, **kwds):
        """
        Row(items, align=alignment, spacing=10, width=None, expand=None)
        align = 't', 'c' or 'b'
        """
        RowOrColumn.__init__(self, width, items, kwds)


#---------------------------------------------------------------------------


class Column(RowOrColumn):
    d = (0, 1)
    axis = 'v'
    longways = 'height'
    crossways = 'width'
    align_map = {
        'l': (0, 'topleft', 'bottomleft'),
        'c': (1, 'midtop', 'midbottom'),
        'r': (2, 'topright', 'bottomright'),
    }

    def __init__(self, items, height=None, **kwds):
        """
        Column(items, align=alignment, spacing=10, height=None, expand=None)
        align = 'l', 'c' or 'r'
        """
        RowOrColumn.__init__(self, height, items, kwds)


#---------------------------------------------------------------------------


class Grid(Widget):
    _is_gl_container = True

    def __init__(self, rows, row_spacing=10, column_spacing=10, **kwds):
        col_widths = [0] * len(rows[0])
        row_heights = [0] * len(rows)
        for j, row in enumerate(rows):
            for i, widget in enumerate(row):
                if widget:
                    col_widths[i] = max(col_widths[i], widget.width)
                    row_heights[j] = max(row_heights[j], widget.height)
        row_top = 0
        for j, row in enumerate(rows):
            h = row_heights[j]
            y = row_top + h // 2
            col_left = 0
            for i, widget in enumerate(row):
                if widget:
                    w = col_widths[i]
                    x = col_left
                    widget.midleft = (x, y)
                col_left += w + column_spacing
            row_top += h + row_spacing
        width = max(1, col_left - column_spacing)
        height = max(1, row_top - row_spacing)
        r = Rect(0, 0, width, height)
        #print "albow.controls.Grid: r =", r ###
        #print "...col_widths =", col_widths ###
        #print "...row_heights =", row_heights ###
        Widget.__init__(self, r, **kwds)
        self.add(rows)


#---------------------------------------------------------------------------


class Frame(Widget):
    #  margin  int        spacing between border and widget

    border_width = 1
    margin = 2

    def __init__(self, client, border_spacing=None, **kwds):
        Widget.__init__(self, **kwds)
        self.client = client
        if border_spacing is not None:
            self.margin = self.border_width + border_spacing
        d = self.margin
        w, h = client.size
        self.size = (w + 2 * d, h + 2 * d)
        client.topleft = (d, d)
        self.add(client)

    def call_handler(self, name, *args):
        # Automatically call the parent *_action methods
        if Widget.call_handler(self, name, *args) == 'pass':
            return self.call_parent_handler(name, *args)
