# grid.py micro-gui widget providing the Grid class: a 2d array of Label instances.

# Released under the MIT License (MIT). See LICENSE.
# Copyright (c) 2023 Peter Hinch

from gui.core.ugui import Widget, display
from gui.core.writer import Writer
from gui.core.colors import *
from gui.widgets import Label

# lwidth may be integer Label width in pixels or a tuple/list of widths
class Grid(Widget):
    def __init__(self, writer, row, col, lwidth, nrows, ncols, invert=False, fgcolor=None, bgcolor=BLACK, bdcolor=None, justify=0):
        self.nrows = nrows
        self.ncols = ncols
        self.ncells = nrows * ncols
        self.cheight = writer.height + 4  # Cell height including borders
        # Build column width list. Column width is Label width + 4.
        if isinstance(lwidth, int):
            self.cwidth = [lwidth + 4] * ncols
        else:  # Ensure len(.cwidth) == ncols
            self.cwidth = [w + 4 for w in lwidth][:ncols]
            self.cwidth.extend([lwidth[-1] + 4] * (ncols - len(lwidth)))
        width = sum(self.cwidth) - 4  # Dimensions of widget interior
        height = nrows * self.cheight - 4
        super().__init__(writer, row, col, height, width, fgcolor, bgcolor, bdcolor)
        self.cells = []
        r = row
        c = col
        for _ in range(self.nrows):
            for cw in self.cwidth:
                self.cells.append(Label(writer, r, c, cw - 4, invert, fgcolor, bgcolor, False, justify))  # No border
                c += cw
            r += self.cheight
            c = col

    def _idx(self, n):
        if isinstance(n, tuple) or isinstance(n, list):
            if n[0] >= self.nrows:
                raise ValueError("Grid row index too large")
            if n[1] >= self.ncols:
                raise ValueError("Grid col index too large")
            idx = n[1] + n[0] * self.ncols
        else:
            idx = n
        if idx >= self.ncells:
            raise ValueError("Grid cell index too large")
        return idx

    def __getitem__(self, n):  # Return the Label instance
        return self.cells[self._idx(n)]

    # allow grid[[r, c]] = "foo" or kwargs for Label:
    # grid[[r, c]] = {"text": str(n), "fgcolor" : RED}
    def __setitem__(self, n, x):
        v = self.cells[self._idx(n)].value
        _ = v(**x) if isinstance(x, dict) else v(x)

    def show(self):
        super().show()  # Draw border
        if self.has_border:  # Draw grid
            color = self.bdcolor
            x = self.col - 2  # Border top left corner
            y = self.row - 2
            dy = self.cheight
            for row in range(1, self.nrows):
                display.hline(x, y + row * dy, self.width + 4, color)
            for cw in self.cwidth[:-1]:
                x += cw
                display.vline(x, y, self.height + 4, color)
