# Path: LoggingConfig.py
# class LoggingConfig():
#     def __init__(self, filename: str, max_bytes: int):
#         self.__filename = filename
#         self.__max_bytes = max_bytes
#         self.__debug = False
# 
#     def enable_debug(self, debug: bool):
#         self.__debug = debug
# 
#     def get_logger(self) -> logging.Logger:
#         formatter = logging.Formatter(fmt='%(levelname)s (%(threadName)-10s) :%(name)s: %(message)s '
#                                   '(%(asctime)s; %(filename)s:%(lineno)d)',
#                               datefmt="%Y-%m-%d %H:%M:%S")
#         handlers = [
#             logging.handlers.RotatingFileHandler(self.__filename,
#                                                  encoding='utf8',
#                                                  maxBytes=self.__max_bytes,
#                                                  backupCount=3),
#             logging.StreamHandler()
#         ]
#         self.__root_logger = logging.getLogger()
#         if (self.__debug):
#             level = logging.DEBUG
#         else:
#             level = logging.WARNING
#         self.__root_logger.setLevel(level)
#         for h in handlers:
#             h.setFormatter(formatter)
#             h.setLevel(level)
#             self.__root_logger.addHandler(h)
#         return self.__root_logger
# 
#     def set_error_hadler(self, type, value, tb):
#         self.__root_logger.exception("Uncaught exception: {0}".format(str(value)))
# 
# Path: communication/MqttConnection.py
# class MqttConnection:
#     MOVEMENT_CHANNEL = 'robot/movement'
#     STATUS_CHANNEL = 'robot/status'
# 
#     def __init__(self, host: str, port: str, user: str, password: str):
#         self.__host = host
#         self.__port = port
#         self.__user = user
#         self.__password = password
#         self.__callback = None
#         self.__client = None
# 
#     def connect(self):
#         self.__client = mqtt.Client()
# 
#         def on_connect(client, userdata, flags, rc):
#             self.__client.subscribe(self.MOVEMENT_CHANNEL)
# 
#         def on_message(client, userdata, msg):
#             if self.__callback is not None:
#                 self.__callback(msg.payload)
# 
#         self.__client.on_connect = on_connect
#         self.__client.on_message = on_message
#         self.__client.username_pw_set(self.__user, self.__password)
#         self.__client.connect_async(self.__host, self.__port, 60)
#         self.__client.loop_start()
# 
#     def listen(self, callback: Callable[[codecs.StreamReader], None]):
#         self.__callback = callback
# 
#     def send(self, channel: str, message: str):
#         self.__client.publish(channel, message, 2)
# 
# Path: communication/Serial.py
# class Serial:
#     def __init__(self, port: str, baud_rate: str):
#         self.__port = port
#         self.__baud_rate = baud_rate
#         self.__message_buffer = ''
#         self.__serial = None
#         self.__receive_message_callback = None
# 
#     def add_callback(self, receive_message_callback):
#         self.__receive_message_callback = receive_message_callback
# 
#     def connect(self):
#         self.__serial = serial.Serial(self.__port, self.__baud_rate,timeout=0.5, writeTimeout=0.5)
# 
#     def disconnect(self):
#         self.__serial.close()
# 
#     def send(self, value: str):
#         self.__serial.write(value)
# 
#     def loop(self):
#         if self.__receive_message_callback is None:
#             return
#         received_data = self.__serial.read()
#         if received_data.decode() is False or received_data.decode() == '':
#             return
#         self.__message_buffer += received_data.decode()
#         if not self.__has_received_full_message():
#             return
#         self.__receive_message_callback(self.__message_buffer)
#         self.__message_buffer = ''
# 
#     def __has_received_full_message(self):
#         return True if self.__message_buffer[-1] == RobotSerialCommandsConverter.MESSAGE_TERMINATOR else False
# 
# Path: communication/SerialMqttBridge.py
# class SerialMqttBridge:
#     COMMUNICATION_TERMINATOR = ';'
# 
#     def __init__(self, mqtt_connection : MqttConnection, serial: Serial, logging: logging.Logger):
#         self.__mqtt_connection = mqtt_connection
#         self.__serial = serial
#         self.__logging = logging
# 
#     def received_serial_message(self, message: str):
#         self.__logging.debug("Received through serial:" + message)
#         self.__mqtt_connection.send(MqttConnection.STATUS_CHANNEL, message)
# 
#     def received_command(self, message: codecs.StreamReader):
#         self.__logging.debug("Received through MQTT: " + message.decode())
#         forward_serial = message + RobotSerialCommandsConverter.MESSAGE_TERMINATOR.encode()
#         self.__serial.send(forward_serial)


import config
import argparse
import sys
from LoggingConfig import LoggingConfig
from time import sleep
from communication.MqttConnection import MqttConnection
from communication.Serial import Serial
from communication.SerialMqttBridge import SerialMqttBridge



# configure argument parser
parser = argparse.ArgumentParser(description='Controlls robot')
parser.add_argument('--debug', dest='debug', action='store_true')
parser.set_defaults(feature=False)
args = parser.parse_args()

# configure logging and exception handler
logging_config = LoggingConfig(config.logging['log_file'], config.logging['log_entries'])
logging_config.enable_debug(args.debug)

# Path: LoggingConfig.py
# class LoggingConfig():
#     def __init__(self, filename: str, max_bytes: int):
#         self.__filename = filename
#         self.__max_bytes = max_bytes
#         self.__debug = False
# 
#     def enable_debug(self, debug: bool):
#         self.__debug = debug
# 
#     def get_logger(self) -> logging.Logger:
#         formatter = logging.Formatter(fmt='%(levelname)s (%(threadName)-10s) :%(name)s: %(message)s '
#                                   '(%(asctime)s; %(filename)s:%(lineno)d)',
#                               datefmt="%Y-%m-%d %H:%M:%S")
#         handlers = [
#             logging.handlers.RotatingFileHandler(self.__filename,
#                                                  encoding='utf8',
#                                                  maxBytes=self.__max_bytes,
#                                                  backupCount=3),
#             logging.StreamHandler()
#         ]
#         self.__root_logger = logging.getLogger()
#         if (self.__debug):
#             level = logging.DEBUG
#         else:
#             level = logging.WARNING
#         self.__root_logger.setLevel(level)
#         for h in handlers:
#             h.setFormatter(formatter)
#             h.setLevel(level)
#             self.__root_logger.addHandler(h)
#         return self.__root_logger
# 
#     def set_error_hadler(self, type, value, tb):
#         self.__root_logger.exception("Uncaught exception: {0}".format(str(value)))
# 
# Path: communication/MqttConnection.py
# class MqttConnection:
#     MOVEMENT_CHANNEL = 'robot/movement'
#     STATUS_CHANNEL = 'robot/status'
# 
#     def __init__(self, host: str, port: str, user: str, password: str):
#         self.__host = host
#         self.__port = port
#         self.__user = user
#         self.__password = password
#         self.__callback = None
#         self.__client = None
# 
#     def connect(self):
#         self.__client = mqtt.Client()
# 
#         def on_connect(client, userdata, flags, rc):
#             self.__client.subscribe(self.MOVEMENT_CHANNEL)
# 
#         def on_message(client, userdata, msg):
#             if self.__callback is not None:
#                 self.__callback(msg.payload)
# 
#         self.__client.on_connect = on_connect
#         self.__client.on_message = on_message
#         self.__client.username_pw_set(self.__user, self.__password)
#         self.__client.connect_async(self.__host, self.__port, 60)
#         self.__client.loop_start()
# 
#     def listen(self, callback: Callable[[codecs.StreamReader], None]):
#         self.__callback = callback
# 
#     def send(self, channel: str, message: str):
#         self.__client.publish(channel, message, 2)
# 
# Path: communication/Serial.py
# class Serial:
#     def __init__(self, port: str, baud_rate: str):
#         self.__port = port
#         self.__baud_rate = baud_rate
#         self.__message_buffer = ''
#         self.__serial = None
#         self.__receive_message_callback = None
# 
#     def add_callback(self, receive_message_callback):
#         self.__receive_message_callback = receive_message_callback
# 
#     def connect(self):
#         self.__serial = serial.Serial(self.__port, self.__baud_rate,timeout=0.5, writeTimeout=0.5)
# 
#     def disconnect(self):
#         self.__serial.close()
# 
#     def send(self, value: str):
#         self.__serial.write(value)
# 
#     def loop(self):
#         if self.__receive_message_callback is None:
#             return
#         received_data = self.__serial.read()
#         if received_data.decode() is False or received_data.decode() == '':
#             return
#         self.__message_buffer += received_data.decode()
#         if not self.__has_received_full_message():
#             return
#         self.__receive_message_callback(self.__message_buffer)
#         self.__message_buffer = ''
# 
#     def __has_received_full_message(self):
#         return True if self.__message_buffer[-1] == RobotSerialCommandsConverter.MESSAGE_TERMINATOR else False
# 
# Path: communication/SerialMqttBridge.py
# class SerialMqttBridge:
#     COMMUNICATION_TERMINATOR = ';'
# 
#     def __init__(self, mqtt_connection : MqttConnection, serial: Serial, logging: logging.Logger):
#         self.__mqtt_connection = mqtt_connection
#         self.__serial = serial
#         self.__logging = logging
# 
#     def received_serial_message(self, message: str):
#         self.__logging.debug("Received through serial:" + message)
#         self.__mqtt_connection.send(MqttConnection.STATUS_CHANNEL, message)
# 
#     def received_command(self, message: codecs.StreamReader):
#         self.__logging.debug("Received through MQTT: " + message.decode())
#         forward_serial = message + RobotSerialCommandsConverter.MESSAGE_TERMINATOR.encode()
#         self.__serial.send(forward_serial)


# Path: server.py
import config
import argparse
import sys
from LoggingConfig import LoggingConfig
from time import sleep
from communication.MqttConnection import MqttConnection
from communication.Serial import Serial
from communication.SerialMqttBridge import SerialMqttBridge




# configure argument parser
parser = argparse.ArgumentParser(description='Controlls robot')
parser.add_argument('--debug', dest='debug', action='store_true')
parser.set_defaults(feature=False)
args = parser.parse_args()

# configure logging and exception handler
logging_config = LoggingConfig(config.logging['log_file'], config.logging['log_entries'])
logging_config.enable_debug(args.debug)

logger = logging_config.get_logger()