"""Results table focused state."""

from __future__ import annotations

from sqlit.core.input_context import InputContext
from sqlit.core.state_base import DisplayBinding, State, resolve_display_key


class ResultsFocusedState(State):
    """Results table has focus."""

    help_category = "Results"
    keymap_context = "results"

    def _setup_actions(self) -> None:
        def has_results(app: InputContext) -> bool:
            return app.has_results

        self.allows("view_cell", has_results, key="v", label="View cell", help="Preview cell (tooltip)")
        self.allows("view_cell_full", has_results, key="V", label="View full", help="View full cell value")
        self.allows("edit_cell", has_results, key="u", label="Update cell", help="Update cell (generate UPDATE)")
        self.allows("delete_row", has_results, key="d", label="Delete row", help="Delete row (generate DELETE)")
        self.allows("results_yank_leader_key", has_results, key="y", label="Copy", help="Copy menu (cell/row/all)")
        self.allows("clear_results", has_results, key="x", label="Clear", help="Clear results")
        self.allows("results_filter", has_results, key="slash", label="Filter", help="Filter rows")
        self.allows("results_cursor_left", has_results)  # vim h
        self.allows("results_cursor_down", has_results)  # vim j
        self.allows("results_cursor_up", has_results)  # vim k
        self.allows("results_cursor_right", has_results)  # vim l
        self.allows("rg_leader_key", has_results)  # vim gg (first step)
        self.allows("rg_first_row", has_results)  # vim gg (second step)
        self.allows("results_cursor_last_row", has_results)  # vim G
        self.allows("results_page_up", has_results)  # vim Ctrl+U
        self.allows("results_page_down", has_results)  # vim Ctrl+D
        self.allows("results_cursor_first_column", has_results)  # vim 0
        self.allows("results_cursor_last_column", has_results)  # vim $
        self.allows("results_column_picker", has_results)  # vim f/F
        self.allows("next_result_section", has_results, label="Next result", help="Next result section")
        self.allows("prev_result_section", has_results, label="Prev result", help="Previous result section")

    def get_display_bindings(self, app: InputContext) -> tuple[list[DisplayBinding], list[DisplayBinding]]:
        # No bindings when there are no results
        if not app.has_results:
            left: list[DisplayBinding] = []
            if self.parent:
                left, _ = self.parent.get_display_bindings(app)
            return left, []

        left: list[DisplayBinding] = []
        seen: set[str] = set()

        is_error = app.last_result_is_error

        if is_error:
            left.append(
                DisplayBinding(
                    key=resolve_display_key("view_cell") or "v",
                    label="View error",
                    action="view_cell",
                )
            )
            left.append(
                DisplayBinding(
                    key=resolve_display_key("results_yank_leader_key") or "y",
                    label="Copy",
                    action="results_yank_leader_key",
                )
            )
        else:
            left.append(
                DisplayBinding(
                    key=resolve_display_key("view_cell") or "v",
                    label="Preview",
                    action="view_cell",
                )
            )
            left.append(
                DisplayBinding(
                    key=resolve_display_key("view_cell_full") or "V",
                    label="View",
                    action="view_cell_full",
                )
            )
            left.append(
                DisplayBinding(
                    key=resolve_display_key("edit_cell") or "u",
                    label="Update",
                    action="edit_cell",
                )
            )
            left.append(
                DisplayBinding(
                    key=resolve_display_key("delete_row") or "d",
                    label="Delete",
                    action="delete_row",
                )
            )
            left.append(
                DisplayBinding(
                    key=resolve_display_key("results_yank_leader_key") or "y",
                    label="Copy",
                    action="results_yank_leader_key",
                )
            )
        left.append(
            DisplayBinding(
                key=resolve_display_key("clear_results") or "x",
                label="Clear",
                action="clear_results",
            )
        )
        left.append(
            DisplayBinding(
                key=resolve_display_key("results_filter") or "/",
                label="Filter",
                action="results_filter",
            )
        )
        if app.stacked_result_count > 1:
            left.append(
                DisplayBinding(
                    key=resolve_display_key("next_result_section") or "tab",
                    label="Next result",
                    action="next_result_section",
                )
            )
            left.append(
                DisplayBinding(
                    key=resolve_display_key("prev_result_section") or "shift+tab",
                    label="Prev result",
                    action="prev_result_section",
                )
            )

        seen.update(
            [
                "view_cell",
                "view_cell_full",
                "delete_row",
                "results_yank_leader_key",
                "clear_results",
                "results_filter",
                "next_result_section",
                "prev_result_section",
            ]
        )

        if self.parent:
            parent_left, _ = self.parent.get_display_bindings(app)
            for binding in parent_left:
                if binding.action not in seen:
                    left.append(binding)
                    seen.add(binding.action)

        return left, []

    def is_active(self, app: InputContext) -> bool:
        return app.focus == "results"
