# Source code for tabletree.src.api.column

    # sphinx bug workaround for python 3.11. see grm:86663
    from __future__ import annotations

    from abc import ABC, abstractmethod
    from typing import Any, Literal, Self, cast

    from ..lib.column import (
        ColumnBuilder,
        ColumnBuilderBase,
        ColumnFilterType,
        ColumnImageType,
        ColumnStyleBuilder,
        ColumnSummaryType,
        ColumnType,
        ColumnUnitfulType,
        RowHeaderColumnBuilder,
        SummaryFormulaBuilder,
    )
    from ..lib.i18n import I18nResourcesWriter, I18nWord

    ColumnFlag = Literal[
        "is_resizable",
        "is_hidden",
        "is_statistical",
        "is_editable",
        "is_display_large",
    ]

    class IColumn(ABC):
        @abstractmethod
        def __init__(self): ...

        @abstractmethod
        def set_max_width(self, width: int | I18nWord) -> Self:
            """Set the maximum width of the column.

            Args:
                width:
                    The maximum width of the column.
            """
            ...

        @abstractmethod
        def set_min_width(self, width: int | I18nWord) -> Self:
            """Set the minimum width of the column.

            Args:
                width:
                    The minimum width of the column.
            """
            ...

        @abstractmethod
        def set_flag(self, flag: ColumnFlag, state: bool) -> Self:
            """Change a flag state of the column.

            Args:
                flag:
                    'is_resizable' (default: true):
                        If true, a user can change the column width.
                    'is_hidden' (default: false):
                        If true, the column is not shown in the table by default.
                    'is_statistical' (default: false):
                        If true, the numbers of each property values
                        are shown on the status bar.
                    'is_editable' (default: false):
                        If true, a user can edit the values of the property.
                    'is_display_large' (default: false):
                        If true, the property is shown in an exclusive tab
                        in the property list.
                state:
                    The new state of the flag.
            """
            ...

        @abstractmethod
        def set_property_for_sort(self, key: str) -> Self:
            """Set a key used to sort the items.

            Args:
                key:
                    The property key used to sort the items.
            """
            ...

        @abstractmethod
        def _get_data(self):
            """Obtain the data."""
            ...

    class ColumnBase(IColumn):
        _builder: ColumnBuilderBase
        _style_builder: ColumnStyleBuilder
        _summary_formula_builder: SummaryFormulaBuilder | None

        def __init__(self):
            self._style_builder = ColumnStyleBuilder()
            self._summary_formula_builder = None

        def __post_init__(self):
            self.set_flag("is_resizable", True).set_flag("is_hidden", False)

        def set_max_width(self, width: int | I18nWord) -> Self:
            if isinstance(width, int):
                self._style_builder.set_max_width(width)
            else:
                self._style_builder.set_max_width_i18n(width)
                I18nResourcesWriter.get_instance().add_word(width)
            return self

        def set_min_width(self, width: int | I18nWord) -> Self:
            if isinstance(width, int):
                self._style_builder.set_min_width(width)
            else:
                self._style_builder.set_min_width_i18n(width)
                I18nResourcesWriter.get_instance().add_word(width)
            return self

        def set_flag(self, flag: ColumnFlag, state: bool) -> Self:
            if flag == "is_resizable":
                self._builder.set_flag("isResizable", state)
            elif flag == "is_hidden":
                self._builder.set_flag("isDisplayDefault", not state)
            elif flag == "is_statistical":
                self._builder.set_flag("isStatistical", state)
            elif flag == "is_editable":
                self._builder.set_flag("isEditable", state)
            elif flag == "is_display_large":
                self._builder.set_flag("isLargeDisplay", state)
            return self

        def set_property_for_sort(self, key: str) -> Self:
            self._builder.set_sort_key(key)
            return self

        def _get_data(self) -> ColumnBuilderBase:
            self._builder.set_style(self._style_builder)

            return self._builder

    class Column(ColumnBase):
        _builder: ColumnBuilder

        def __init__(
            self,
            name: str | I18nWord,
            property_key: str,
            property_type: ColumnType,
            property_subtype: ColumnImageType | ColumnUnitfulType | None = None,
            summary_options: dict[str, Any] | None = None,
        ):
            """Create a column for a property.

            Args:
                name:
                    The name of the column.
                property_key:
                    The property to be shown in the column.
                property_type:
                    The type of the property.
                property_subtype:
                    The image format (ColumnImageType)
                    for a column with 'image' property_type.

                    The length unit (ColumnUnitfulType)
                    for a column with 'unitful' property_type.
                summary_options:
                    The summary options
                    for a column with 'summary' property_type.
            """
            super().__init__()

            self._builder = ColumnBuilder(property_key, property_type)
            if isinstance(name, str):
                self._builder.set_name(name)
            else:
                self._builder.set_name_i18n(name)
                I18nResourcesWriter.get_instance().add_word(name)
            if property_type == "image":
                if property_subtype is None:
                    raise ValueError(
                        "property_subtype cannot be None "
                        "when property_type is image"
                    )
                self._builder.set_image_type(
                    cast(ColumnImageType, property_subtype)
                )
            if property_type == "summary":
                if summary_options is None:
                    raise ValueError(
                        "summary_options of Column cannot be None "
                        "when property_type is summary"
                    )
                self._builder.set_summary_formula(
                    SummaryFormulaBuilder(
                        cast(ColumnSummaryType, summary_options["type"]),
                        summary_options["options"],
                    )
                )
            if property_type == "unitful":
                if property_subtype is None:
                    raise ValueError(
                        "property_subtype cannot be None "
                        f"when property_type is {property_type}"
                    )
                self._builder.set_unit(cast(ColumnUnitfulType, property_subtype))
            self.set_filter_type("free")
            super().__post_init__()

        def set_filter_type(self, filter_type: ColumnFilterType) -> Self:
            """Set filter type to the column.

            Args:
                filter_type:
                    'none':
                        No filter can be set for the column.
                    'range':
                        The table items can be filtered
                        with maximum and minimum values of the property.
                    'select':
                        The table items can be filtered
                        with a set of values of the property.
                    'existence':
                        The table items can be filtered by
                        whether they have non-nullish values
                        as the property or not.
                    'free':
                        The table items can be filtered
                        with a text or a regular expression.
            """
            self._builder.set_filter_type(filter_type)
            return self

        def add_choice(self, choice: str | I18nWord) -> Self:
            """Add an option for editing and setting a filter to the property.

            Args:
                choice:
                    The value to be added as an option.
            """
            if isinstance(choice, str):
                self._builder.add_option(choice)
            else:
                self._builder.add_option_i18n(choice)
                I18nResourcesWriter.get_instance().add_word(choice)
            return self

        def _get_data(self) -> ColumnBuilder:
            super()._get_data()
            return self._builder

    class NameColumn(ColumnBase):
        _builder: RowHeaderColumnBuilder

        def __init__(self):
            """Create a style for a name column of a table."""
            super().__init__()
            self._builder = RowHeaderColumnBuilder()
            super().__post_init__()

        def _get_data(self) -> RowHeaderColumnBuilder:
            super()._get_data()
            return self._builder