# -*- coding: utf-8 -*-

# Copyright 2021 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.
"""Functions to create checkboxes for menus and toolbars."""

import sys
from typing import Callable, Iterable, Optional, NamedTuple

from prompt_toolkit.formatted_text.base import OneStyleAndTextTuple
from prompt_toolkit.formatted_text import StyleAndTextTuples

_KEY_SEPARATOR = ' '
_CHECKED_BOX = '[✓]'

if sys.platform in ['win32']:
    _CHECKED_BOX = '[x]'


class ToolbarButton(NamedTuple):
    key: Optional[str] = None
    description: Optional[str] = 'Button'
    mouse_handler: Optional[Callable] = None
    is_checkbox: bool = False
    checked: Optional[Callable] = None


def to_checkbox(
    checked: bool,
    mouse_handler: Optional[Callable] = None,
    end: str = ' ',
    unchecked_style: str = 'class:checkbox',
    checked_style: str = 'class:checkbox-checked',
) -> OneStyleAndTextTuple:
    text = _CHECKED_BOX if checked else '[ ]'
    text += end
    style = checked_style if checked else unchecked_style
    if mouse_handler:
        return (style, text, mouse_handler)
    return (style, text)


def to_checkbox_text(checked: bool, end=' '):
    return to_checkbox(checked, end=end)[1]


def to_setting(
    checked: bool,
    text: str,
    active_style='class:toolbar-setting-active',
    inactive_style='',
    mouse_handler=None,
):
    """Apply a style to text if checked is True."""
    style = active_style if checked else inactive_style
    if mouse_handler:
        return (style, text, mouse_handler)
    return (style, text)


def to_checkbox_with_keybind_indicator(
    checked: bool,
    key: str,
    description: str,
    mouse_handler=None,
    base_style: str = '',
    **checkbox_kwargs,
):
    """Create a clickable keybind indicator with checkbox for toolbars."""
    if mouse_handler:
        return to_keybind_indicator(key,
                                    description,
                                    mouse_handler,
                                    leading_fragments=[
                                        to_checkbox(checked, mouse_handler,
                                                    **checkbox_kwargs)
                                    ],
                                    base_style=base_style)
    return to_keybind_indicator(
        key,
        description,
        leading_fragments=[to_checkbox(checked, **checkbox_kwargs)],
        base_style=base_style)


def to_keybind_indicator(
    key: str,
    description: str,
    mouse_handler: Optional[Callable] = None,
    leading_fragments: Optional[Iterable] = None,
    middle_fragments: Optional[Iterable] = None,
    base_style: str = '',
    key_style: str = 'class:keybind',
    description_style: str = 'class:keyhelp',
):
    """Create a clickable keybind indicator for toolbars."""
    if base_style:
        base_style += ' '

    fragments: StyleAndTextTuples = []
    fragments.append((base_style + 'class:toolbar-button-decoration', ' '))

    def append_fragment_with_base_style(frag_list, fragment) -> None:
        if mouse_handler:
            frag_list.append(
                (base_style + fragment[0], fragment[1], mouse_handler))
        else:
            frag_list.append((base_style + fragment[0], fragment[1]))

    # Add any starting fragments first
    if leading_fragments:
        for fragment in leading_fragments:
            append_fragment_with_base_style(fragments, fragment)

    # Function name
    if mouse_handler:
        fragments.append(
            (base_style + description_style, description, mouse_handler))
    else:
        fragments.append((base_style + description_style, description))

    if middle_fragments:
        for fragment in middle_fragments:
            append_fragment_with_base_style(fragments, fragment)

    # Separator and keybind
    if key:
        if mouse_handler:
            fragments.append((base_style + description_style, _KEY_SEPARATOR,
                              mouse_handler))
            fragments.append((base_style + key_style, key, mouse_handler))
        else:
            fragments.append((base_style + description_style, _KEY_SEPARATOR))
            fragments.append((base_style + key_style, key))

    fragments.append((base_style + 'class:toolbar-button-decoration', ' '))
    return fragments
