# Copyright (C) 2015-2021 Swift Navigation Inc.
# Contact: https://support.swiftnav.com
#
# This source is subject to the license found in the file 'LICENSE' which must
# be be distributed together with this source. All other rights reserved.
#
# THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
# EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.

from threading import Thread


class Forwarder(Thread):
    """Forwarder

    The :class:`Forwarder` connects an iterable source of incoming
    SBP messages to a callable sink of outgoing SBP messages.  The source
    will typically be a :class:`Handler` which provides queueing and message
    filtering.  The :class:`Forwarder` runs its own thread iterating over the
    source messages and delivering them to the sink.  The thread is run in
    daemon mode and will be destroyed when the main thread exits, or the
    source stops iteration.

    Parameters
    ----------
    source : iterable of tuple(SBP, dict)
      Source of SBP messages.
    sink : callable (SBP, metadata)
      Callable sink of SBP messages.

    """

    def __init__(self, source, sink):
        Thread.__init__(self, name="SBP Forwarder")
        self.daemon = True
        self._broken = False
        self._source = source
        self._sink = sink

    def run(self):
        for msg, metadata in self._source:
            if self._broken:
                break
            self._sink(msg, **metadata)

    def stop(self):
        self._broken = True
        try:
            self._source.breakiter()
            self._sink.flush()
            self._sink.close()
        except:
            pass

    def __enter__(self):
        self.run()

    def __exit__(self, *args, **kw):
        self.stop()
