# -*- coding: utf-8 -*-
#!/usr/bin/env python

"""Writer class based on InfluxDB

This implementation does its best to follow the Robert Martin's Clean code guidelines.
The comments follows the Google Python Style Guide:
    https://github.com/google/styleguide/blob/gh-pages/pyguide.md
"""

__copyright__ = 'Copyright 2021, FCRlab at University of Messina'
__author__ = 'Lorenzo Carnevale <lcarnevale@unime.it>'
__credits__ = ''
__description__ = 'Writer class based on InfluxDB'


import time
import logging
import threading
import persistqueue
from datetime import datetime
from influxdb_client.client.write_api import SYNCHRONOUS
from influxdb_client import InfluxDBClient, Point, WritePrecision

class Reader:

    def __init__(self, host, port, token, organization, bucket, mutex, verbosity):
        self.__url = "http://%s:%s" % (host, port)
        self.__token = token
        self.__organization = organization
        self.__bucket = bucket
        self.__mutex = mutex
        self.__reader = None
        self.__setup_logging(verbosity)

    def __setup_logging(self, verbosity):
        format = "%(asctime)s %(filename)s:%(lineno)d %(levelname)s - %(message)s"
        filename='log/mqtt2influx.log'
        datefmt = "%d/%m/%Y %H:%M:%S"
        level = logging.INFO
        if (verbosity):
            level = logging.DEBUG
        logging.basicConfig(filename=filename, filemode='a', format=format, level=level, datefmt=datefmt)


    def setup(self):
        self.__reader = threading.Thread(
            target = self.__reader_job, 
            args = (self.__url, self.__token, self.__organization, self.__bucket)
        )
    
    def __reader_job(self, url, token, organization, bucket):
        self.__mutex.acquire()
        q = persistqueue.SQLiteQueue('data', multithreading=True, auto_commit=True)
        self.__mutex.release()

        client = InfluxDBClient(url=url, token=token)
        write_api = client.write_api(write_options=SYNCHRONOUS)
        
        try:
            while (True):
                raw_data = q.get()
                logging.debug("Just got new data")

                logging.debug("Parsing data points")
                data = [
                    {
                        "measurement": raw_data['measurement'],
                        "tags": raw_data['tags'], 
                        "fields": raw_data['fields'], 
                        "time": raw_data['time']
                    }
                ]

                write_api.write(bucket, organization, data)
                logging.info("Data into InfluxDB")

                time.sleep(0.3)
        except KeyboardInterrupt:
            pass
        

    def start(self):
        self.__reader.start()
[((1349, 1451), 'logging.basicConfig', 'logging.basicConfig', ([], {'filename': 'filename', 'filemode': '"""a"""', 'format': 'format', 'level': 'level', 'datefmt': 'datefmt'}), "(filename=filename, filemode='a', format=format, level=\n    level, datefmt=datefmt)\n", (1368, 1451), False, 'import logging\n'), ((1494, 1609), 'threading.Thread', 'threading.Thread', ([], {'target': 'self.__reader_job', 'args': '(self.__url, self.__token, self.__organization, self.__bucket)'}), '(target=self.__reader_job, args=(self.__url, self.__token,\n    self.__organization, self.__bucket))\n', (1510, 1609), False, 'import threading\n'), ((1755, 1826), 'persistqueue.SQLiteQueue', 'persistqueue.SQLiteQueue', (['"""data"""'], {'multithreading': '(True)', 'auto_commit': '(True)'}), "('data', multithreading=True, auto_commit=True)\n", (1779, 1826), False, 'import persistqueue\n'), ((1876, 1912), 'influxdb_client.InfluxDBClient', 'InfluxDBClient', ([], {'url': 'url', 'token': 'token'}), '(url=url, token=token)\n', (1890, 1912), False, 'from influxdb_client import InfluxDBClient, Point, WritePrecision\n'), ((2076, 2110), 'logging.debug', 'logging.debug', (['"""Just got new data"""'], {}), "('Just got new data')\n", (2089, 2110), False, 'import logging\n'), ((2128, 2164), 'logging.debug', 'logging.debug', (['"""Parsing data points"""'], {}), "('Parsing data points')\n", (2141, 2164), False, 'import logging\n'), ((2548, 2582), 'logging.info', 'logging.info', (['"""Data into InfluxDB"""'], {}), "('Data into InfluxDB')\n", (2560, 2582), False, 'import logging\n'), ((2600, 2615), 'time.sleep', 'time.sleep', (['(0.3)'], {}), '(0.3)\n', (2610, 2615), False, 'import time\n')]