# Copyright 2016 Google Inc.
#
# 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
#
#     http://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.

from concurrent.futures import ThreadPoolExecutor
import queue
import re
import threading
import time
import traceback


class EventDispatcherError(Exception):
  pass


class IllegalStateError(EventDispatcherError):
  """Raise when user tries to put event_dispatcher into an illegal state.
  """


class DuplicateError(EventDispatcherError):
  """Raise when a duplicate is being created and it shouldn't.
  """


class EventDispatcher:
  """Class managing events for an sl4a connection.
  """

  DEFAULT_TIMEOUT = 60

  def __init__(self, sl4a):
    self._sl4a = sl4a
    self.started = False
    self.executor = None
    self.poller = None
    self.event_dict = {}
    self.handlers = {}
    self.lock = threading.RLock()

  def poll_events(self):
    """Continuously polls all types of events from sl4a.

    Events are sorted by name and store in separate queues.
    If there are registered handlers, the handlers will be called with
    corresponding event immediately upon event discovery, and the event
    won't be stored. If exceptions occur, stop the dispatcher and return
    """
    while self.started:
      event_obj = None
      event_name = None
      try:
        event_obj = self._sl4a.eventWait(50000)
      except:
        if self.started:
          print("Exception happened during polling.")
          print(traceback.format_exc())
          raise
      if not event_obj:
        continue
      elif 'name' not in event_obj:
        print("Received Malformed event {}".format(event_obj))
        continue
      else:
        event_name = event_obj['name']
      # if handler registered, process event
      if event_name in self.handlers:
        self.handle_subscribed_event(event_obj, event_name)
      if event_name == "EventDispatcherShutdown":
        self._sl4a.closeSl4aSession()
        break
      else:
        self.lock.acquire()
        if event_name in self.event_dict:  # otherwise, cache event
          self.event_dict[event_name].put(event_obj)
        else:
          q = queue.Queue()
          q.put(event_obj)
          self.event_dict[event_name] = q
        self.lock.release()

  def register_handler(self, handler, event_name, args):
    """Registers an event handler.

    One type of event can only have one event handler associated with it.

    Args:
      handler: The event handler function to be registered.
      event_name: Name of the event the handler is for.
      args: User arguments to be passed to the handler when it's called.

    Raises:
      IllegalStateError: Raised if attempts to register a handler after
        the dispatcher starts running.
      DuplicateError: Raised if attempts to register more than one
        handler for one type of event.
    """
    if self.started:
      raise IllegalStateError(("Can't register service after polling is"
                   " started"))
    self.lock.acquire()
    try:
      if event_name in self.handlers:
        raise DuplicateError(
          'A handler for {} already exists'.format(event_name))
      self.handlers[event_name] = (handler, args)
    finally:
      self.lock.release()

  def start(self):
    """Starts the event dispatcher.

    Initiates executor and start polling events.

    Raises:
      IllegalStateError: Can't start a dispatcher again when it's already
        running.
    """
    if not self.started:
      self.started = True
      self.executor = ThreadPoolExecutor(max_workers=32)
      self.poller = self.executor.submit(self.poll_events)
    else:
      raise IllegalStateError("Dispatcher is already started.")

  def clean_up(self):
    """Clean up and release resources after the event dispatcher polling
    loop has been broken.

    The following things happen:
    1. Clear all events and flags.
    2. Close the sl4a client the event_dispatcher object holds.
    3. Shut down executor without waiting.
    """
    if not self.started:
      return
    self.started = False
    self.clear_all_events()
    # At this point, the sl4a apk is destroyed and nothing is listening on
    # the socket. Avoid sending any sl4a commands; just clean up the socket
    # and return.
    self._sl4a.disconnect()
    self.poller.set_result("Done")
    # The polling thread is guaranteed to finish after a max of 60 seconds,
    # so we don't wait here.
    self.executor.shutdown(wait=False)

  def pop_event(self, event_name, timeout=DEFAULT_TIMEOUT):
    """Pop an event from its queue.

    Return and remove the oldest entry of an event.
    Block until an event of specified name is available or
    times out if timeout is set.

    Args:
      event_name: Name of the event to be popped.
      timeout: Number of seconds to wait when event is not present.
        Never times out if None.

    Returns:
      The oldest entry of the specified event. None if timed out.

    Raises:
      IllegalStateError: Raised if pop is called before the dispatcher
        starts polling.
    """
    if not self.started:
      raise IllegalStateError(
        "Dispatcher needs to be started before popping.")

    e_queue = self.get_event_q(event_name)

    if not e_queue:
      raise TypeError(
        "Failed to get an event queue for {}".format(event_name))

    try:
      # Block for timeout
      if timeout:
        return e_queue.get(True, timeout)
      # Non-blocking poll for event
      elif timeout == 0:
        return e_queue.get(False)
      else:
        # Block forever on event wait
        return e_queue.get(True)
    except queue.Empty:
      raise queue.Empty('Timeout after {}s waiting for event: {}'.format(
        timeout, event_name))

  def wait_for_event(self,
             event_name,
             predicate,
             timeout=DEFAULT_TIMEOUT,
             *args,
             **kwargs):
    """Wait for an event that satisfies a predicate to appear.

    Continuously pop events of a particular name and check against the
    predicate until an event that satisfies the predicate is popped or
    timed out. Note this will remove all the events of the same name that
    do not satisfy the predicate in the process.

    Args:
      event_name: Name of the event to be popped.
      predicate: A function that takes an event and returns True if the
        predicate is satisfied, False otherwise.
      timeout: Number of seconds to wait.
      *args: Optional positional args passed to predicate().
      **kwargs: Optional keyword args passed to predicate().

    Returns:
      The event that satisfies the predicate.

    Raises:
      queue.Empty: Raised if no event that satisfies the predicate was
        found before time out.
    """
    deadline = time.time() + timeout

    while True:
      event = None
      try:
        event = self.pop_event(event_name, 1)
      except queue.Empty:
        pass

      if event and predicate(event, *args, **kwargs):
        return event

      if time.time() > deadline:
        raise queue.Empty(
          'Timeout after {}s waiting for event: {}'.format(
            timeout, event_name))

  def pop_events(self, regex_pattern, timeout):
    """Pop events whose names match a regex pattern.

    If such event(s) exist, pop one event from each event queue that
    satisfies the condition. Otherwise, wait for an event that satisfies
    the condition to occur, with timeout.

    Results are sorted by timestamp in ascending order.

    Args:
      regex_pattern: The regular expression pattern that an event name
        should match in order to be popped.
      timeout: Number of seconds to wait for events in case no event
        matching the condition exits when the function is called.

    Returns:
      Events whose names match a regex pattern.
      Empty if none exist and the wait timed out.

    Raises:
      IllegalStateError: Raised if pop is called before the dispatcher
        starts polling.
      queue.Empty: Raised if no event was found before time out.
    """
    if not self.started:
      raise IllegalStateError(
        "Dispatcher needs to be started before popping.")
    deadline = time.time() + timeout
    while True:
      #TODO: fix the sleep loop
      results = self._match_and_pop(regex_pattern)
      if len(results) != 0 or time.time() > deadline:
        break
      time.sleep(1)
    if len(results) == 0:
      raise queue.Empty('Timeout after {}s waiting for event: {}'.format(
        timeout, regex_pattern))

    return sorted(results, key=lambda event: event['time'])

  def _match_and_pop(self, regex_pattern):
    """Pop one event from each of the event queues whose names
    match (in a sense of regular expression) regex_pattern.
    """
    results = []
    self.lock.acquire()
    for name in self.event_dict.keys():
      if re.match(regex_pattern, name):
        q = self.event_dict[name]
        if q:
          try:
            results.append(q.get(False))
          except:
            pass
    self.lock.release()
    return results

  def get_event_q(self, event_name):
    """Obtain the queue storing events of the specified name.

    If no event of this name has been polled, wait for one to.

    Returns:
      A queue storing all the events of the specified name.
      None if timed out.

    Raises:
      queue.Empty: Raised if the queue does not exist and timeout has
        passed.
    """
    self.lock.acquire()
    if event_name not in self.event_dict or self.event_dict[
        event_name] is None:
      self.event_dict[event_name] = queue.Queue()
    self.lock.release()

    event_queue = self.event_dict[event_name]
    return event_queue

  def handle_subscribed_event(self, event_obj, event_name):
    """Execute the registered handler of an event.

    Retrieve the handler and its arguments, and execute the handler in a
      new thread.

    Args:
      event_obj: Json object of the event.
      event_name: Name of the event to call handler for.
    """
    handler, args = self.handlers[event_name]
    self.executor.submit(handler, event_obj, *args)

  def _handle(self, event_handler, event_name, user_args, event_timeout,
        cond, cond_timeout):
    """Pop an event of specified type and calls its handler on it. If
    condition is not None, block until condition is met or timeout.
    """
    if cond:
      cond.wait(cond_timeout)
    event = self.pop_event(event_name, event_timeout)
    return event_handler(event, *user_args)

  def handle_event(self,
           event_handler,
           event_name,
           user_args,
           event_timeout=None,
           cond=None,
           cond_timeout=None):
    """Handle events that don't have registered handlers

    In a new thread, poll one event of specified type from its queue and
    execute its handler. If no such event exists, the thread waits until
    one appears.

    Args:
      event_handler: Handler for the event, which should take at least
        one argument - the event json object.
      event_name: Name of the event to be handled.
      user_args: User arguments for the handler; to be passed in after
        the event json.
      event_timeout: Number of seconds to wait for the event to come.
      cond: A condition to wait on before executing the handler. Should
        be a threading.Event object.
      cond_timeout: Number of seconds to wait before the condition times
        out. Never times out if None.

    Returns:
      A concurrent.Future object associated with the handler.
      If blocking call worker.result() is triggered, the handler
      needs to return something to unblock.
    """
    worker = self.executor.submit(self._handle, event_handler, event_name,
                    user_args, event_timeout, cond,
                    cond_timeout)
    return worker

  def pop_all(self, event_name):
    """Return and remove all stored events of a specified name.

    Pops all events from their queue. May miss the latest ones.
    If no event is available, return immediately.

    Args:
      event_name: Name of the events to be popped.

    Returns:
      List of the desired events.

    Raises:
      IllegalStateError: Raised if pop is called before the dispatcher
        starts polling.
    """
    if not self.started:
      raise IllegalStateError(("Dispatcher needs to be started before "
                   "popping."))
    results = []
    try:
      self.lock.acquire()
      while True:
        e = self.event_dict[event_name].get(block=False)
        results.append(e)
    except (queue.Empty, KeyError):
      return results
    finally:
      self.lock.release()

  def clear_events(self, event_name):
    """Clear all events of a particular name.

    Args:
      event_name: Name of the events to be popped.
    """
    self.lock.acquire()
    try:
      q = self.get_event_q(event_name)
      q.queue.clear()
    except queue.Empty:
      return
    finally:
      self.lock.release()

  def clear_all_events(self):
    """Clear all event queues and their cached events."""
    self.lock.acquire()
    self.event_dict.clear()
    self.lock.release()
