#import logging, queue, threading
#from typing import Dict
#from monitoring.client.monitoring_client import MonitoringClient
#from monitoring.proto.monitoring_pb2 import Kpi
#from .driver_api._Driver import _Driver
#
#LOGGER = logging.getLogger(__name__)
#QUEUE_GET_WAIT_TIMEOUT = 0.5
#
#class MonitoringLoop:
#    def __init__(self, driver : _Driver, samples_queue : queue.Queue) -> None:
#        self._driver = driver
#        self._samples_queue = samples_queue
#        self._running = threading.Event()
#        self._terminate = threading.Event()
#        self._samples_stream = self._driver.GetState(blocking=True)
#        self._collector_thread = threading.Thread(target=self._collect, daemon=False)
#
#    def _collect(self) -> None:
#        for sample in self._samples_stream:
#            if self._terminate.is_set(): break
#            LOGGER.info('[MonitoringLoop:_collect] sample={:s}'.format(str(sample)))
#            # TODO: add timestamp (if not present)
#            self._samples_queue.put_nowait(sample)
#
#    def start(self):
#        self._collector_thread.start()
#        self._running.set()
#
#    @property
#    def is_running(self): return self._running.is_set()
#
#    def stop(self):
#        self._terminate.set()
#        self._samples_stream.cancel()
#        self._collector_thread.join()
#
#class MonitoringLoops:
#    def __init__(self, monitoring_client : MonitoringClient) -> None:
#        self._monitoring_client = monitoring_client
#        self._samples_queue = queue.Queue()
#        self._running = threading.Event()
#        self._terminate = threading.Event()
#        self._lock = threading.Lock()
#        self._device_uuid__to__monitoring_loop : Dict[str, MonitoringLoop] = {}
#        self._exporter_thread = threading.Thread(target=self._export, daemon=False)
#
#    def add(self, device_uuid : str, driver : _Driver) -> None:
#        with self._lock:
#            monitoring_loop = self._device_uuid__to__monitoring_loop.get(device_uuid)
#            if (monitoring_loop is not None) and monitoring_loop.is_running: return
#            monitoring_loop = MonitoringLoop(driver, self._samples_queue)
#            self._device_uuid__to__monitoring_loop[device_uuid] = monitoring_loop
#            monitoring_loop.start()
#
#    def remove(self, device_uuid : str) -> None:
#        with self._lock:
#            monitoring_loop = self._device_uuid__to__monitoring_loop.get(device_uuid)
#            if monitoring_loop is None: return
#            if monitoring_loop.is_running: monitoring_loop.stop()
#            self._device_uuid__to__monitoring_loop.pop(device_uuid, None)
#
#    def start(self):
#        self._exporter_thread.start()
#        self._running.set()
#
#    @property
#    def is_running(self): return self._running.is_set()
#
#    def stop(self):
#        self._terminate.set()
#        self._exporter_thread.join()
#
#    def _export(self) -> None:
#        while not self._terminate.is_set():
#            try:
#                sample = self._samples_queue.get(block=True, timeout=QUEUE_GET_WAIT_TIMEOUT)
#                LOGGER.info('[MonitoringLoops:_export] sample={:s}'.format(str(sample)))
#            except queue.Empty:
#                continue
#            # TODO: find in database the KpiId, format KPI and send to Monitoring
#            kpi_data = {}
#            self._monitoring_client.IncludeKpi(Kpi(**kpi_data))
