import re

import border
import font
import html_util
from html_util import E

# A purely numeric cell value (either decimal-mark style, optional sign).
number_rgx = re.compile(r"[-+]?[\d.,]+$")

class Cell:
    def __init__(self, text, font, hpos,
                 top, right, bottom, left,
                 left_all, right_all,
                 rowspan, colspan, first_column=False, hpos_forced=False,
                 fit_class="", flush_left=False, flush_right=False):
        self.text = text
        self.font = font
        self.hpos = hpos
        # An :hpos override on an ordinary cell must reach the tex target
        # through a \multicolumn{1} (the column spec sets the default).
        self.hpos_forced = hpos_forced
        self.border = border.Border(top, right, bottom, left, left_all, right_all)
        self.rowspan = rowspan
        self.colspan = colspan
        self.first_column = first_column
        # html only: the class(es) clamping a 'fit' column's cell to its
        # widest entry -- "Wfit Wpct" in a full-width table, "Wfit" in a
        # content-sized ('fill') table, "" when not a fit column.
        self.fit_class = fit_class
        # Cell sits on a table edge with no outer vertical line: its outer
        # padding (html) / \tabcolsep (tex, via @{}) is removed so the text
        # aligns with the text margin.  A tex \multicolumn replaces the
        # whole preamble entry including the @{}, so edge cells must
        # re-emit it in their own spec.
        self.flush_left = flush_left
        self.flush_right = flush_right
        #print("Cell:", text, hpos)

    def __str__(self):
        b = str(self.border)
        b = f"[{b}]" if b else ""
        rs = f"[r{self.rowspan}]" if self.rowspan else ""
        cs = f"[r{self.colspan}]" if self.colspan else ""
        #return f'<cell"{self.text}"{self.font}{self.hpos}{b}>'
        return f'<cell"{self.text}"{b}{rs}{cs}>'

    def __repr__(self):
        return self.__str__()

    def html(self):
        result = self.text
        result = E("td").body(font.html_fontify(result, self.font, 1.0))
        if self.rowspan > 1:
            result.attr("rowspan", self.rowspan)
        if self.colspan > 1:
            result.attr("colspan", self.colspan)
        for pred, cls_name in zip(self.border.has(), "Bt Br Bb Bl".split()):
            if pred:
                result.cls(cls_name)
        result.cls(f"H{self.hpos}")
        if self.fit_class:
            result.cls(self.fit_class)
        if self.flush_left:
            result.cls("Fl")
        if self.flush_right:
            result.cls("Fr")
        return result.str()

    def tex(self, debug=False): # , left_line, right_line):
        result = self.text
        # A number must not line-break (LaTeX breaks after a minus sign
        # read as a hyphen in narrow fit-width columns).
        if number_rgx.match(result.strip()):
            result = f"\\mbox{{{result.strip()}}}"
        if self.font != "r":
            result = font.tex_fontify(result, self.font, 1.0)
        if self.rowspan > 1:
            result = f"\\multirow{{{self.rowspan}}}{{*}}{{{result}}}"
        if self.colspan > 1:
            # \multicolumn carries the merged cell's own column spec.  A
            # left bar may only be given when the span starts at the
            # table's first column: elsewhere the bar to the left belongs
            # to the preceding column's preamble entry, and adding one
            # here draws a doubled line.
            pos = self.hpos
            if self.border.left and self.first_column:
                pos = "|" + pos
            if self.border.right:
                pos = pos + "|"
            if self.flush_left:
                pos = "@{}" + pos
            if self.flush_right:
                pos = pos + "@{}"
            return f"\\multicolumn{{{self.colspan}}}{{{pos}}}{{{result}}}"
        remove_left = self.border.left_all and not self.border.left
        remove_right = self.border.right_all and not self.border.right
        if debug:
            left_marker = "xL" if remove_left else "L" if self.border.left_all else ""
            right_marker = "Rx" if remove_right else "R" if self.border.right_all else ""
            result = f"{left_marker} {result} {right_marker}"
        if remove_left or remove_right or self.hpos_forced:
            pos = self.hpos
            if self.border.left_all and self.border.left:
                pos = "|" + pos
            if self.border.right_all and self.border.right:
                pos = pos + "|"
            if self.flush_left:
                pos = "@{}" + pos
            if self.flush_right:
                pos = pos + "@{}"
            result = f"\\multicolumn{{1}}{{{pos}}}{{{result}}}"
        return result


if __name__ == "__main__":
    print(Cell("dog", "r", "c", True, False, True, False))
