import serial
import time
import os
import sys
import configparser

from kbhit import KBHit

def parse_line(line, set_clock=False):

    tokens = line.split(",")
    if len(tokens) == 16:
        log_data = {}
        log_data['temp'] = float(tokens[2])
        log_data['humidity'] = float(tokens[4])

        if set_clock:
            # parse time from controller RTC and set system
            # eg: 2021-10-22 19:38:11.198
            time_string = tokens[1]
            logger.warning("Setting system clock from controller...")
            os.system('sudo timedatectl set-time "' + time_string + '"')

        return log_data

    else:

        return None

def call_shutdown(do_shutdown):
    if do_shutdown:
        logger.warning("Shutdown started")
        os.system("ssh -t eyeris-user@10.1.70.11 'sudo shutdown -h now'")
        os.system("sudo shutdown -h now")
        exit(1)

from loguru import logger

if __name__=="__main__":

    cfg = configparser.ConfigParser()
    cfg.read("config.ini")

    data_path = cfg.get("monitor","data_path",fallback="/NVMEDATA/monitor")
    log_rotate = cfg.get("monitor","log_rotate", fallback="10 MB")
    max_temp = cfg.getfloat("monitor","max_temp",fallback=40.0)
    max_humidity = cfg.getfloat("monitor","max_humidity",fallback=30.0)
    do_shutdown = cfg.getboolean("monitor","do_shutdown", fallback=True)
    set_clock = cfg.getboolean("monitor","set_clock", fallback=True)

    if not os.path.exists(data_path):
        os.makedirs(data_path)

    serial_port = cfg.get("serial","port",fallback="/dev/ttyUSB0")
    serial_baud = cfg.get("serial","baud",fallback=115200)

    logger.add(os.path.join(data_path,"{time}.log"), rotation=log_rotate)

    with serial.Serial(serial_port, serial_baud, timeout=1) as ser:

        kb = KBHit()

        while True:

            if kb.kbhit(): 
                c = kb.getch()
                if ord(c) == 27:
                    break

                # command mode
                if c == '!':

                    # retore "normal" terminal
                    kb.set_normal_term()

                    ser.write(c.encode())
                    #line = ser.read_until(expected='>').decode().rstrip()
                    #logger.warning(line)

                    # passthrough loop
                    timer = time.time()
                    while True:
                        if (time.time() - timer > 60):
                            logger.warning("command mode timeout.")
                            break
                        #print("ELC > ", end="")
                        cmd = input("ELC > ")
                        if len(cmd) > 0:
                            logger.info(cmd)
                            if cmd[0] == '!':
                                ser.write((cmd[0]).encode())
                                break
                            else:
                                ser.write((cmd+'\r\n').encode())
                                while True:
                                    line = ser.readline().decode().rstrip()
                                    logger.warning(line)
                                    # Return to prompt after command
                                    if len(line) > 0 and line[-1] == '>':
                                        break
                                    # yes or no question then return to prompt
                                    if len(line) > 0 and line[-1] == ':':
                                        cmd = input("Answer: ")
                                        if len(cmd) > 0 and cmd[0].lower() == 'y':
                                            ser.write(('y').encode())
                                        else:
                                            ser.write(('n').encode())
                                        
                                        break
                        else:
                            time.sleep(0.1)

                    # return to kbhit terminal
                    kb = KBHit()



            line = ser.readline()
            if len(line) > 0:
                line = line.decode().rstrip()
                logger.info(line)

                # parse log data and check sensors
                log_data = parse_line(line, set_clock)
                if log_data:

                    # only set clock on first parse
                    set_clock = False

                    if log_data['temp'] > max_temp:
                        logger.error("Max temperature reached")
                        call_shutdown()

                    if log_data['humidity'] > max_humidity:
                        logger.error("Max humidity reached")
                        call_shutdown(do_shutdown)
                

                # detect shutdown request
                if "shutdown" in line:
                    logger.warning("Shutdown requested, taking action.")
                    call_shutdown(do_shutdown)
            else:
                logger.error("No bytes received from controller.")
                time.sleep(1.0)