# Copyright 2020 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.
"""Run an interruptable, cancellable function after debouncing run requests"""

import enum
import logging
import threading
from abc import ABC, abstractmethod

_LOG = logging.getLogger(__name__)


class DebouncedFunction(ABC):
    """Function to be run by Debouncer"""
    @abstractmethod
    def run(self):
        """Run the function"""

    @abstractmethod
    def cancel(self):
        """Cancel an in-progress run of the function.
        Must be called from different thread than run().
        Returns true if run was successfully cancelled, false otherwise"""

    @abstractmethod
    def on_complete(self, cancelled=False):
        """Called after run() finishes. If true, cancelled indicates
        cancel() was invoked during the last run()"""

    # Note: The debounce uses threads. Since there is no way to guarantee which
    # thread recieves a KeyboardInterrupt, it is necessary catch this event
    # in all debouncer threads and forward it to the user.
    @abstractmethod
    def on_keyboard_interrupt(self):
        """Called when keyboard interrupt is delivered to a debouncer thread"""


class State(enum.Enum):
    IDLE = 1  # ------- Transistions to: DEBOUNCING
    DEBOUNCING = 2  # - Transistions to: RUNNING
    RUNNING = 3  # ---- Transistions to: INTERRUPTED or COOLDOWN
    INTERRUPTED = 4  #- Transistions to: RERUN
    COOLDOWN = 5  #---- Transistions to: IDLE
    RERUN = 6  #------- Transistions to: IDLE (but triggers a press)


class Debouncer:
    """Run an interruptable, cancellable function with debouncing"""
    def __init__(self, function):
        super().__init__()
        self.function = function

        self.state = State.IDLE

        self.debounce_seconds = 1
        self.debounce_timer = None

        self.cooldown_seconds = 1
        self.cooldown_timer = None

        self.rerun_event_description = None

        self.lock = threading.Lock()

    def press(self, event_description=None):
        """Try to run the function for the class. If the function is recently
        started, this may push out the deadline for actually starting. If the
        function is already running, will interrupt the function"""
        with self.lock:
            self._press_unlocked(event_description)

    def _press_unlocked(self, event_description=None):
        _LOG.debug('Press - state = %s', str(self.state))
        if self.state == State.IDLE:
            if event_description:
                _LOG.info(event_description)
            self._start_debounce_timer()
            self._transition(State.DEBOUNCING)

        elif self.state == State.DEBOUNCING:
            self._start_debounce_timer()

        elif self.state == State.RUNNING:
            # When the function is already running but we get an incoming
            # event, go into the INTERRUPTED state to signal that we should
            # re-try running afterwards.

            # Push an empty line to flush ongoing I/O in subprocess.
            print()

            # Surround the error message with newlines to make it stand out.
            print()
            _LOG.error('Event while running: %s', event_description)
            print()

            self.function.cancel()
            self._transition(State.INTERRUPTED)
            self.rerun_event_description = event_description

        elif self.state == State.INTERRUPTED:
            # Function is running but was already interrupted. Do nothing.
            _LOG.debug('Ignoring press - interrupted')

        elif self.state == State.COOLDOWN:
            # Function just finished and we are cooling down; so trigger rerun.
            _LOG.debug('Got event in cooldown; scheduling rerun')
            self._transition(State.RERUN)
            self.rerun_event_description = event_description

    def _transition(self, new_state):
        _LOG.debug('State: %s -> %s', str(self.state), str(new_state))
        self.state = new_state

    def _start_debounce_timer(self):
        assert self.lock.locked()
        if self.state == State.DEBOUNCING:
            self.debounce_timer.cancel()
        self.debounce_timer = threading.Timer(self.debounce_seconds,
                                              self._run_function)
        self.debounce_timer.start()

    # Called from debounce_timer thread.
    def _run_function(self):
        try:
            with self.lock:
                assert self.state == State.DEBOUNCING
                self.debounce_timer = None
                self._transition(State.RUNNING)

            # Must run the function without the lock held so further press()
            # calls don't deadlock.
            _LOG.debug('Running debounced function')
            self.function.run()

            _LOG.debug('Finished running debounced function')
            with self.lock:
                if self.state == State.RUNNING:
                    self.function.on_complete(cancelled=False)
                    self._transition(State.COOLDOWN)
                elif self.state == State.INTERRUPTED:
                    self.function.on_complete(cancelled=True)
                    self._transition(State.RERUN)
                self._start_cooldown_timer()
        # Ctrl-C on Unix generates KeyboardInterrupt
        # Ctrl-Z on Windows generates EOFError
        except (KeyboardInterrupt, EOFError):
            self.function.on_keyboard_interrupt()

    def _start_cooldown_timer(self):
        assert self.lock.locked()
        self.cooldown_timer = threading.Timer(self.cooldown_seconds,
                                              self._exit_cooldown)
        self.cooldown_timer.start()

    # Called from cooldown_timer thread.
    def _exit_cooldown(self):
        try:
            with self.lock:
                self.cooldown_timer = None
                rerun = (self.state == State.RERUN)
                self._transition(State.IDLE)

                # If we were in the RERUN state, then re-trigger the event.
                if rerun:
                    self._press_unlocked('Rerunning: %s' %
                                         self.rerun_event_description)

        # Ctrl-C on Unix generates KeyboardInterrupt
        # Ctrl-Z on Windows generates EOFError
        except (KeyboardInterrupt, EOFError):
            self.function.on_keyboard_interrupt()
