# 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.
"""Window pane base class."""

import asyncio
import logging
from threading import Thread
import time
from typing import Callable, Optional

from pw_console.get_pw_console_app import get_pw_console_app


class PluginMixin:
    """Handles background task management in a Pigweed Console plugin.

    Pigweed Console plugins can inherit from this class if they require running
    tasks in the background. This is important as any plugin code not in its
    own dedicated thread can potentially block the user interface

    Example usage: ::

        import logging
        from pw_console.plugin_mixin import PluginMixin
        from pw_console.widgets import WindowPaneToolbar

        class AwesomeToolbar(WindowPaneToolbar, PluginMixin):
            TOOLBAR_HEIGHT = 1

            def __init__(self, *args, **kwargs):
                # Call parent class WindowPaneToolbar.__init__
                super().__init__(*args, **kwargs)

                # Set PluginMixin to execute
                # self._awesome_background_task every 10 seconds.
                self.plugin_init(
                    plugin_callback=self._awesome_background_task,
                    plugin_callback_frequency=10.0,
                    plugin_logger_name='awesome_toolbar_plugin')

            # This function will be run in a separate thread every 10 seconds.
            def _awesome_background_task(self) -> bool:
                time.sleep(1)  # Do real work here.

                if self.new_data_processed:
                    # If new data was processed, and the user interface
                    # should be updated return True.

                    # Log using self.plugin_logger for debugging.
                    self.plugin_logger.debug('New data processed')

                    # Return True to signal a UI redraw.
                    return True

                # Returning False means no updates needed.
                return False

    Attributes:
        plugin_callback: Callable that is run in a background thread.
        plugin_callback_frequency: Number of seconds to wait between
            executing plugin_callback.
        plugin_logger: logging instance for this plugin. Useful for debugging
            code running in a separate thread.
        plugin_callback_future: `Future`_ object for the plugin background task.
        plugin_event_loop: asyncio event loop running in the background thread.
        plugin_enable_background_task: If True, keep periodically running
            plugin_callback at the desired frequency. If False the background
            task will stop.

    .. _Future: https://docs.python.org/3/library/asyncio-future.html
    """
    def plugin_init(
        self,
        plugin_callback: Optional[Callable[..., bool]] = None,
        plugin_callback_frequency: float = 30.0,
        plugin_logger_name: Optional[str] = 'pw_console_plugins',
    ) -> None:
        """Call this on __init__() to set plugin background task variables.

        Args:
            plugin_callback: Callable to run in a separate thread from the
                Pigweed Console UI. This function should return True if the UI
                should be redrawn after execution.
            plugin_callback_frequency: Number of seconds to wait between
                executing plugin_callback.
            plugin_logger_name: Unique name for this plugin's Python
                logger. Useful for debugging code running in a separate thread.
        """
        self.plugin_callback = plugin_callback
        self.plugin_callback_frequency = plugin_callback_frequency
        self.plugin_logger = logging.getLogger(plugin_logger_name)

        self.plugin_callback_future = None

        # Event loop for executing plugin code.
        self.plugin_event_loop = asyncio.new_event_loop()
        self.plugin_enable_background_task = True

    def plugin_start(self):
        """Function used to start this plugin's background thead and task."""

        # Create an entry point for the plugin thread.
        def _plugin_thread_entry():
            # Disable log propagation
            self.plugin_logger.propagate = False
            asyncio.set_event_loop(self.plugin_event_loop)
            self.plugin_event_loop.run_forever()

        # Create a thread for running user code so the UI isn't blocked.
        thread = Thread(target=_plugin_thread_entry, args=(), daemon=True)
        thread.start()

        self.plugin_logger.debug('Starting plugin: %s', self)
        if self.plugin_callback is None:
            return

        self.plugin_enable_background_task = True
        self.plugin_callback_future = asyncio.run_coroutine_threadsafe(
            # This function will be executed in a separate thread.
            self._plugin_periodically_run_callback(),
            # Using this asyncio event loop.
            self.plugin_event_loop)  # type: ignore

    def plugin_stop(self):
        self.plugin_enable_background_task = False

    async def _plugin_periodically_run_callback(self) -> None:
        while self.plugin_enable_background_task:
            start_time = time.time()
            # Run the callback and redraw the UI if return value is True
            if self.plugin_callback and self.plugin_callback():
                get_pw_console_app().redraw_ui()
            run_time = time.time() - start_time
            await asyncio.sleep(self.plugin_callback_frequency - run_time)
