#!/usr/bin/python3
# -*- coding: utf-8 -*-

import datetime
from subprocess import run, PIPE
import traceback
import gpsd
import os
import time
import logging
from logging.handlers import RotatingFileHandler
from configobj import ConfigObj
import zmq
import sys
from timezonefinder import TimezoneFinder
#import daemon
#import subprocess

# SetUp logging
# logging.basicConfig(filename='/bdr/gpsctl.log',format='%(asctime)s: %(levelname)s - %(message)s',level=logging.DEBUG)
# Създаване на RotatingFileHandler
handler = RotatingFileHandler(
    filename='/bdr/gpsctl.log',
    maxBytes=10*1024*1024,  # 10 MB максимална големина на файл
    backupCount=5,          # Запазване на 5 стари лог файла
    encoding='utf-8'        # Опционално: задаване на кодиране
)

formatter = logging.Formatter('%(asctime)s: %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
handler.setFormatter(formatter)
logger = logging.getLogger()
logger.setLevel(logging.INFO)  # Задаване на ниво на логване
logger.addHandler(handler)

APP_VERSION = "2.1.1"

### Read global config
# Reference
# https://stackoverflow.com/a/42568457/2147823
# https://stackoverflow.com/a/54148952/2147823
conf = ConfigObj('/etc/bdr.conf') # GPS_DAEMON_SLEEP variable and other global
###

ovrl_cmd = '/usr/local/bin/gstd-client element_set cam_src_pipe location text '
tracking = '/bdr/gpstrack.log'
tz_obj=TimezoneFinder(in_memory=True)
#tz_obj=TimezoneFinder()
CMDDEBUG = False  # Set to True for debug output
SELF_GPS = "6105"
DUMMY_GPS = "FE00"

### ZMQ
context = zmq.Context()
socket = context.socket(zmq.PUB)
socket.connect("tcp://localhost:5555")
time.sleep(1)

websimulator = "/bdr/websimulator.py"

### Connect to the local gpsd ###
gpsd.connect() # gpsd.connect(host="127.0.0.1", port=2947)
location_current = None

class CmdTool:
    def __init__(self, name, cmd):
        self.name = name
        self.cmd = cmd

    def to_arg_list(self, *argv):
        args = self.cmd.split()
        for arg in argv:
            args.append(arg)

        return args

    def run(self, *argv):
        cmd_args = self.to_arg_list(*argv)
        cmd_out = run(cmd_args, stdout=PIPE, stderr=PIPE, universal_newlines=True)
        rc = cmd_out.returncode
        try:
            output = cmd_out.stdout  # int(cmd_out.stdout, base=10)
        except Exception:
            output = None

        return rc, output

def deleteContent(fName):
    open(fName, "w").close()

def daemon_status():
    with open(conf['BDR_STATUS_FIFO'],'a') as f_status: # or status_file
        f_status.write("GPS=1")
        # f_status.close()

def GPSONOFF_state():
    with open('/proc/bdr/gpsonoff','r') as f_state:
        state=f_state.read()
        # f_state.close()
#        state_int=int(float(state))
    if state.rstrip() != str(1):
        logging.debug('GPS ON')
        return True
    else:
        time.sleep(int(conf['GPS_DAEMON_SLEEP']))
        logging.debug('GPS OFF')
        return False

def cmd_to_mcu(opcode,data):

    send_buff = []
    send_buff.append("e6")
    send_buff.append("00")
    send_buff.append(opcode[:2])
    send_buff.append(opcode[2:])
    for ch in data:      #String
        send_buff.append(hex(ord(ch))[2:])
    send_buff.append('00') #ChSum

    # send_buff[1]=str(hex(len(send_buff))).lower() #Replace lenght byte
    strlen = len(send_buff)
    send_buff[1]=str("{0:02x}".format(strlen))

    cmd=''.join(str(ch) for ch in send_buff)
    if CMDDEBUG:
        print("Lenght {} cmd {}".format(strlen,cmd))
        logging.debug("Lenght {} cmd {}".format(strlen,cmd))

    CmdTool("cmd_to_mcu",websimulator).run(cmd)
    send_buff.clear()

def timezone_refresh(current_lat,current_lon,datenew):
#    logging.info('Update TZ')
    # Get current TZ
    tz_file=open("/etc/timezone","r")
    current_tz=tz_file.read()
    tz_file.close()
    logging.debug('System TZ is: %s', current_tz)

    # Get GPS TZ
    gps_tz=tz_obj.certain_timezone_at(lng=current_lon, lat=current_lat)
    logging.debug('GPS TZ is: %s', gps_tz)

    if gps_tz.strip() != current_tz.strip():
        os.system("timedatectl set-timezone " + str(gps_tz))
        os.system("timedatectl set-local-rtc 0")
        newdate="date -s" + "\"" + str(datenew) + "\""
        os.system(newdate)
        os.system("hwclock -w")
        logging.info('Refresh TZ to %s Date is %s', gps_tz, datenew)
    else:
        logging.debug('Current TZ is the same: %s Date is %s', current_tz, datenew)
        newdate="date -s" + "\"" + str(datenew) + "\""
        os.system(newdate)

# def update_ovrl(_location):
#     logging.info('Update GSTD overlay')
#     update_data = (ovrl_cmd + _location)
#     os.system(update_data)


def gps_parser(conf):
    try:
        global location_current
        packet = gpsd.get_current()
        logging.debug('GPS poll %s' % (packet))

        if packet.mode >= 2:

            latitude=packet.lat
            longtitude=packet.lon
            location = str(round(float(latitude),5))+"|"+str(round(float(longtitude),5))

            # with open('/proc/bdr/gpslock','w') as gpslock_file:
            #     # gpslock.write("%d" % packet.mode)
            #     val = 1
            #     gpslock_file.write(str(val))
            logging.debug("Locked position /proc/bdr/gpslock")
            os.system("echo 1 > /proc/bdr/gpslock")


            logging.debug('GPS mode=%s location %s', str(packet.mode), str(location))

            if location_current is None or location != location_current:

                location_current = location

                ###     Check&Set TimeZone
                getdateandtime=str(packet.get_time(local_time=True))
                getdate=getdateandtime.split(' ',1)[1]
                timezone_refresh(latitude,longtitude,getdate)

                ###     Loging data                     ###
                logging.info('GPS mode %s with sats %s position %s',packet.mode,packet.sats,packet.position())

                ###     Write GPS Mode 2/3 and data     ###
                with open('/bdr/gpslocation.log', 'a') as gpslocation:
                    timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                    logging.debug('Save Position')
                    gpslocation.write("{timestamp}: {location}\n".format(timestamp=timestamp, location=location))

                ###     Keep track to file "tracking"   ###
                with open (tracking,'a') as trackingfile:
                    trackingfile.write("%s: %s   %s\n" % ( str(packet.get_time(local_time=True)),packet.position(),packet.map_url()))

                ### Send to DMC deaemon gps data with ZMQ
                pattern="GPS"
                ## TODO - Should be string.encode('utf-8') ?
                socket.send_string("%s %s %s" % (pattern,latitude,longtitude))

                ### Send GPS coords to MCU to the display
                # #latitude = round(float(latitude),4)
                # #longtitude = round(float(longtitude),4)
                # data_string=" " + str(round(float(latitude),4))+"|"+str(round(float(longtitude),4))
                logging.debug('GPS coords to MCU %s' % (location))
                cmd_to_mcu(DUMMY_GPS,location)
                time.sleep(int(conf['GPS_DAEMON_SLEEP']))

        else:
            logging.debug('No GPS lock, mode=%s', str(packet.mode))
            os.system("echo 1 > /proc/bdr/gpslock")
            # cmd_to_mcu(DUMMY_GPS,"00000|00000")
            cmd_to_mcu(DUMMY_GPS,"No location @{} |".format(packet.sats))
            location_current="00000"
            time.sleep(2)
            # with open('/proc/bdr/gpslock','w') as gpslock_file:
            #     # gpslock.write("%d" % packet.mode)
            #     val = 0
            #     gpslock_file.write(str(val))

            # deleteContent('/home/user/bidentifier/gpslocation')


    except Exception as e:
        logging.error("{} {} ".format(traceback.extract_tb(e.__traceback__)[-1],e))

###     Update overlay of GST ###
    # update_ovrl(location_current)

def main():
#    daemon_status()
    conf = None
    while True:
        try:
            logging.info('---')
            conf = ConfigObj('/etc/bdr.conf') # GPS_DAEMON_SLEEP variable and other global vars
            # logging.debug(conf['GPS_DAEMON_SLEEP'] + " seconds time interval")
            # time.sleep(int(conf['GPS_DAEMON_SLEEP']))
            try:
                gps_parser(conf)
            except Exception as str_error:
                logging.warning('Error %s',str_error)
                continue
        except Exception as e:
            logging.error("{} {} ".format(traceback.extract_tb(e.__traceback__)[-1],e))

if __name__ == "__main__":
    main()

### reference
# https://stackoverflow.com/a/20985318/2147823
# https://stackoverflow.com/a/48726480/2147823
###
