# Copyright 2019 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
"""Module containing different output formatters for the bloat script."""

import abc
import enum
from typing import Callable, Collection, Dict, List, Optional, Tuple, Type
from typing import Union

from binary_diff import BinaryDiff, FormattedDiff


class Output(abc.ABC):
    """An Output produces a size report card in a specific format."""
    def __init__(self,
                 title: Optional[str],
                 diffs: Collection[BinaryDiff] = ()):
        self._title = title
        self._diffs = diffs

    @abc.abstractmethod
    def diff(self) -> str:
        """Creates a report card for a size diff between binaries and a base."""

    @abc.abstractmethod
    def absolute(self) -> str:
        """Creates a report card for the absolute size breakdown of binaries."""


class AsciiCharset(enum.Enum):
    """Set of ASCII characters for drawing tables."""
    TL = '+'
    TM = '+'
    TR = '+'
    ML = '+'
    MM = '+'
    MR = '+'
    BL = '+'
    BM = '+'
    BR = '+'
    V = '|'
    H = '-'
    HH = '='


class LineCharset(enum.Enum):
    """Set of line-drawing characters for tables."""
    TL = '┌'
    TM = '┬'
    TR = '┐'
    ML = '├'
    MM = '┼'
    MR = '┤'
    BL = '└'
    BM = '┴'
    BR = '┘'
    V = '│'
    H = '─'
    HH = '═'


def identity(val: str) -> str:
    """Returns a string unmodified."""
    return val


class TableOutput(Output):
    """Tabular output."""

    LABEL_COLUMN = 'Label'

    def __init__(
        self,
        title: Optional[str],
        diffs: Collection[BinaryDiff] = (),
        charset: Union[Type[AsciiCharset], Type[LineCharset]] = AsciiCharset,
        preprocess: Callable[[str], str] = identity,
        # TODO(frolv): Make this a Literal type.
        justify: str = 'rjust'):
        self._cs = charset
        self._preprocess = preprocess
        self._justify = justify

        super().__init__(title, diffs)

    def diff(self) -> str:
        """Build a tabular diff output showing binary size deltas."""

        # Calculate the width of each column in the table.
        max_label = len(self.LABEL_COLUMN)
        column_widths = [len(field) for field in FormattedDiff._fields]

        for diff in self._diffs:
            max_label = max(max_label, len(diff.label))
            for segment in diff.formatted_segments():
                for i, val in enumerate(segment):
                    val = self._preprocess(val)
                    column_widths[i] = max(column_widths[i], len(val))

        separators = self._row_separators([max_label] + column_widths)

        def title_pad(string: str) -> str:
            padding = (len(separators['top']) - len(string)) // 2
            return ' ' * padding + string

        titles = [
            self._center_align(val.capitalize(), column_widths[i])
            for i, val in enumerate(FormattedDiff._fields)
        ]
        column_names = [self._center_align(self.LABEL_COLUMN, max_label)
                        ] + titles

        rows: List[str] = []

        if self._title is not None:
            rows.extend([
                title_pad(self._title),
                title_pad(self._cs.H.value * len(self._title)),
            ])

        rows.extend([
            separators['top'],
            self._table_row(column_names),
            separators['hdg'],
        ])

        for row, diff in enumerate(self._diffs):
            subrows: List[str] = []

            for segment in diff.formatted_segments():
                subrow: List[str] = []
                label = diff.label if not subrows else ''
                subrow.append(getattr(label, self._justify)(max_label, ' '))
                subrow.extend([
                    getattr(self._preprocess(val),
                            self._justify)(column_widths[i], ' ')
                    for i, val in enumerate(segment)
                ])
                subrows.append(self._table_row(subrow))

            rows.append('\n'.join(subrows))
            rows.append(separators['bot' if row == len(self._diffs) -
                                   1 else 'mid'])

        return '\n'.join(rows)

    def absolute(self) -> str:
        return ''

    def _row_separators(self, column_widths: List[int]) -> Dict[str, str]:
        """Returns row separators for a table based on the character set."""

        # Left, middle, and right characters for each of the separator rows.
        top = (self._cs.TL.value, self._cs.TM.value, self._cs.TR.value)
        mid = (self._cs.ML.value, self._cs.MM.value, self._cs.MR.value)
        bot = (self._cs.BL.value, self._cs.BM.value, self._cs.BR.value)

        def sep(chars: Tuple[str, str, str], heading: bool = False) -> str:
            line = self._cs.HH.value if heading else self._cs.H.value
            lines = [line * width for width in column_widths]
            left = f'{chars[0]}{line}'
            mid = f'{line}{chars[1]}{line}'.join(lines)
            right = f'{line}{chars[2]}'
            return f'{left}{mid}{right}'

        return {
            'top': sep(top),
            'hdg': sep(mid, True),
            'mid': sep(mid),
            'bot': sep(bot),
        }

    def _table_row(self, vals: Collection[str]) -> str:
        """Formats a row of the table with the selected character set."""
        vert = self._cs.V.value
        main = f' {vert} '.join(vals)
        return f'{vert} {main} {vert}'

    @staticmethod
    def _center_align(val: str, width: int) -> str:
        """Left and right pads a value with spaces to center within a width."""
        space = width - len(val)
        padding = ' ' * (space // 2)
        extra = ' ' if space % 2 == 1 else ''
        return f'{extra}{padding}{val}{padding}'


class RstOutput(TableOutput):
    """Tabular output in ASCII format, which is also valid RST."""
    def __init__(self, diffs: Collection[BinaryDiff] = ()):
        # Use RST line blocks within table cells to force each value to appear
        # on a new line in the HTML output.
        def add_rst_block(val: str) -> str:
            return f'| {val}'

        super().__init__(None,
                         diffs,
                         AsciiCharset,
                         preprocess=add_rst_block,
                         justify='ljust')
