# 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.
"""pw_console preferences"""

import os
from pathlib import Path
from typing import Dict, Callable, List, Union

from prompt_toolkit.key_binding import KeyBindings
import yaml

from pw_console.style import get_theme_colors
from pw_console.key_bindings import DEFAULT_KEY_BINDINGS
from pw_console.yaml_config_loader_mixin import YamlConfigLoaderMixin

_DEFAULT_REPL_HISTORY: Path = Path.home() / '.pw_console_history'
_DEFAULT_SEARCH_HISTORY: Path = Path.home() / '.pw_console_search'

_DEFAULT_CONFIG = {
    # History files
    'repl_history': _DEFAULT_REPL_HISTORY,
    'search_history': _DEFAULT_SEARCH_HISTORY,
    # Appearance
    'ui_theme': 'dark',
    'code_theme': 'pigweed-code',
    'swap_light_and_dark': False,
    'spaces_between_columns': 2,
    'column_order_omit_unspecified_columns': False,
    'column_order': [],
    'column_colors': {},
    'show_python_file': False,
    'show_python_logger': False,
    'show_source_file': False,
    'hide_date_from_log_time': False,
    # Window arrangement
    'windows': {},
    'window_column_split_method': 'vertical',
    'command_runner': {
        'width': 80,
        'height': 10,
        'position': {
            'top': 3
        },
    },
    'key_bindings': DEFAULT_KEY_BINDINGS,
}

_DEFAULT_PROJECT_FILE = Path('$PW_PROJECT_ROOT/.pw_console.yaml')
_DEFAULT_PROJECT_USER_FILE = Path('$PW_PROJECT_ROOT/.pw_console.user.yaml')
_DEFAULT_USER_FILE = Path('$HOME/.pw_console.yaml')


class UnknownWindowTitle(Exception):
    """Exception for window titles not present in the window manager layout."""


class EmptyWindowList(Exception):
    """Exception for window lists with no content."""


def error_unknown_window(window_title: str,
                         existing_pane_titles: List[str]) -> None:
    """Raise an error when the window config has an unknown title.

    If a window title does not already exist on startup it must have a loggers:
    or duplicate_of: option set."""

    pane_title_text = '  ' + '\n  '.join(existing_pane_titles)
    existing_pane_title_example = 'Window Title'
    if existing_pane_titles:
        existing_pane_title_example = existing_pane_titles[0]
    raise UnknownWindowTitle(
        f'\n\n"{window_title}" does not exist.\n'
        'Existing windows include:\n'
        f'{pane_title_text}\n'
        'If this window should be a duplicate of one of the above,\n'
        f'add "duplicate_of: {existing_pane_title_example}" to your config.\n'
        'If this is a brand new window, include a "loggers:" section.\n'
        'See also: '
        'https://pigweed.dev/pw_console/docs/user_guide.html#example-config')


def error_empty_window_list(window_list_title: str, ) -> None:
    """Raise an error if a window list is empty."""

    raise EmptyWindowList(
        f'\n\nError: The window layout heading "{window_list_title}" contains '
        'no windows.\n'
        'See also: '
        'https://pigweed.dev/pw_console/docs/user_guide.html#example-config')


class ConsolePrefs(YamlConfigLoaderMixin):
    """Pigweed Console preferences storage class."""

    # pylint: disable=too-many-public-methods

    def __init__(
        self,
        project_file: Union[Path, bool] = _DEFAULT_PROJECT_FILE,
        project_user_file: Union[Path, bool] = _DEFAULT_PROJECT_USER_FILE,
        user_file: Union[Path, bool] = _DEFAULT_USER_FILE,
    ) -> None:
        self.config_init(
            config_section_title='pw_console',
            project_file=project_file,
            project_user_file=project_user_file,
            user_file=user_file,
            default_config=_DEFAULT_CONFIG,
            environment_var='PW_CONSOLE_CONFIG_FILE',
        )

        self.registered_commands = DEFAULT_KEY_BINDINGS
        self.registered_commands.update(self.user_key_bindings)

    @property
    def ui_theme(self) -> str:
        return self._config.get('ui_theme', '')

    def set_ui_theme(self, theme_name: str):
        self._config['ui_theme'] = theme_name

    @property
    def theme_colors(self):
        return get_theme_colors(self.ui_theme)

    @property
    def code_theme(self) -> str:
        return self._config.get('code_theme', '')

    def set_code_theme(self, theme_name: str):
        self._config['code_theme'] = theme_name

    @property
    def swap_light_and_dark(self) -> bool:
        return self._config.get('swap_light_and_dark', False)

    @property
    def repl_history(self) -> Path:
        history = Path(self._config['repl_history'])
        history = Path(os.path.expandvars(str(history.expanduser())))
        return history

    @property
    def search_history(self) -> Path:
        history = Path(self._config['search_history'])
        history = Path(os.path.expandvars(str(history.expanduser())))
        return history

    @property
    def spaces_between_columns(self) -> int:
        spaces = self._config.get('spaces_between_columns', 2)
        assert isinstance(spaces, int) and spaces > 0
        return spaces

    @property
    def omit_unspecified_columns(self) -> bool:
        return self._config.get('column_order_omit_unspecified_columns', False)

    @property
    def hide_date_from_log_time(self) -> bool:
        return self._config.get('hide_date_from_log_time', False)

    @property
    def show_python_file(self) -> bool:
        return self._config.get('show_python_file', False)

    @property
    def show_source_file(self) -> bool:
        return self._config.get('show_source_file', False)

    @property
    def show_python_logger(self) -> bool:
        return self._config.get('show_python_logger', False)

    def toggle_bool_option(self, name: str):
        existing_setting = self._config[name]
        assert isinstance(existing_setting, bool)
        self._config[name] = not existing_setting

    @property
    def column_order(self) -> list:
        return self._config.get('column_order', [])

    def column_style(self,
                     column_name: str,
                     column_value: str,
                     default='') -> str:
        column_colors = self._config.get('column_colors', {})
        column_style = default

        if column_name in column_colors:
            # If key exists but doesn't have any values.
            if not column_colors[column_name]:
                return default
            # Check for user supplied default.
            column_style = column_colors[column_name].get('default', default)
            # Check for value specific color, otherwise use the default.
            column_style = column_colors[column_name].get(
                column_value, column_style)
        return column_style

    @property
    def window_column_split_method(self) -> str:
        return self._config.get('window_column_split_method', 'vertical')

    @property
    def windows(self) -> dict:
        return self._config.get('windows', {})

    @property
    def window_column_modes(self) -> list:
        return list(column_type for column_type in self.windows.keys())

    @property
    def command_runner_position(self) -> Dict[str, int]:
        position = self._config.get('command_runner',
                                    {}).get('position', {'top': 3})
        return {
            key: value
            for key, value in position.items()
            if key in ['top', 'bottom', 'left', 'right']
        }

    @property
    def command_runner_width(self) -> int:
        return self._config.get('command_runner', {}).get('width', 80)

    @property
    def command_runner_height(self) -> int:
        return self._config.get('command_runner', {}).get('height', 10)

    @property
    def user_key_bindings(self) -> Dict[str, List[str]]:
        return self._config.get('key_bindings', {})

    def current_config_as_yaml(self) -> str:
        yaml_options = dict(sort_keys=True,
                            default_style='',
                            default_flow_style=False)

        title = {'config_title': 'pw_console'}
        text = '\n'
        text += yaml.safe_dump(title, **yaml_options)  # type: ignore

        keys = {'key_bindings': self.registered_commands}
        text += '\n'
        text += yaml.safe_dump(keys, **yaml_options)  # type: ignore

        return text

    @property
    def unique_window_titles(self) -> set:
        titles = []
        for window_list_title, column in self.windows.items():
            if not column:
                error_empty_window_list(window_list_title)

            for window_key_title, window_dict in column.items():
                window_options = window_dict if window_dict else {}
                # Use 'duplicate_of: Title' if it exists, otherwise use the key.
                titles.append(
                    window_options.get('duplicate_of', window_key_title))
        return set(titles)

    def get_function_keys(self, name: str) -> List:
        """Return the keys for the named function."""
        try:
            return self.registered_commands[name]
        except KeyError as error:
            raise KeyError('Unbound key function: {}'.format(name)) from error

    def register_named_key_function(self, name: str,
                                    default_bindings: List[str]) -> None:
        self.registered_commands[name] = default_bindings

    def register_keybinding(self, name: str, key_bindings: KeyBindings,
                            **kwargs) -> Callable:
        """Apply registered keys for the given named function."""
        def decorator(handler: Callable) -> Callable:
            "`handler` is a callable or Binding."
            for keys in self.get_function_keys(name):
                key_bindings.add(*keys.split(' '), **kwargs)(handler)
            return handler

        return decorator
