# Copyright 2022 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.
"""Dialog box for log selection functions."""

from __future__ import annotations
import functools
from typing import TYPE_CHECKING

from prompt_toolkit.filters import Condition
from prompt_toolkit.layout import (
    ConditionalContainer,
    FormattedTextControl,
    Window,
    WindowAlign,
)

import pw_console.style
import pw_console.widgets.checkbox
import pw_console.widgets.border
import pw_console.widgets.mouse_handlers

if TYPE_CHECKING:
    from pw_console.log_pane import LogPane


class LogPaneSelectionDialog(ConditionalContainer):
    """Dialog box for showing log selection functions.

    Displays number of lines selected, buttons for copying to the clipboar or
    saving to a file, and buttons to select all or cancel (clear) the
    selection."""
    # Height of the dialog box contens in lines of text.
    DIALOG_HEIGHT = 3

    def __init__(self, log_pane: 'LogPane'):
        self.log_pane = log_pane
        self.log_view = log_pane.log_view

        self._markdown_flag: bool = False
        self._table_flag: bool = True

        selection_bar_control = FormattedTextControl(self.get_fragments)
        selection_bar_window = Window(content=selection_bar_control,
                                      height=1,
                                      align=WindowAlign.LEFT,
                                      dont_extend_width=False,
                                      style='class:selection-dialog')

        super().__init__(
            pw_console.widgets.border.create_border(
                selection_bar_window,
                (LogPaneSelectionDialog.DIALOG_HEIGHT - 1),
                border_style='class:selection-dialog-border',
                base_style='class:selection-dialog-default-fg',
                top=False,
                right=False,
            ),
            filter=Condition(lambda: self.log_view.visual_select_mode))

    def focus_log_pane(self):
        self.log_pane.application.focus_on_container(self.log_pane)

    def _toggle_markdown_flag(self) -> None:
        self._markdown_flag = not self._markdown_flag

    def _toggle_table_flag(self) -> None:
        self._table_flag = not self._table_flag

    def _select_all(self) -> None:
        self.log_view.visual_select_all()

    def _select_none(self) -> None:
        self.log_view.clear_visual_selection()

    def _copy_selection(self) -> None:
        if self.log_view.export_logs(
                to_clipboard=True,
                use_table_formatting=self._table_flag,
                selected_lines_only=True,
                add_markdown_fence=self._markdown_flag,
        ):
            self._select_none()

    def _saveas_file(self) -> None:
        self.log_pane.start_saveas(table_format=self._table_flag,
                                   selected_lines_only=True)

    def get_fragments(self):
        """Return formatted text tuples for both rows of the selection
        dialog."""

        focus = functools.partial(pw_console.widgets.mouse_handlers.on_click,
                                  self.focus_log_pane)

        one_space = ('', ' ', focus)
        two_spaces = ('', '  ', focus)
        select_all = functools.partial(
            pw_console.widgets.mouse_handlers.on_click, self._select_all)
        select_none = functools.partial(
            pw_console.widgets.mouse_handlers.on_click, self._select_none)

        copy_selection = functools.partial(
            pw_console.widgets.mouse_handlers.on_click, self._copy_selection)
        saveas_file = functools.partial(
            pw_console.widgets.mouse_handlers.on_click, self._saveas_file)
        toggle_markdown = functools.partial(
            pw_console.widgets.mouse_handlers.on_click,
            self._toggle_markdown_flag)
        toggle_table = functools.partial(
            pw_console.widgets.mouse_handlers.on_click,
            self._toggle_table_flag)

        button_style = 'class:toolbar-button-inactive'

        # First row of text
        fragments = [('class:selection-dialog-title', ' {} Selected '.format(
            self.log_view.visual_selected_log_count()), focus), one_space,
                     ('class:selection-dialog-default-fg', 'Format: ', focus)]

        # Table and Markdown options
        fragments.extend(
            pw_console.widgets.checkbox.to_checkbox_with_keybind_indicator(
                self._table_flag,
                key='',
                description='Table',
                mouse_handler=toggle_table,
                base_style='class:selection-dialog-default-bg'))

        fragments.extend(
            pw_console.widgets.checkbox.to_checkbox_with_keybind_indicator(
                self._markdown_flag,
                key='',
                description='Markdown',
                mouse_handler=toggle_markdown,
                base_style='class:selection-dialog-default-bg'))

        # Line break
        fragments.append(('', '\n'))

        # Second row of text
        fragments.append(one_space)

        fragments.extend(
            pw_console.widgets.checkbox.to_keybind_indicator(
                key='Ctrl-c',
                description='Cancel',
                mouse_handler=select_none,
                base_style=button_style,
            ))
        fragments.append(two_spaces)

        fragments.extend(
            pw_console.widgets.checkbox.to_keybind_indicator(
                key='Ctrl-a',
                description='Select All',
                mouse_handler=select_all,
                base_style=button_style,
            ))
        fragments.append(two_spaces)

        fragments.append(one_space)
        fragments.extend(
            pw_console.widgets.checkbox.to_keybind_indicator(
                key='',
                description='Save as File',
                mouse_handler=saveas_file,
                base_style=button_style,
            ))
        fragments.append(two_spaces)

        fragments.extend(
            pw_console.widgets.checkbox.to_keybind_indicator(
                key='',
                description='Copy',
                mouse_handler=copy_selection,
                base_style=button_style,
            ))
        fragments.append(one_space)

        return fragments
