#!/usr/bin/python3

import copy
from threading import Lock
from elt.oldb import CiiOldb
from elt.oldb import CiiOldbFactory
from elt.oldb import CiiOldbGlobal
from elt.oldb import CiiOldbDpQuality
from elt.pymal import Uri
from elt.oldb import CiiOldbDataPointVectorDOUBLE
from elt.oldb import CiiOldbDpValueDOUBLE
from CiiErrorPyB import CiiPathNotFound
from CiiOldbPyB import CiiOldbException
from CiiOldbPyB import CiiOldbInvalidUriException
from CiiOldbPyB import CiiOldbDpUndefinedException
from CiiOldbPyB import CiiOldbStorageError
from CiiOldbPyB import CiiOldbDpQualityException
from elt.oldb.typesupport import (INT8, INT16, INT32, INT64, UINT8, UINT16, UINT32, UINT64,
                                  DOUBLE, SINGLE, STRING, BOOLEAN,
                                  VECTOR_DOUBLE, VECTOR_SINGLE, VECTOR_INT16, VECTOR_INT32, VECTOR_INT64,
                                  VECTOR_STRING,
                                  MATRIX2D_SINGLE, MATRIX2D_DOUBLE, MATRIX2D_INT16, MATRIX2D_INT32, MATRIX2D_INT64)

class OldbSubscription():

    def __init__(self):
        self._finish_mutex: Lock = Lock()
        self._last_timestamp_mutex: Lock = Lock()
        self._finished = False

    def __del__(self):
        self.finish()

    def finish(self):
        self._finish_mutex.acquire()
        self._finished = True
        self._finish_mutex.release()

    def new_value(self, value: CiiOldbDpValueDOUBLE, uri: str):
        with self._finish_mutex:
            if self._finished:
                return

        quality = None
        val = None
        timestamp = None
        try:
            quality = copy.deepcopy(value.get_quality())
            val = copy.deepcopy(value.get_value())
            timestamp = copy.deepcopy(value.get_timestamp())
            print("{}\t{}\t{}\t{}".format(uri, str(val).ljust(46), str(quality), str(timestamp)))
        except CiiOldbDpQualityException:
            val = copy.deepcopy(value.get_value())
            timestamp = copy.deepcopy(value.get_timestamp())
            print("[OLDB] Quality Exception")
            print("{}\t{}\t{}\t{}".format(uri, str(val).ljust(46), str(quality), str(timestamp)))
        except Exception as e:
            print("[OLDB] Error caught getting values from CiiOldbDpValue {}".format(str(e)))
            print("{}\t{}\t{}\t{}".format(uri, str(val).ljust(46), str(quality), str(timestamp)))

    def dp_removed(self, uri: str):
        self._finish_mutex.acquire()
        if self._finished:
            self._finish_mutex.release()
            return
        else:
            self._finish_mutex.release()
        print("Datapoint %s removed" % (uri))
        # TODO: Implement removal of DP.

if __name__ == "__main__":
    oldbUriString1 = "cii.oldb:///cut/demoservice/instance1/double-vector-current-radec";
    oldbUriString2 = "cii.oldb:///cut/demoservice/instance1/double-vector-current-altaz";
    oldbUriString3 = "cii.oldb:///cut/demoservice/instance1/double-vector-target-radec";
    oldbUriString4 = "cii.oldb:///cut/demoservice/instance1/double-vector-target-altaz";

    uri1 = Uri(oldbUriString1)
    uri2 = Uri(oldbUriString2)
    uri3 = Uri(oldbUriString3)
    uri4 = Uri(oldbUriString4)

    oldb_client = CiiOldbFactory.get_instance()
    double_dp1 = oldb_client.get_data_point(uri1)
    double_dp2 = oldb_client.get_data_point(uri2)
    double_dp3 = oldb_client.get_data_point(uri3)
    double_dp4 = oldb_client.get_data_point(uri4)
    listener1 = VECTOR_DOUBLE.get_new_subscription_instance(OldbSubscription())
    listener2 = VECTOR_DOUBLE.get_new_subscription_instance(OldbSubscription())
    listener3 = VECTOR_DOUBLE.get_new_subscription_instance(OldbSubscription())
    listener4 = VECTOR_DOUBLE.get_new_subscription_instance(OldbSubscription())
    double_dp1.subscribe(listener1)
    double_dp2.subscribe(listener2)
    double_dp3.subscribe(listener3)
    double_dp4.subscribe(listener4)
    input("Press any key to exit")
