# OBSAH SOUBORU:
# - ziskavani formatovani z oblasti tabulek

import re

from openpyxl import Workbook
from openpyxl.cell import Cell
from openpyxl.worksheet.worksheet import Worksheet

import colors
import fontsize
import utils
import settings
from classes import CTableStyle, CDxf, CCell
from enums import EColor, EBorderStyle, EFontFlags, EBorder, ETableOptions

from colors import theme_and_tint_to_ninecolors


# Vetsina stylu tabulek je vestavena a definovana pouze nazvem. V definici dle nazvu lze zapnout nebo vypnout nejake
# prvky, typu zahlavi, pruhovane sloupce/radky, ale jinak je to vse "hardcoded".

# Strukturu tehcto definic jde velmi krasne videt v momente, kdy v excelu formatujete oblast jako tabulku. Vidite
# deleni na svetlou, stredni a tmavou variantu, a ze jednotlive 'styly' se opakuji vzdy po 7 barvach. Dokonce jsou
# v tomto nahledu serazeny presne v tom poradi, ve kterem byly definovany.

# Vlastni styly lze vytvorit bud na zaklade nejakeho preddefinovaneho stylu, a nebo uplne od podlahy. Opet o nich
# vime jen nazev, a pak tzv. differintialFormat, ktere jsou definovany primo v .xml (presneji v styles.xml). openpyxl
# je umi parsovat a ma je vsechny predem ulozene v objektu tridy Workbook. Priradit k prvkum tabulky je musime rucne :(

# Poznamky:
#  - Ve vlastnim stylu mohou byt jen barvy tematu, nebo indexovane (ty jsou pokazde stejne).
#  - differintialFormat, jak nazev napovida, funguje tak, ze rekne pouze jake formaty se u prvku lisi oproti nejakemu
#    referencnimu. daji se tim jakoby nabalovat styly. ktery je jako referencni zalezi na prvku ke kteremu se vaze.
#       - napr. format u first_col ma jako referenci odd_col, a odd_col ma jako referenci whole_table
#       - vychazi to z tech moznosti v Navrhu tabulky v excelu, ktere se daji ruzne pozapinat (pruhovane sloupce apod.)


def convert_dxf_from_id(wb: Workbook, dxf_id: int):
    """Funkce si z objektu typu Workbook vytahne potrebny differentialFormat (dxf) podle prislusneho ID, a pak
    jej prevede na muj datovy typ CDxf."""

    if not wb:
        raise RuntimeError('Neplatny soubor')

    if not hasattr(wb, '_differential_styles'):
        return None

    if not wb._differential_styles.styles:
        return None

    if not isinstance(dxf_id, int):
        return None

    if len(wb._differential_styles.styles) < dxf_id:
        raise RuntimeError('Dane dxf neexistuje')

    my_dxf = CDxf()
    dxf = wb._differential_styles.styles[dxf_id]

    # ziskani stylu
    if dxf.fill and dxf.fill.bgColor:
        my_dxf.bgcolor = colors.get_cell_color_nine(wb, dxf.fill.bgColor, allow_black=True)

    if dxf.font:
        if dxf.font.color:
            my_dxf.fgcolor = colors.get_cell_color_nine(wb, dxf.font.color)

        font_flags = EFontFlags.NONE
        if dxf.font.b or dxf.font.bold:
            font_flags |= EFontFlags.BOLD

        if dxf.font.i or dxf.font.italic:
            font_flags |= EFontFlags.ITALIC

        if dxf.font.u:
            if dxf.font.u[0] == 's':
                font_flags |= EFontFlags.UNDER
            else:
                font_flags |= EFontFlags.DOUBLE_UNDER

        if font_flags != EFontFlags.NONE:
            font_flags ^= EFontFlags.NONE

        my_dxf.font_flags = font_flags

        if dxf.font.sz or dxf.font.size:
            my_dxf.font_size = fontsize.get_font_size(dxf, int(settings.ltx.default_text_size), 'article')

    # okraje jednoho formatu
    # vnejsi okraje ... okraje daneho prvku (napr. vnejsi okraj radku)
    # vnitrni okraje ... mezi bunkami daneho prvku (napr. vertialni okraje mezi bunkami 1 radku)
    if dxf.border:
        # vnejsi okraje
        if dxf.border.bottom:
            my_dxf.borders |= EBorder.BOTTOM
            my_dxf.border_styles[0] = EBorderStyle[dxf.border.bottom.style.upper()]
            my_dxf.border_colors[0] = colors.get_cell_color_nine(wb, dxf.border.bottom.color)
        if dxf.border.right:
            my_dxf.borders |= EBorder.RIGHT
            my_dxf.border_styles[1] = EBorderStyle[dxf.border.right.style.upper()]
            my_dxf.border_colors[1] = colors.get_cell_color_nine(wb, dxf.border.right.color)
        if dxf.border.top:
            my_dxf.borders |= EBorder.TOP
            my_dxf.border_styles[2] = EBorderStyle[dxf.border.top.style.upper()]
            my_dxf.border_colors[2] = colors.get_cell_color_nine(wb, dxf.border.top.color)
        if dxf.border.left:
            my_dxf.borders |= EBorder.LEFT
            my_dxf.border_styles[3] = EBorderStyle[dxf.border.left.style.upper()]
            my_dxf.border_colors[3] = colors.get_cell_color_nine(wb, dxf.border.left.color)

        # vnitrni okraje
        if dxf.border.horizontal:
            my_dxf.borders |= EBorder.INSIDE_H
            my_dxf.inside_border_styles[0] = EBorderStyle[dxf.border.horizontal.style.upper()]
            my_dxf.inside_border_colors[0] = colors.get_cell_color_nine(wb, dxf.border.horizontal.color)

        if dxf.border.vertical:
            my_dxf.borders |= EBorder.INSIDE_V
            my_dxf.inside_border_styles[1] = EBorderStyle[dxf.border.vertical.style.upper()]
            my_dxf.inside_border_colors[1] = colors.get_cell_color_nine(wb, dxf.border.vertical.color)

    return my_dxf


def get_table_style_custom(wb: Workbook, ws: Worksheet, style_str: str):
    """Funkce pro ziskani jednotlivych dxf u vsech casti vlastniho stylu tabulky."""

    if not wb:
        raise RuntimeError('Neplatny soubor')

    if not hasattr(wb, '_table_styles'):
        return None

    if not wb._table_styles.tableStyle:
        return None

    if not settings.conv.tables.enable:
        return None

    # prvni si zjistim ktere vlastni formaty tabulka ma a priradim si k nim patricny dxf, ktery si zrovna
    # prevedu na svuj format
    table_style = CTableStyle(style_str, False, get_table_options(ws, style_str))

    # tohle je vylozene slovnik, ty jmena u sveho chci mit takto
    attr_dict = {'wholeTable': 'whole_table', 'headerRow': 'header_row', 'totalRow': 'total_row',
                 'firstColumn': 'first_col', 'lastColumn': 'last_col', 'firstColumnStripe': 'odd_col',
                 'secondColumnStripe': 'even_col', 'firstRowStripe': 'odd_row', 'secondRowStripe': 'even_row',
                 'firstHeaderCell': 'first_header_cell', 'lastHeaderCell': 'last_header_cell',
                 'firstTotalCell': 'first_total_cell', 'lastTotalCell': 'last_total_cell'}

    # v pripade ze se okraje 2 casti tabulky prekryvaji, musi jedna z techto casti zvitezit. takze si ke kazdemu
    # okraji priradim prioritu tak, aby vyhral ten spravny.
    border_priority_dict = {'wholeTable': -10, 'headerRow': -9, 'totalRow': -9,
                            'firstColumn': -8, 'lastColumn': -8, 'firstColumnStripe': -7,
                            'secondColumnStripe': -6, 'firstRowStripe': -5, 'secondRowStripe': -4,
                            'firstHeaderCell': -3, 'lastHeaderCell': -3,
                            'firstTotalCell': -2, 'lastTotalCell': -2}

    for ts in wb._table_styles.tableStyle:
        # jiny styl nez ten co prevadim
        if ts.name != style_str:
            continue

        for elem in ts.tableStyleElement:
            attr_dxf = convert_dxf_from_id(wb, elem.dxfId)

            if attr_dxf is not None:
                # prepisu dxf dane casti tabulky
                setattr(table_style, attr_dict[elem.type], attr_dxf)

                # pokud to dxf ma okraje, pak jim priradim prioritu
                for i in range(4):
                    if attr_dxf.border_styles[i] != EBorderStyle.NONE:
                        attr_dxf.border_priorities[i] = border_priority_dict[elem.type]

            # sirka pruhovanych sloupcu/radku vetsi nez 1
            if elem.size is not None and elem.size > 1:
                if 'second' in elem.type:
                    if 'Column' in elem.type:
                        table_style.even_col_w = elem.size
                    elif 'Row' in elem.type:
                        table_style.even_row_h = elem.size
                elif 'first' in elem.type:
                    if 'Column' in elem.type:
                        table_style.odd_col_w = elem.size
                    elif 'Row' in elem.type:
                        table_style.odd_row_h = elem.size

    return table_style


def get_table_style_predefined(wb: Workbook, ws: Worksheet, predef_style: str, style_index: int):
    """Funkce pro ziskani jednotlivych dxf u vsech casti preddefinovaneho stylu tabulky. Techto stylu je celkem dost
        a jsou hardcoded ve specifikaci openoffice .xml"""

    if not wb:
        return None

    if not ws:
        return None

    if not predef_style:
        return None

    if style_index < 0:
        return None

    if not settings.conv.tables.enable:
        return None

    table_style = CTableStyle(predef_style, True, get_table_options(ws, predef_style))
    color_index = (style_index % 7) + 2

    # ninecolors pro prilis svetle barvy vsude udelal sedou (ktera nebyla o moc svetlejsi), nebo ty barvy udelal stejne.
    # zkratka mu chybi jeste 1 stupen. takze jedine reseni je proste ty vstupni barvy udelat o kousek tmavsi.
    # toto cislo vzniklo metodou pokus-omyl, rozhodne nefunguje ve 100 % pripadu.
    tint_correction1 = -0.0
    tint_correction2 = -0.0

    if 'Light' in predef_style:
        if style_index < 8:
            fg_nine = theme_and_tint_to_ninecolors(wb, color_index, 0, True)
            odd_bg = theme_and_tint_to_ninecolors(wb, color_index, tint=0.8 + tint_correction1, allow_black=True)

            table_style.whole_table = \
                CDxf(border_styles=utils.BS(EBorderStyle.THIN, [0, 2]),
                     border_colors=utils.BC(fg_nine, [0, 2]),
                     borders=EBorder.TOP | EBorder.BOTTOM,
                     border_priorities=(-10, -11, -10, -11),
                     bg=theme_and_tint_to_ninecolors(wb, 0, tint=0),
                     fg=fg_nine, )

            table_style.header_row = \
                CDxf(border_styles=utils.BS(EBorderStyle.THIN, [0]),
                     border_colors=utils.BC(fg_nine, [0]),
                     borders=EBorder.BOTTOM,
                     border_priorities=(-9, -11, -11, -11),
                     font_flags=EFontFlags.BOLD)

            table_style.odd_row = \
                CDxf(bg=odd_bg)

            table_style.first_col = CDxf(font_flags=EFontFlags.BOLD)
            table_style.odd_col = CDxf(bg=odd_bg)
            table_style.last_col = CDxf(font_flags=EFontFlags.BOLD)

            table_style.total_row = \
                CDxf(border_styles=utils.BS(EBorderStyle.THIN, [2]),
                     border_colors=utils.BC(fg_nine, [2]),
                     border_priorities=(-11, -11, -9, -11),
                     borders=EBorder.TOP,
                     font_flags=EFontFlags.BOLD)

        elif style_index < 15:
            border_color = theme_and_tint_to_ninecolors(wb, color_index, tint=0, allow_black=True)
            whole_bg_nine = theme_and_tint_to_ninecolors(wb, 0, tint=0)
            fg_nine = theme_and_tint_to_ninecolors(wb, 1, tint=0)

            table_style.whole_table = \
                CDxf(border_styles=utils.BS(EBorderStyle.THIN, [0, 1, 2, 3]),
                     border_colors=utils.BC(border_color, [0, 1, 2, 3]),
                     borders=EBorder.TOP | EBorder.BOTTOM | EBorder.LEFT | EBorder.RIGHT,
                     border_priorities=(-10, -10, -10, -10),
                     bg=whole_bg_nine,
                     fg=fg_nine)

            table_style.header_row = \
                CDxf(bg=border_color,
                     fg=whole_bg_nine,
                     font_flags=EFontFlags.BOLD)

            table_style.first_col = CDxf(font_flags=EFontFlags.BOLD)
            table_style.last_col = table_style.first_col

            table_style.odd = \
                CDxf(borders=EBorder.BOTTOM,
                     border_priorities=(-7, -11, -11, -11),
                     border_styles=utils.BS(EBorderStyle.THIN, [0]),
                     border_colors=utils.BC(border_color, [0]))

            table_style.even_row = \
                CDxf(borders=EBorder.BOTTOM,
                     border_priorities=(-11, -7, -11, -11),
                     border_styles=utils.BS(EBorderStyle.THIN, [2]),
                     border_colors=utils.BC(border_color, [2]))

            table_style.odd_col = \
                CDxf(borders=EBorder.LEFT,
                     border_priorities=(-11, -11, -11, -7),
                     border_styles=utils.BS(EBorderStyle.THIN, [3]),
                     border_colors=utils.BC(border_color, [3]))

            table_style.even_col = \
                CDxf(borders=EBorder.RIGHT,
                     border_priorities=(-11, -6, -11, -11),
                     border_styles=utils.BS(EBorderStyle.THIN, [1]),
                     border_colors=utils.BC(border_color, [1]))

            table_style.total_row = \
                CDxf(borders=EBorder.TOP,
                     border_priorities=(-11, -11, -9, -11),
                     border_styles=utils.BS(EBorderStyle.DOUBLE, [2]),
                     border_colors=utils.BC(border_color, [2]),
                     font_flags=EFontFlags.BOLD)

        elif style_index < 22:
            border_color = theme_and_tint_to_ninecolors(wb, color_index, tint=0, allow_black=True)
            whole_bg_nine = theme_and_tint_to_ninecolors(wb, 0, tint=0)
            fg_nine = theme_and_tint_to_ninecolors(wb, 1, tint=0)
            bg_odd = theme_and_tint_to_ninecolors(wb, color_index, tint=0.8 + tint_correction1)

            table_style.whole_table = \
                CDxf(border_styles=utils.BS(EBorderStyle.THIN, [0, 1, 2, 3]),
                     border_colors=utils.BC(border_color, [0, 1, 2, 3]),
                     borders=EBorder.TOP | EBorder.BOTTOM | EBorder.LEFT | EBorder.RIGHT |
                             EBorder.INSIDE_V | EBorder.INSIDE_H,
                     border_priorities=(-10, -10, -10, -10),
                     inside_border_styles=(EBorderStyle.THIN, EBorderStyle.THIN),
                     inside_border_colors=(border_color, border_color),
                     bg=whole_bg_nine,
                     fg=fg_nine)

            table_style.header_row = \
                CDxf(bg=whole_bg_nine,
                     fg=fg_nine,
                     font_flags=EFontFlags.BOLD)

            table_style.odd_col = CDxf(bg=bg_odd)
            table_style.odd_row = table_style.even_col

            table_style.first_col = CDxf(font_flags=EFontFlags.BOLD)
            table_style.last_col = table_style.first_col

            table_style.total_row = \
                CDxf(borders=EBorder.TOP,
                     border_priorities=(-11, -11, -9, -11),
                     border_styles=utils.BS(EBorderStyle.DOUBLE, [2]),
                     border_colors=utils.BC(border_color, [2]),
                     font_flags=EFontFlags.BOLD)

        else:
            return get_table_style_custom(wb, ws, predef_style)

    elif 'Medium' in predef_style:
        if style_index < 8:
            border_color = theme_and_tint_to_ninecolors(wb, color_index, tint=0, allow_black=True)
            whole_bg_nine = theme_and_tint_to_ninecolors(wb, 0, tint=0)
            fg_nine = theme_and_tint_to_ninecolors(wb, 1, tint=0)

            table_style.whole_table = \
                CDxf(border_styles=utils.BS(EBorderStyle.THIN, [0, 2]),
                     border_colors=utils.BC(border_color, [0, 2]),
                     borders=EBorder.TOP | EBorder.BOTTOM | EBorder.LEFT | EBorder.RIGHT | EBorder.INSIDE_H,
                     border_priorities=(-10, -10, -10, -10),
                     inside_border_styles=(EBorderStyle.THIN, EBorderStyle.NONE),
                     inside_border_colors=(border_color, EColor.NOT_SET),
                     bg=whole_bg_nine,
                     fg=fg_nine)

            table_style.header_row = \
                CDxf(bg=border_color,
                     fg=whole_bg_nine,
                     font_flags=EFontFlags.BOLD)

            table_style.odd_row = CDxf(bg=theme_and_tint_to_ninecolors(wb, color_index, tint=0.8 + tint_correction1))
            table_style.odd_col = table_style.odd_row

            table_style.first_col = CDxf(font_flags=EFontFlags.BOLD)
            table_style.last_col = table_style.first_col

            table_style.total_row = \
                CDxf(borders=EBorder.TOP,
                     border_priorities=(-11, -11, -9, -11),
                     border_styles=utils.BS(EBorderStyle.DOUBLE, [2]),
                     border_colors=utils.BC(border_color, [2]),
                     font_flags=EFontFlags.BOLD)

        elif style_index < 15:
            border_color = theme_and_tint_to_ninecolors(wb, 0, tint=0, allow_black=True)
            fg_nine = theme_and_tint_to_ninecolors(wb, 1, tint=0)
            head_bg = theme_and_tint_to_ninecolors(wb, color_index, tint=0, allow_black=True)

            table_style.whole_table = \
                CDxf(borders=EBorder.INSIDE_V | EBorder.INSIDE_H,
                     border_priorities=(-10, -10, -10, -10),
                     inside_border_styles=(EBorderStyle.THIN, EBorderStyle.THIN),
                     inside_border_colors=(border_color, border_color),
                     fg=fg_nine,
                     bg=theme_and_tint_to_ninecolors(wb, color_index, tint=0.8 + tint_correction1))

            table_style.header_row = \
                CDxf(borders=EBorder.BOTTOM,
                     border_styles=utils.BS(EBorderStyle.MEDIUM, [0]),
                     border_colors=utils.BC(border_color, [0]),
                     border_priorities=(-9, -11, -11, -11),
                     bg=head_bg,
                     fg=border_color,
                     font_flags=EFontFlags.BOLD)

            table_style.odd_row = CDxf(bg=theme_and_tint_to_ninecolors(wb, color_index, tint=0.6 + tint_correction2))
            table_style.odd_col = table_style.odd_row

            table_style.first_col = CDxf(bg=head_bg, fg=border_color)
            table_style.last_col = table_style.first_col

            table_style.total_row = \
                CDxf(borders=EBorder.TOP,
                     border_priorities=(-11, -11, -9, -11),
                     border_styles=utils.BS(EBorderStyle.MEDIUM, [2]),
                     border_colors=utils.BC(border_color, [2]),
                     bg=head_bg,
                     fg=border_color,
                     font_flags=EFontFlags.BOLD)

        elif style_index < 22:
            border_color = theme_and_tint_to_ninecolors(wb, 1, tint=0, allow_black=True)
            whole_bg_nine = theme_and_tint_to_ninecolors(wb, 0, tint=0)
            fg_nine = theme_and_tint_to_ninecolors(wb, 1, tint=0)
            head_bg = theme_and_tint_to_ninecolors(wb, color_index, tint=0, allow_black=True)

            table_style.whole_table = \
                CDxf(border_styles=utils.BS(EBorderStyle.THIN, [0, 2]),
                     border_colors=utils.BC(border_color, [0, 2]),
                     borders=EBorder.TOP | EBorder.BOTTOM,
                     border_priorities=(-10, -11, -10, -11),
                     bg=whole_bg_nine,
                     fg=fg_nine)

            table_style.header_row = \
                CDxf(bg=head_bg,
                     fg=whole_bg_nine,
                     font_flags=EFontFlags.BOLD,
                     borders=EBorder.BOTTOM,
                     border_priorities=(-9, -11, -11, -11),
                     border_styles=utils.BS(EBorderStyle.MEDIUM, [0]),
                     border_colors=utils.BC(border_color, [0]))

            table_style.odd_row = CDxf(bg=theme_and_tint_to_ninecolors(wb, 1, tint=0.8 + tint_correction1))
            table_style.odd_col = table_style.odd_row

            table_style.first_col = \
                CDxf(bg=head_bg,
                     fg=whole_bg_nine,
                     font_flags=EFontFlags.BOLD)

            table_style.last_col = table_style.first_col

            table_style.first_total_cell = table_style.first_col
            table_style.last_total_cell = table_style.first_col

            table_style.total_row = \
                CDxf(borders=EBorder.TOP,
                     border_priorities=(-11, -11, -9, -11),
                     border_styles=utils.BS(EBorderStyle.DOUBLE, [2]),
                     border_colors=utils.BC(border_color, [2]))

        elif style_index < 29:
            border_color = theme_and_tint_to_ninecolors(wb, color_index, tint=0.6 + tint_correction2, allow_black=True)
            whole_bg_nine = theme_and_tint_to_ninecolors(wb, color_index, tint=0.8 + tint_correction1)
            fg_nine = theme_and_tint_to_ninecolors(wb, 1, tint=0)

            table_style.whole_table = \
                CDxf(border_styles=utils.BS(EBorderStyle.THIN, [0, 1, 2, 3]),
                     border_colors=utils.BC(border_color, [0, 1, 2, 3]),
                     borders=EBorder.TOP | EBorder.BOTTOM | EBorder.LEFT | EBorder.RIGHT |
                             EBorder.INSIDE_V | EBorder.INSIDE_H,
                     border_priorities=(-10, -10, -10, -10),
                     inside_border_styles=(EBorderStyle.THIN, EBorderStyle.THIN),
                     inside_border_colors=(border_color, border_color),
                     bg=whole_bg_nine,
                     fg=fg_nine)

            table_style.header_row = \
                CDxf(font_flags=EFontFlags.BOLD)

            table_style.odd_row = \
                CDxf(bg=theme_and_tint_to_ninecolors(wb, color_index, tint=0.6 + tint_correction2))

            table_style.odd_col = table_style.odd_row
            table_style.first_col = CDxf(font_flags=EFontFlags.BOLD)
            table_style.last_col = table_style.first_col

            total_border_nine = theme_and_tint_to_ninecolors(wb, color_index, tint=0, allow_black=True)
            table_style.total_row = \
                CDxf(borders=EBorder.TOP,
                     border_priorities=(-11, -11, -9, -11),
                     border_styles=utils.BS(EBorderStyle.MEDIUM, [2]),
                     border_colors=utils.BC(total_border_nine, [2]),
                     font_flags=EFontFlags.BOLD)

        else:
            return get_table_style_custom(wb, ws, predef_style)

    elif 'Dark' in predef_style:
        if style_index < 8:
            border_color = theme_and_tint_to_ninecolors(wb, 0, tint=0, allow_black=True)
            head_bg = theme_and_tint_to_ninecolors(wb, 1, tint=0)

            table_style.whole_table = \
                CDxf(fg=border_color)

            table_style.header_row = \
                CDxf(borders=EBorder.BOTTOM,
                     border_priorities=(-9, -11, -11, -11),
                     border_styles=utils.BS(EBorderStyle.MEDIUM, [0]),
                     border_colors=utils.BC(border_color, [0]),
                     bg=head_bg,
                     font_flags=EFontFlags.BOLD)

            odd_bg = theme_and_tint_to_ninecolors(wb, color_index, tint=-0.25)

            table_style.odd_row = CDxf(bg=odd_bg)
            table_style.even_row = CDxf(bg=theme_and_tint_to_ninecolors(wb, color_index, tint=0, allow_black=True))

            table_style.first_col = \
                CDxf(borders=EBorder.RIGHT,
                     border_priorities=(-11, -8, -11, -11),
                     border_styles=utils.BS(EBorderStyle.MEDIUM, [1]),
                     border_colors=utils.BC(border_color, [1]),
                     font_flags=EFontFlags.BOLD)

            table_style.last_col = \
                CDxf(bg=odd_bg,
                     font_flags=EFontFlags.BOLD)

            table_style.total_row = \
                CDxf(borders=EBorder.TOP,
                     border_priorities=(-11, -11, -9, -11),
                     border_styles=utils.BS(EBorderStyle.MEDIUM, [2]),
                     border_colors=utils.BC(border_color, [2]),
                     bg=theme_and_tint_to_ninecolors(wb, color_index, tint=-0.5),
                     font_flags=EFontFlags.BOLD)

        elif style_index == 8:
            border_color = theme_and_tint_to_ninecolors(wb, color_index, tint=0, allow_black=True)
            whole_bg_nine = theme_and_tint_to_ninecolors(wb, 0, tint=-0.15)
            odd_bg_nine = theme_and_tint_to_ninecolors(wb, 0, tint=-0.35)
            fg_nine = theme_and_tint_to_ninecolors(wb, 1, tint=0)

            table_style.whole_table = \
                CDxf(bg=whole_bg_nine,
                     fg=fg_nine)

            table_style.header_row = \
                CDxf(bg=border_color,
                     fg=theme_and_tint_to_ninecolors(wb, 0, tint=0))

            table_style.odd_row = CDxf(bg=odd_bg_nine)
            table_style.odd_col = table_style.odd_row

            table_style.first_col = CDxf(font_flags=EFontFlags.BOLD)
            table_style.last_col = table_style.first_col

            table_style.first_header_cell = CDxf(font_flags=EFontFlags.BOLD)
            table_style.last_header_cell = table_style.first_header_cell

            table_style.total_row = \
                CDxf(borders=EBorder.TOP,
                     border_priorities=(-11, -11, -9, -11),
                     border_styles=utils.BS(EBorderStyle.DOUBLE, [2]),
                     border_colors=utils.BC(border_color, [2]),
                     font_flags=EFontFlags.BOLD)

        elif style_index < 12:
            fg_nine = theme_and_tint_to_ninecolors(wb, 1, 0, True)
            odd_bg = theme_and_tint_to_ninecolors(wb, color_index, tint=0.6 + tint_correction2)
            even_bg = theme_and_tint_to_ninecolors(wb, color_index, tint=0.8 + tint_correction1)

            table_style.whole_table = \
                CDxf(bg=even_bg,
                     fg=fg_nine)

            table_style.header_row = \
                CDxf(bg=theme_and_tint_to_ninecolors(wb, color_index - 1, tint=0, allow_black=True),
                     fg=theme_and_tint_to_ninecolors(wb, 0, tint=0, allow_black=True))

            table_style.odd_row = CDxf(bg=odd_bg)
            table_style.odd_col = table_style.odd_row

            table_style.first_col = CDxf(font_flags=EFontFlags.BOLD)
            table_style.last_col = table_style.first_col

            table_style.total_row = \
                CDxf(border_styles=utils.BS(EBorderStyle.DOUBLE, [2]),
                     border_colors=utils.BC(fg_nine, [2]),
                     border_priorities=(-11, -11, -9, -11),
                     borders=EBorder.TOP,
                     font_flags=EFontFlags.BOLD)

        else:
            return get_table_style_custom(wb, ws, predef_style)

    return table_style


def get_table_style_from_theme(wb: Workbook, ws: Worksheet, table_style_str: str):
    """Funkce pro ziskani jednotlivych formatu (dxf) tabulky z nazvu jejiho stylu."""

    if not wb:
        return None

    if not table_style_str:
        return None

    is_pre_defined = re.search(r'^TableStyle(Dark|Light|Medium)\d{1,2}$', table_style_str)

    # jmenuje se styl tabulky TableStyleDark6, nebo TableStyleLight13, apod.?
    if is_pre_defined is not None:
        style_match = re.search(r'\d{1,2}$', table_style_str)
        style_index = int(style_match.group())
        table_style = get_table_style_predefined(wb, ws, table_style_str, style_index)

        if table_style is None:
            table_style = get_table_style_custom(wb, ws, table_style_str)

    # pokud ne, tak neni preddefinovany
    else:
        table_style = get_table_style_custom(wb, ws, table_style_str)

    return table_style


def get_table_options(ws: Worksheet, table_style_str: str):
    """Funkce pro ziskani dodatecnych nastaveni tabulky (pruhovane sloupce, zahlavi, radek sourhnu...)"""

    options = ETableOptions.NONE

    for tbl in ws.tables.values():
        if tbl.tableStyleInfo.name != table_style_str:
            continue

        if (tbl.headerRowCount is not None and tbl.headerRowCount > 0) \
                or settings.conv.tables.head:
            options |= ETableOptions.HEADER_ROW

        if (tbl.totalsRowCount is not None and tbl.totalsRowCount > 0) \
                or settings.conv.tables.total:
            options |= ETableOptions.TOTAL_ROW

        if tbl.tableStyleInfo.showColumnStripes or settings.conv.tables.stripe_v:
            options |= ETableOptions.COL_STRIPES

        if tbl.tableStyleInfo.showRowStripes or settings.conv.tables.stripe_h:
            options |= ETableOptions.ROW_STRIPES

        if tbl.tableStyleInfo.showFirstColumn:
            options |= ETableOptions.FIRST_COL

        if tbl.tableStyleInfo.showLastColumn:
            options |= ETableOptions.LAST_COL

    if options != ETableOptions.NONE:
        options ^= ETableOptions.NONE

    return options


def is_cell_in_table(cell: Cell, table_styles: 'list[CTableStyle]',
                     table_ranges: 'list[tuple[tuple[int, int], tuple[int, int]]]'):
    """Funkce zjisti zda se konkretni bunka nachazi v oblasti ktera je formatovana jako tabulka"""

    if not cell:
        return False, None, None

    if not table_styles:
        return False, None, None

    if not table_ranges:
        return False, None, None

    i = 0
    for table_range in table_ranges:
        (minx, miny), (maxx, maxy) = table_range

        if miny <= cell.row <= maxy:
            if minx <= cell.column <= maxx:
                return True, table_styles[i], table_range

        i += 1

    return False, None, None


def cell_which_parts_of_table(cell: Cell, is_in_table: bool, table_style: CTableStyle,
                              table_range: 'tuple[tuple[int, int], tuple[int, int]]'):
    """Funkce vrati nazvy vsech casti tabulky do kterych bunka patri. Podle toho se bude moct zjistit
    format teto bunky, protoze jednotlive casti tabulek maji ruzne formaty, ktere se 'nabaluji'."""

    if is_in_table is None:
        return None

    if table_range is None:
        return None

    if not is_in_table:
        return None

    if not cell:
        return None

    if table_style is None:
        return None

    table_options = table_style.options
    row_h_e = table_style.even_row_h
    row_h_o = table_style.odd_row_h
    col_w_e = table_style.even_col_w
    col_w_o = table_style.odd_col_w

    (minx, miny), (maxx, maxy) = table_range

    parts = ['whole_table']
    odd_start = 2 if table_options & ETableOptions.HEADER_ROW else 1

    is_odd_col = utils.is_odd_table_col(cell.column - minx + 1, range(minx, maxx + 1), col_w_e, col_w_o, 1)
    is_odd_row = utils.is_odd_table_row(cell.row - miny + 1, range(miny, maxy + 1), row_h_e, row_h_o, odd_start)

    # takovato if silenost je tu proto, abych mel jiste poradi tech prvku. asi by sla zjednodusit.
    if table_options & ETableOptions.COL_STRIPES:
        if is_odd_col:
            parts.append('odd_col')
        else:
            parts.append('even_col')

    if table_options & ETableOptions.ROW_STRIPES:
        if is_odd_row:
            parts.append('odd_row')
        else:
            parts.append('even_row')

    if cell.column == maxx and table_options & ETableOptions.LAST_COL:
        parts.append('last_col')

    elif cell.column == minx and table_options & ETableOptions.FIRST_COL:
        parts.append('first_col')

    if cell.row == miny and table_options & ETableOptions.HEADER_ROW:
        parts.append('header_row')

        if cell.column == minx and table_options & ETableOptions.FIRST_COL:
            parts.append('first_header_cell')

        elif cell.column == maxx and table_options & ETableOptions.LAST_COL:
            parts.append('last_header_cell')

    elif cell.row == maxy and table_options & ETableOptions.TOTAL_ROW:
        parts.append('total_row')

        if cell.column == minx and table_options & ETableOptions.FIRST_COL:
            parts.append('first_total_cell')

        elif cell.column == maxx and table_options & ETableOptions.LAST_COL:
            parts.append('last_total_cell')

    return parts


def get_cell_style_from_table(cell: Cell, table_styles: 'list[CTableStyle]',
                              table_ranges: 'list[tuple[tuple[int, int], tuple[int, int]]]'):
    """Funknce zjistuje zda dana bunka nema nejake formaty z tech casti listu v excelu, ktere jsou formatovany jako
    tabulka. Pote projde vsemi castmi tabulky, pod ktere dana bunka spada. Postupne na bunku nabaluje styly techto
    casti. Dulezite je aby tyto casti byly serazeny od tech s nejnizsi prioritou po ty s nejvyssi"""

    if not settings.conv.tables.enable:
        return CCell(cell.coordinate)

    my_cell = CCell(cell.coordinate)

    is_in_table, table_style, table_range = is_cell_in_table(cell, table_styles, table_ranges)

    if table_style is None:
        return None

    table_parts = cell_which_parts_of_table(cell, is_in_table, table_style, table_range)

    if table_parts is None:
        return None

    (minx, miny), (maxx, maxy) = table_range

    for part in table_parts:
        cur_dxf: CDxf = getattr(table_style, part)
        my_cell.dxf += cur_dxf

    if not settings.conv.tables.borders:
        my_cell.remove_borders()
        return my_cell

    # v pripade ze nema bunka nema spodni okraj, ale styl tabulky definuje vnitrni okraje, pak za predpokladu
    # ze bunka neni na okraji tohoto stylu musime vnitrni premenit na klasicky
    if not my_cell.dxf.borders & EBorder.BOTTOM:
        if cell.row < maxy:
            # horizontalni vnitrni okraje pro sloupce s sirkou stylu 1
            if my_cell.dxf.inside_border_styles[0] != EBorderStyle.NONE:
                my_cell.dxf.borders |= EBorder.BOTTOM
                my_cell.dxf.border_styles[0] = my_cell.dxf.inside_border_styles[0]
                my_cell.dxf.border_colors[0] = my_cell.dxf.inside_border_colors[0]

            # horizontalni vnitrni okraje pro sloupce s sirkou stylu vetsi nez 1
            elif table_style.odd_col_w > 1 and 'odd_col' in table_parts \
                    or table_style.even_col_w > 1 and 'even_col' in table_parts:
                my_cell.dxf.borders |= EBorder.BOTTOM
                my_cell.dxf.border_styles[0] = my_cell.dxf.inside_border_styles[0]
                my_cell.dxf.border_colors[0] = my_cell.dxf.inside_border_colors[0]

    if not my_cell.dxf.borders & EBorder.RIGHT:
        if cell.column < maxx:
            # vertikalni vnitrni okraje pro radky s vyskou stylu 1
            if my_cell.dxf.inside_border_styles[1] != EBorderStyle.NONE:
                my_cell.dxf.borders |= EBorder.RIGHT
                my_cell.dxf.border_styles[1] = my_cell.dxf.inside_border_styles[1]
                my_cell.dxf.border_colors[1] = my_cell.dxf.inside_border_colors[1]

            # vertikalni vnitrni okraje pro radky s vyskou stylu vetsi nez 1
            elif table_style.odd_row_h > 1 and 'odd_row' in table_parts \
                    or table_style.even_row_h > 1 and 'even_row' in table_parts:
                my_cell.dxf.borders |= EBorder.RIGHT
                my_cell.dxf.border_styles[1] = my_cell.dxf.inside_border_styles[1]
                my_cell.dxf.border_colors[1] = my_cell.dxf.inside_border_colors[1]

    my_cell.border_priorties = [-8, -8, -8, -8]

    if not settings.conv.border.style:
        for i, bs in enumerate(my_cell.dxf.border_styles):
            if bs != EBorderStyle.NONE:
                my_cell.dxf.border_styles[i] = EBorderStyle.THIN

    if not settings.conv.color.border:
        for i, bc in enumerate(my_cell.dxf.border_colors):
            if bc not in [EColor.NOT_SET, EColor.BLACK]:
                my_cell.dxf.border_colors[i] = EColor.NOT_SET

    return my_cell
