from helper import remove_accents
from systools import sys_log_exception
from typing import (
    List,
)

from basereport import (
    SimpleReport,
    TableReport,
    ReportColumnDefinition,
    AlignTypes,
)
from report import (
    Presenter,
    Part,
)
from report.command import (
    NewLineCommand,
    RepeatCommand,
    FontCommand,
    AlignCommand,
)

from reportsdata.justificationreport.dto import (
    JustificationGeneratorDto,
    JustificationBodyDto,
    JustificationHeaderDto,
)
from utils import format_line


class JustificationReportPresenter(Presenter):

    def __init__(
        self,
        columns,    # type: int
    ):
        # type: (...) -> None

        self.total = 0
        self.columns = columns

        self.header_column_definition = [
            ReportColumnDefinition(
                width=columns,
                align=AlignTypes.CENTER,
            )
        ]

        self.body_definitions = [
            ReportColumnDefinition(width=16, after_fill_text=': ', fill_with_char=''),
            ReportColumnDefinition(width=columns - 16)
        ]

        self.center_definitions = [
            ReportColumnDefinition(width=columns),
        ]

        self.footer_column_definition = [
            ReportColumnDefinition(
                width=columns,
                align=AlignTypes.CENTER,
            )
        ]

    def present(
        self,
        dto,     # type: JustificationGeneratorDto
    ):
        # type: (...) -> SimpleReport

        try:
            parts = [Part(commands=[FontCommand(FontCommand.Font.B)])]
            parts.extend(self._build_header(dto.header))
            parts.extend(self._build_body(dto.body))
            parts.extend(self._build_footer())
            parts.extend([Part(None, [NewLineCommand()])])
        except Exception as _:
            sys_log_exception("Error building Benefits Report")
            raise

        return SimpleReport(
            parts=parts,
            width=self.columns,
        )

    def _build_header(
        self,
        header,      # type: JustificationHeaderDto
    ):
        # type: (...) -> List

        parts = [
            self._get_title(header.title)[0],
        ]

        if header.subtitle:
            parts.append(
                self._get_title(header.subtitle)[0],
            )

        parts.append(
            Part(
                text=None,
                commands=[
                    RepeatCommand(self.columns, "="),
                    NewLineCommand(),
                    AlignCommand(AlignCommand.Alignment.center)
                ],
            ),
        )

        return parts

    def _build_body(
        self,
        body,    # type: JustificationBodyDto
    ):
        # type: (...) -> List

        parts = []

        parts.extend(
            self._get_line(
                title="$ORDER",
                text=body.order_id,
                definition=self.body_definitions,
            )
        )

        parts.extend(
           self._get_line(
               title="$OPERATOR",
               text=body.operator,
               definition=self.body_definitions,
            )
        )

        parts.extend(
            self._get_line(
                title="$AUTHORIZED_BY",
                text=body.authorized_by,
                definition=self.body_definitions,
            )
        )

        parts.extend(
            [
                Part(
                    text=None,
                    commands=[
                        RepeatCommand(self.columns, "="),
                        AlignCommand(AlignCommand.Alignment.center),
                        NewLineCommand(),
                    ],
                )
            ]
        )

        if body.discount_description not in ['', None]:
            parts.extend(
                self._get_line(
                    title=None,
                    text="$DISCOUNT_JUSTIFICATION {0}".format(body.discount_description),
                    definition=self.center_definitions,
                )
            )

            parts.extend(
                [
                    Part(
                        text=None,
                        commands=[
                            NewLineCommand(),
                        ]
                    ),
                ]
            )

        parts.extend(
            self._get_line(
                title=None,
                text="$JUSTIFICATION {0}".format(body.justification),
                definition=self.center_definitions,
            )
        )

        return parts

    def _build_footer(
        self,
    ):
        # type: (...) -> List

        parts = [
            Part(
                text=None,
                commands=[
                    NewLineCommand(),
                    NewLineCommand(),
                    NewLineCommand(),
                    RepeatCommand(self.columns, "_"),
                    NewLineCommand(),
                    AlignCommand(AlignCommand.Alignment.center),
                ]
            ),
        ]

        parts.extend(
            self._get_line(
                title=None,
                text="$SIGNATURE",
                definition=self.footer_column_definition,
            )
        )

        return parts

    def _get_title(
        self,
        text,      # type: JustificationHeaderDto
    ):
        # type: (...) -> str

        return format_line(
            title=None,
            text=text,
            columns=self.columns,
            definition=self.header_column_definition,
        )

    def _get_line(
        self,
        title,              # type: str
        text,               # type: str
        definition,         # type: List[ReportColumnDefinition]
    ):
        # type: (...) -> List[TableReport]

        value = remove_accents(
           text=text,
        )

        return format_line(
            title=title,
            text=value,
            columns=self.columns,
            definition=definition,
        )
