# OBSAH SOUBORU:
# - definice vlastnich datovych typu (bunky, radky, ...)

from openpyxl.cell import Cell

import legend_entries
from enums import EFontSize, EColor, EHAlign, EVAlign, EFontFlags, EConvertedState, EMergedCell, EBorder, EBorderStyle, \
    ETableOptions, ELtxTableType


class CDxf:
    def __init__(self,
                 font_flags: EFontFlags = EFontFlags.NONE,
                 font_size: EFontSize = EFontSize.NORMAL,
                 bg: EColor = EColor.NOT_SET,
                 fg: EColor = EColor.NOT_SET,
                 halign: EHAlign = EHAlign.NONE,
                 valign: EVAlign = EVAlign.NONE,
                 borders: EBorder = EBorder.NONE,
                 border_styles = (EBorderStyle.NONE, EBorderStyle.NONE, EBorderStyle.NONE, EBorderStyle.NONE),
                 border_colors=(EColor.NOT_SET, EColor.NOT_SET, EColor.NOT_SET, EColor.NOT_SET),
                 inside_border_styles= (EBorderStyle.NONE, EBorderStyle.NONE),
                 inside_border_colors = (EColor.NOT_SET, EColor.NOT_SET),
                 border_priorities = (-11, -11, -11, -11)):

        self.font_flags: EFontFlags = font_flags
        self.font_size: EFontSize = font_size
        self.bgcolor = bg
        self.fgcolor = fg
        self.text_halign: EHAlign = halign
        self.text_valign: EVAlign = valign
        self.borders: EBorder = borders
        #                    bot           right            top         left
        self.border_styles=list(border_styles)
        self.border_colors=list(border_colors)
        self.border_priorities= list(border_priorities)
        #                           horizontal     vertical
        self.inside_border_styles = list(inside_border_styles)
        self.inside_border_colors = list(inside_border_colors)

    def __eq__(self, other):
        return self.fgcolor == other.fgcolor and \
               self.bgcolor == other.bgcolor and \
               self.font_flags == other.font_flags and \
               self.font_size == other.font_size and \
               self.text_halign == other.text_halign and \
               self.text_valign == other.text_valign

    def __add__(self, other):
        if not isinstance(other, CDxf):
            return NotImplemented

        self.font_flags |= other.font_flags

        self.font_size = other.font_size

        if other.bgcolor != EColor.NOT_SET:
            self.bgcolor = other.bgcolor

        if other.fgcolor != EColor.NOT_SET:
            self.fgcolor = other.fgcolor

        self.borders |= other.borders

        for i in range(4):
            if other.border_priorities[i] > self.border_priorities[i]:
                self.border_priorities[i] = other.border_priorities[i]
            elif other.border_priorities[i] < self.border_priorities[i]:
                continue

            if other.border_styles[i] != EBorderStyle.NONE:
                self.border_styles[i] = other.border_styles[i]

            if other.border_colors[i] != EColor.NOT_SET:
                self.border_colors[i] = other.border_colors[i]

        for i in range(2):
            if other.inside_border_styles[i] != EBorderStyle.NONE:
                self.inside_border_styles[i] = other.inside_border_styles[i]

            if other.inside_border_colors[i] != EColor.NOT_SET:
                self.inside_border_colors[i] = other.inside_border_colors[i]

        if other.text_halign != EHAlign.NONE:
            self.text_halign = other.text_halign

        if other.text_valign != EVAlign.NONE:
            self.text_valign = other.text_valign

        return self


class CTableStyle:
    def __init__(self, theme: str, is_predefined: bool, table_options: ETableOptions):
        self.whole_table = CDxf()
        self.header_row = CDxf()
        self.total_row = CDxf()
        self.first_col = CDxf()
        self.last_col = CDxf()
        self.odd_row = CDxf()
        self.even_row = CDxf()
        self.odd_col = CDxf()
        self.even_col = CDxf()
        self.first_header_cell = CDxf()
        self.last_header_cell = CDxf()
        self.first_total_cell = CDxf()
        self.last_total_cell = CDxf()
        self.theme: str = theme
        self.is_predefined: bool = is_predefined
        self.options: ETableOptions = table_options
        self.odd_col_w = 1
        self.even_col_w = 1
        self.odd_row_h = 1
        self.even_row_h = 1


class CCell:
    def __init__(self, coord: str):
        self.coord = coord
        self.y = -1
        self.x = -1
        self.value = None
        self.disp_value: str = None
        self.dxf = CDxf()
        self.is_merged: EMergedCell = EMergedCell.NOT_MERGED
        self.merged_size= (1, 1)  # cols, rows
        self.is_converted: EConvertedState = EConvertedState.NOT_CONV

    def __eq__(self, other):
        if not isinstance(other, CCell):
            return NotImplemented

        return self.coord == other.coord and \
               self.value == other.value and \
               self.disp_value == other.disp_value and \
               self.dxf == other.dxf

    # tento pristup funguje jen kdyz ty formatovani aplikujete ve spravnem poradi
    def __add__(self, other):
        if not isinstance(other, CCell):
            return NotImplemented

        self.dxf += other.dxf

        return self

    def remove_borders(self):
        self.dxf.borders = EBorder.NONE
        self.dxf.border_priorities = [-11, -11, -11, -11]
        self.dxf.border_styles = [EBorderStyle.NONE, EBorderStyle.NONE, EBorderStyle.NONE, EBorderStyle.NONE]
        self.dxf.border_colors = [EColor.NOT_SET, EColor.NOT_SET, EColor.NOT_SET, EColor.NOT_SET]
        self.dxf.inside_border_styles = [EBorderStyle.NONE, EBorderStyle.NONE]
        self.dxf.inside_border_colors = [EColor.NOT_SET, EColor.NOT_SET]

    def get_halign(self, cell: Cell):
        if cell.alignment is not None:
            if cell.alignment.horizontal is not None:
                cell_alignment = cell.alignment.horizontal[0]
                if cell_alignment == 'l':
                    self.dxf.text_halign = EHAlign.LEFT
                elif cell_alignment == 'r':
                    self.dxf.text_halign = EHAlign.RIGHT
                elif cell_alignment == 'c':
                    self.dxf.text_halign = EHAlign.CENTER
                else:
                    self.dxf.text_halign = EHAlign.NONE

    def get_valign(self, cell: Cell):
        if cell.alignment is not None:
            if cell.alignment.vertical is not None:
                cell_alignment = cell.alignment.vertical[0]
                if cell_alignment in ['m', 'c']:
                    self.dxf.text_valign = EVAlign.MIDDLE
                elif cell_alignment == 't':
                    self.dxf.text_valign = EVAlign.TOP
                elif cell_alignment == 'b':
                    self.dxf.text_valign = EVAlign.BOTTOM


class CCellDO:
    def __init__(self, coord: str):
        self.coord = coord
        self.y = -1
        self.x = -1
        self.disp_value: str = ''
        self.is_merged: EMergedCell = EMergedCell.NOT_MERGED
        self.merged_size = (1, 1)  # cols, rows


class CRow:
    def __init__(self):
        self.index = -1
        self.members = []
        self.shared_bgcolor: EColor = EColor.NOT_SET
        self.shared_fgcolor: EColor = EColor.NOT_SET
        self.shared_font_size: EFontSize = EFontSize.NORMAL
        self.shared_font_flags: EFontFlags = EFontFlags.NONE
        self.shared_text_halign: EHAlign = EHAlign.NONE
        self.shared_text_valign: EVAlign = EVAlign.NONE
        self.vsize: float = 0
        self.is_converted: EConvertedState = EConvertedState.NOT_CONV
        self.whole_borders_clr: EColor = EColor.NOT_SET
        self.whole_borders: EBorderStyle = EBorderStyle.NONE

    def __eq__(self, other):
        if not isinstance(other, CRow):
            return NotImplemented

        return self.shared_fgcolor == other.shared_fgcolor \
               and self.shared_bgcolor == other.shared_bgcolor \
               and self.shared_font_size == other.shared_font_size \
               and self.shared_font_flags == other.shared_font_flags \
               and self.shared_text_valign == other.shared_text_valign \
               and self.shared_text_halign == other.shared_text_halign \
               and self.vsize == other.vsize

    def __iter__(self):
        return self.members

    def has_align_only(self):
        all_else = (self.shared_fgcolor == EColor.NOT_SET or self.shared_fgcolor == EColor.WHITE) \
                   and (self.shared_bgcolor == EColor.NOT_SET or self.shared_bgcolor == EColor.WHITE) \
                   and self.shared_font_size == EFontSize.NORMAL \
                   and self.shared_font_flags is EFontFlags.NONE

        return all_else and self.shared_text_halign != EHAlign.NONE, \
                            self.shared_text_valign != EVAlign.NONE

class CCol:
    def __init__(self):
        self.index = -1
        self.members = []
        self.shared_bgcolor: EColor = EColor.NOT_SET
        self.shared_fgcolor: EColor = EColor.NOT_SET
        self.shared_font_size: EFontSize = EFontSize.NORMAL
        self.shared_font_flags: EFontFlags = EFontFlags.NONE
        self.shared_text_halign: EHAlign = EHAlign.NONE
        self.shared_text_valign: EVAlign = EVAlign.NONE
        self.hsize: float = 0
        self.is_converted: EConvertedState = EConvertedState.NOT_CONV
        self.max_char_size: int = 0
        self.whole_borders_clr: EColor = EColor.NOT_SET
        self.whole_borders: EBorderStyle = EBorderStyle.NONE

    def __eq__(self, other):
        if not isinstance(other, CCol):
            return NotImplemented

        return self.shared_fgcolor == other.shared_fgcolor \
               and self.shared_bgcolor == other.shared_bgcolor \
               and self.shared_font_size == other.shared_font_size \
               and self.shared_font_flags == other.shared_font_flags \
               and self.shared_text_valign == other.shared_text_valign \
               and self.shared_text_halign == other.shared_text_halign
               # and self.hsize == other.hsize

    def __iter__(self):
        return self.members

    def has_align_only(self):
        all_else = (self.shared_fgcolor == EColor.NOT_SET or self.shared_fgcolor == EColor.WHITE) \
                   and (self.shared_bgcolor == EColor.NOT_SET or self.shared_bgcolor == EColor.WHITE) \
                   and self.shared_font_size == EFontSize.NORMAL \
                   and self.shared_font_flags == EFontFlags.NONE

        return all_else and self.shared_text_halign != EHAlign.NONE, \
               all_else and self.shared_text_valign != EHAlign.NONE


class CTableConvert:
    def __init__(self):
        self.enable:  bool = True
        self.borders: bool = True
        self.head: bool = False
        self.total: bool = False
        self.stripe_h: bool = False
        self.stripe_v: bool = False
        self.first_last: bool = False

    def disable(self):
        self.borders: bool = False
        self.head: bool = False
        self.total: bool = False
        self.stripe_h: bool = False
        self.stripe_v: bool = False
        self.first_last: bool = False


class CCondiConvert:
    def __init__(self):
        self.enable:  bool = True
        self.borders: bool = True
        self.colorscale: bool = True

    def disable(self):
        self.borders: bool = False
        self.colorscale: bool = False


class CColorSettings:
    def __init__(self):
        self.enable: bool = True
        self.fg: bool = True
        self.bg: bool = True
        self.border: bool = True

    def disable(self):
        self.fg: bool = False
        self.bg: bool = False
        self.border: bool = False


class CTextSettings:
    def __init__(self):
        self.enable: bool = True
        self.flags: bool = True
        self.textsize: bool = True
        self.roman: bool = False

    def disable(self):
        self.flags: bool = False
        self.textsize: bool = False
        self.roman: bool = False


class CBorderSettings:
    def __init__(self):
        self.enable: bool = True
        self.style: bool = True

    def disable(self):
        self.style: bool = False


class CConvertSettings:
    def __init__(self):
        self.tables = CTableConvert()
        self.condi = CCondiConvert()
        self.color = CColorSettings()
        self.text = CTextSettings()
        self.border = CBorderSettings()
        self.width: bool = True
        self.height: bool = False
        self.halign: bool = True
        self.valign: bool = True
        self.data_only: bool = False
        self.convert_all: bool = False
        self.custom_head: str = legend_entries.custom_head_intro


class CLatexSettings:
    def __init__(self):
        self.document_class: str = 'article'
        self.document_class_index: int = 0
        self.default_text_size: str = '12'
        self.default_text_size_index: int = 2
        self.align: bool = True
        self.escape: bool = True
        self.dont_escape_math: bool = False
        self.table_type: ELtxTableType = ELtxTableType.NORMAL
        self.longt: CLongTableSettings = CLongTableSettings()
        self.use_setcell: bool = False
        self.caption: str = 'UPRAVme'
        self.dec_separator: str = '.'
        self.thousand_separator: str = '~'
        self.rotate_ccw = True
        self.excel_frac_as_ltx_frac: bool = True
        self.use_sci_nums: bool = False
        self.max_char_width: int = 80
        self.table_hbt: str = 'ht'
        self.use_slshape: bool = False
        self.caption_top: bool = True


class CLongTableSettings:
    def __init__(self):
        self.head_row_count: int = 1
        self.total_row_count: int = 1
        self.caption: str = ''
        self.conthead_text: str = '(pokračování)'
        self.contfoot_text: str = 'Pokračuje na další straně'


class CLegendSettings:
    def __init__(self):
        # nastaveni legendy jako takove
        self.enabled: bool = True
        self.syntax: bool = True
        self.params: bool = False
        self.abbrs: bool = False
        self.expl: bool = True
        self.on_top: bool = False

        # muj denicek toho co se ma v te legende zobrazit pri tisku. tyto nastavim v prubehu prevodu.
        self._hlines: bool = False
        self._vlines: bool = False
        self._hline: bool = False
        self._vline: bool = False
        self._rows: bool = False
        self._columns: bool = False
        self._row: bool = False
        self._column: bool = False
        self._colspec: bool = False
        self._rowspec: bool = False
        self._cell: bool = False
        self._setcell: bool = False

        # k popisu zkratek
        self._bg: bool = False
        self._fg: bool = False
        self._font_cmds: bool = False
        self._latex_cmd: bool = False
        self._typ_sloupce: bool = False
        self._typ_okraje: bool = False
        self._halign: bool = False
        self._valign: bool = False
        self._ht: bool = False
        self._wd: bool = False

    def disable(self):
        self.syntax: bool = False
        self.params: bool = False
        self.expl: bool = False
        self.on_top: bool = False
        self.abbrs: bool = False


class CInputsSettings:
    def __init__(self):
        self.should_load_input: bool = True
        self.start_cell: str = ''
        self.end_cell: str = ''
        self.last_conv_type: str = 'convert_table'


class CProgramSettings:
    def __init__(self):
        self.scale: float = 1
        self.scale_int: int = 100
        self.dark_mode: bool = True
        self.console_mode: bool = False


class CWarning:
    def __init__(self):
        self.uuline: bool = False
        self.rotated_text: bool = False
        self.shitton_of_borders: bool = False
        self.wrong_color: bool = False
        self.filter: bool = False
        self.pivot_table: bool = False
        self.data_only_merged: bool = False

