"""."""
from threading import Thread as _Thread, Event as _Event
import logging as _log

from mathphys.functions import save_pickle as _save_pickle, \
    load_pickle as _load_pickle


class DataBaseClass:
    """."""

    def __init__(self, params=None):
        """."""
        self.data = dict()
        self.params = params

    def save_data(self, fname, overwrite=False):
        """."""
        data = dict(params=self.params, data=self.data)
        _save_pickle(data, fname, overwrite=overwrite)

    def load_and_apply(self, fname):
        """."""
        data = self.load_data(fname)
        self.data = data['data']
        self.params = data['params']

    @staticmethod
    def load_data(fname):
        """."""
        return _load_pickle(fname)


class MeasBaseClass(DataBaseClass):
    """."""

    def __init__(self, params=None):
        """."""
        super().__init__(params=params)
        self.devices = dict()
        self.analysis = dict()
        self.pvs = dict()

    @property
    def connected(self):
        """."""
        conn = all([dev.connected for dev in self.devices.values()])
        conn &= all([pv.connected for pv in self.pvs.values()])
        return conn

    def wait_for_connection(self, timeout=None):
        """."""
        obs = list(self.devices.values()) + list(self.pvs.values())
        for dev in obs:
            if not dev.wait_for_connection(timeout=timeout):
                return False
        return True


class ThreadedMeasBaseClass(MeasBaseClass):
    """."""

    def __init__(self, params=None, target=None, isonline=True):
        """."""
        super().__init__(params=params)
        self.isonline = bool(isonline)
        self._target = target
        self._stopevt = _Event()
        self._finished = _Event()
        self._finished.set()
        self._thread = _Thread(target=self._run, daemon=True)

    def start(self):
        """."""
        if self.ismeasuring:
            _log.error('There is another measurement happening.')
            return
        self._stopevt.clear()
        self._finished.clear()
        self._thread = _Thread(target=self._run, daemon=True)
        self._thread.start()

    def stop(self):
        """."""
        self._stopevt.set()

    @property
    def ismeasuring(self):
        """."""
        return self._finished.is_set()

    def wait_measurement(self, timeout=None):
        """Wait for measurement to finish."""
        return self._finished.wait(timeout=timeout)

    def _run(self):
        self._finished.clear()
        if self._target is not None:
            self._target()
        self._finished.set()

@@ -1749,71 +1749,8 @@
 t()%0A
-        self._finished = _Event()%0A        self._finished.set()%0A
     
@@ -1993,39 +1993,8 @@
 r()%0A
-        self._finished.clear()%0A
     
@@ -2228,23 +2228,23 @@
 lf._
-finished.is_set
+thread.is_alive
 ()%0A%0A
@@ -2347,34 +2347,65 @@
     
-return self._finished.wait
+if self._thread.is_alive():%0A            self._thread.join
 (tim
@@ -2422,59 +2422,105 @@
 ut)%0A
-%0A
+  
     
-def _run(self):%0A        self._finished.clear()
+  else:%0A            return True%0A        return self._thread.is_alive()%0A%0A    def _run(self):
 %0A   
@@ -2584,33 +2584,4 @@
 t()%0A
-        self._finished.set()%0A

use `Thread` methods to find out if it is running and to wait it finishing.