# This file contains a basic "builder" style API for making HTML tables
# and writing them to a file once finished.
#
# Use it as follows:
# with Table(outfile) as table:
#  table.AddRow().AddCell("foo")
#
# To get:
# <table>
#   <td>foo</td>
# </table>
#
# Methods return a reference to self, or to the new thing you added.
# This means you can keep chaining calls to build what you want.
#
# table.AddRow().AddCell("foo").Colspan(1).Style("mystyle")


class TableCell(object):
    def __init__(self, name, content=None):
        self.name = name
        self.content = content
        self.style = None
        self.colspan = None

    def Style(self, style):
        self.style = style
        return self

    def Colspan(self, colspan):
        self.colspan = colspan
        return self

    def Content(self, content):
        self.content = content
        return self

    def __str__(self):
        return "    <{}{}{}>{}</{}>".format(
            self.name,
            "" if self.style is None else ' style="{}"'.format(self.style),
            "" if self.colspan is None else " colspan={}".format(self.colspan),
            "&nbsp;" if self.content is None else self.content,
            self.name,
        )


class Cell(TableCell):
    def __init__(self, content=None):
        super(Cell, self).__init__("td", content)


class Header(TableCell):
    def __init__(self, content=None):
        super(Header, self).__init__("th", content)


class Row(object):
    def __init__(self):
        self.cells = []

    def AddCell(self, content=None):
        self.cells.append(Cell(content))
        return self.cells[-1]

    def AddHeader(self, content=None):
        self.cells.append(Header(content))
        return self.cells[-1]

    def __str__(self):
        return "\n".join(["  <tr>", *map(str, self.cells), "  </tr>"])


class TableBody(object):
    def __init__(self, close=False):
        self.close = close

    def __str__(self):
        return "<{}tbody>".format("/" if self.close else "")


class Table(object):
    def __init__(self, out):
        self.out = out
        self.rows = []
        self.border = None
        self.cellspacing = None
        self.cellpadding = None
        self.body_begins = None

    def __enter__(self):
        return self

    def __exit__(self, *args):
        self.out.write("\n" + str(self))

    def __str__(self):
        open_tag = "<table{}{}{}>".format(
            "" if self.border is None else " border={}".format(self.border),
            ""
            if self.cellspacing is None
            else " cellspacing={}".format(self.cellspacing),
            ""
            if self.cellpadding is None
            else " cellpadding={}".format(self.cellpadding),
        )
        rows = map(str, self.rows)
        close_tag = "</table>"

        return "\n".join([open_tag, *rows, close_tag])

    def AddRow(self):
        self.rows.append(Row())
        return self.rows[-1]

    def Border(self, border):
        self.border = border
        return self

    def Cellspacing(self, cellspacing):
        self.cellspacing = cellspacing
        return self

    def Cellpadding(self, cellpadding):
        self.cellpadding = cellpadding
        return self

    def BeginBody(self):
        self.rows.append(TableBody())

    def EndBody(self):
        self.rows.append(TableBody(close=True))
