import os
import sys
import configparser
import json
from scripts.common.constants import LicenseModule
import base64
import jwt
from dateutil import parser
from datetime import datetime
import yaml
from copy import deepcopy


def licence_validator(payload):
    try:
        dt = parser.parse(payload['valid_till'])
        now = datetime.now()
        if (now > dt):
            sys.stdout.write("Licence Expired \n".format())
            sys.stdout.flush()
            return False
        return True
    except KeyError as e:
        sys.stderr.write("Error loading licence")
        return False


CONFIGURATION_FILE = os.environ.get("CONF_PATH", os.path.join(os.getcwd(), "conf{0}settings.conf".format(os.sep)))
sys.stdout.write("Reading Config from  {} \n".format(CONFIGURATION_FILE))
sys.stdout.flush()
__config = configparser.ConfigParser()
__config.read(CONFIGURATION_FILE)

LOG_LEVEL = os.environ.get("LOG_LEVEL", __config.get('LOGGER', 'loglevel', fallback="DEBUG")).upper()
LOG_HANDLER_NAME = os.environ.get("LOG_HANDLER_NAME", __config.get('LOGGER', 'loglevel', fallback="face-id"))

BASE_LOG_PATH = os.environ.get('BASE_LOG_PATH',
                               __config.get('LOGGER', 'basepath', fallback=os.path.join(os.getcwd(), "logs".format())))

if not os.path.isdir(BASE_LOG_PATH):
    os.mkdir(BASE_LOG_PATH)

DATA_PATH = os.environ.get('BASE_DATA_PATH', __config.get('CLIENT-CONFIG', 'basepath', fallback=os.path.normpath(
    os.getcwd() + '{}data'.format(os.sep))))

sys.stdout.write("Data base path  {} \n".format(DATA_PATH))

DEVICE_ID = os.environ.get("DEVICE_ID", __config.get('CLIENT-CONFIG', 'deviceid', fallback="<undefined>"))

LICENCE_FILE = os.environ.get("LICENCE_FILE", __config.get('CLIENT-CONFIG', 'licence-life', fallback="license.lic"))
LICENCE_FILE = os.path.join(DATA_PATH, LICENCE_FILE)

MODEL_CONFIG_FILE = os.environ.get("MODEL_CONFIG_FILE",
                                   __config.get('CLIENT-CONFIG', 'mask_model=config-path', fallback="mask_model-config.yaml"))
MODEL_CONFIG_FILE = os.path.join(DATA_PATH, MODEL_CONFIG_FILE)

with open(MODEL_CONFIG_FILE, 'r') as stream:
    try:
        MODEL_CONFIG = yaml.safe_load(stream)
    except yaml.YAMLError as exc:
        sys.stderr.write(" **Error loading mask_model config ** \n")
        sys.stderr.flush()
        #sys.exit(1)

PUBLISHERS = os.environ.get("PUBLISHERS", __config.get('CLIENT-CONFIG', 'publishers', fallback="")).split(",")
SUBSCRIBER = os.environ.get("SUBSCRIBER", __config.get('CLIENT-CONFIG', 'subscriber', fallback=""))
if len(PUBLISHERS) == 0:
    sys.stdout.write("Empty publishers \n")
CLIENT_ID = os.environ.get("CLIENT_ID", __config.get('CLIENT-CONFIG', 'client-id', fallback="test-client1"))

STREAM_TYPE = os.environ.get("STREAM_TYPE", __config.get('STREAM-CONFIG', 'stream-type', fallback="usbcam"))

MQTT_CONFIG = {"broker": "", "port": "", "topic": "", "clientId": ""}
MQTT_SUB_CONFIG = deepcopy(MQTT_CONFIG)
FRAME_WRITE_CONFIG = {"basepath": None, "filenameFormat": "{deviceId}_{frameId}", "format": "jpg"}
VIDEO_WRITE_CONFIG = {"basepath": None, "format": "mp4"}
MONGO_WRITE_CONFIG = {"host": None, "port": 27017, "authSource": None, "collection": None, "dbname": None,
                      "keys": "frameId,deviceId,timestamp,metric"}

PUBLISHER_CONFIGS = []
for pub in PUBLISHERS:
    type, Section = pub.split(":")
    if type == "MQTT":
        conf = deepcopy(MQTT_CONFIG)
        conf["broker"] = os.environ.get("{}_broker".format(Section), __config.get(Section, 'broker'))
        conf["port"] = int(os.environ.get("{}_port".format(Section), __config.get(Section, 'port')))
        conf["topic"] = os.environ.get("{}_topic".format(Section), __config.get(Section, 'topic'))
        conf["clientId"] = os.environ.get("{}_clientid".format(Section),
                                          __config.get(Section, 'clientid', fallback="ghf-test-00"))
        conf["type"] = type
        PUBLISHER_CONFIGS.append(conf)
    elif type == "FRAMEWRITE":
        conf = deepcopy(FRAME_WRITE_CONFIG)
        conf["basepath"] = os.environ.get("{}_basepath".format(Section),
                                          __config.get(Section, 'basepath', fallback=os.path.normpath(
                                              os.getcwd() + '{sep}out{sep}frames'.format(sep=os.sep))))
        conf["iformat"] = os.environ.get("{}_iformat".format(Section), __config.get(Section, 'iformat', fallback="jpg"))
        conf["filenameFormat"] = os.environ.get("{}_file_name_format".format(Section),
                                                __config.get(Section, 'file_name_format',
                                                             fallback="{deviceId}_{frameId}"))
        if not os.path.isdir(conf["basepath"]):
            sys.stdout.write("Creating {}  \n".format(conf["basepath"]))
            os.mkdir(conf["basepath"])
        conf["type"] = type
        PUBLISHER_CONFIGS.append(conf)
    elif type == "VIDEOWRITE":
        conf = deepcopy(VIDEO_WRITE_CONFIG)
        conf["basepath"] = os.environ.get("{}_basepath".format(Section),
                                          __config.get(Section, 'basepath', fallback=os.path.normpath(
                                              os.getcwd() + '{sep}out{sep}videos'.format(sep=os.sep))))
        # conf["format"] = os.environ.get("{}_format".format(Section),__config.get(Section, 'file_name_format',fallback="mp4"))
        conf["filenameFormat"] = os.environ.get("{}_file_name_format".format(Section),
                                                __config.get(Section, 'file_name_format',
                                                             fallback="{deviceId}_{timestamp}"))
        conf["fps"] = int(os.environ.get("{}_fps".format(Section),
                                         __config.get(Section, 'fps',
                                                      fallback=30)))
        conf["dims"] = tuple(os.environ.get("{}_dims".format(Section),
                                            __config.get(Section, 'dims',
                                                         fallback="620,320")).split(","))
        if not os.path.isdir(conf["basepath"]):
            sys.stdout.write("Creating {}  \n".format(conf["basepath"]))
            os.mkdir(conf["basepath"])
        conf["type"] = type
        PUBLISHER_CONFIGS.append(conf)
    elif type == "MONGO":
        conf = deepcopy(MONGO_WRITE_CONFIG)
        conf["host"] = os.environ.get("{}_host".format(Section),
                                      __config.get(Section, 'host', fallback="localhost"))
        conf["port"] = int(os.environ.get("{}_port".format(Section),
                                          __config.get(Section, 'port', fallback="test")))
        conf["dbname"] = os.environ.get("{}_dbname".format(Section),
                                        __config.get(Section, 'dbname', fallback="test"))
        conf["collection"] = os.environ.get("{}_collection".format(Section),
                                            __config.get(Section, 'collection', fallback="test"))
        conf["authSource"] = os.environ.get("{}_authsource".format(Section),
                                            __config.get(Section, 'authsource', fallback=None))
        conf["username"] = os.environ.get("{}_username".format(Section),
                                          __config.get(Section, 'username', fallback=None))
        conf["password"] = os.environ.get("{}_password".format(Section),
                                          __config.get(Section, 'password', fallback=None))
        if len(conf["authSource"]) == 0:
            conf["authSource"] = None
        conf["keys"] = os.environ.get("{}_keys".format(Section),
                                      __config.get(Section, 'keys',
                                                   fallback="frameId,deviceId,timestamp,metric")).split(",")
        conf["type"] = type
        PUBLISHER_CONFIGS.append(conf)
    else:
        sys.stderr.write("Unsupported  publisher  {} \n".format(type))

if STREAM_TYPE  in ["rtsp", "usbcam"]:
    FRAME_WIDTH = os.environ.get("FRAME_WIDTH", __config.get('STREAM-CONFIG', 'width', fallback=480))
    FRAME_HEIGHT = os.environ.get("FRAME_HEIGHT", __config.get('STREAM-CONFIG', 'height', fallback=640))
    LATENCY = os.environ.get("LATENCY", __config.get('STREAM-CONFIG', 'latency', fallback=0))
    FRAME_RATE = os.environ.get("FRAME_RATE", __config.get('STREAM-CONFIG', 'framerate', fallback="30/1"))
    F_FORMAT = os.environ.get("F_FORMAT", __config.get('STREAM-CONFIG', 'fformat', fallback="BGRx"))
    USE_GSTREAMER = int(os.environ.get("USE_GSTREAMER", __config.get('STREAM-CONFIG', 'use-gstreamer', fallback=1)))
    CUSTOM_PIPELINE = os.environ.get("CUSTOM_PIPELINE", __config.get('STREAM-CONFIG', 'custom-pipeline', fallback=None))
    URI = os.environ.get("URI", __config.get('STREAM-CONFIG', 'uri', fallback=0))

    BUILD_CONFIG = {
        "sourceType": STREAM_TYPE,
        "width": FRAME_WIDTH,
        "height": FRAME_HEIGHT,
        "latency": LATENCY,
        "framerate": FRAME_RATE,
        "format": F_FORMAT,
        "gstreamer": USE_GSTREAMER,
        "uri": URI
    }

elif STREAM_TYPE == "mqtt":
    MQTT_SUB_CONFIG["broker"] = os.environ.get("STREAM-CONFIG_broker", __config.get('STREAM-CONFIG', 'broker'))
    MQTT_SUB_CONFIG["port"] = os.environ.get("STREAM-CONFIG_port", __config.get('STREAM-CONFIG', 'port'))
    MQTT_SUB_CONFIG["topic"] = os.environ.get("STREAM-CONFIG_topic", __config.get('STREAM-CONFIG', 'topic'))
    MQTT_SUB_CONFIG["clientId"] = os.environ.get("STREAM-CONFIG_clientid",
                                                 __config.get('STREAM-CONFIG', 'clientid', fallback="sdrt"))
    MQTT_SUB_CONFIG["sourceType"] = STREAM_TYPE
    BUILD_CONFIG = MQTT_SUB_CONFIG
elif STREAM_TYPE == "videofile":
    BUILD_CONFIG = {"uri": os.environ.get("URI", __config.get('STREAM-CONFIG', 'uri', fallback=0)),
                    "queueSize": os.environ.get("QUEUE_SIZE",
                                                __config.get('STREAM-CONFIG', 'queue_size', fallback=128)),
                    "sourceType": STREAM_TYPE}
else:
    raise ValueError("unsupported source  {}".format(STREAM_TYPE))

sys.stdout.write("Loading Licence   {} \n".format(LICENCE_FILE))
try:
    private_key = LicenseModule.private_key
    encoding_algorithm = LicenseModule.encoding_algorithm
    LICENCE_PAYLOAD = jwt.decode(bytes(base64.b64decode(open(LICENCE_FILE, 'rb').read())), private_key,
                                 algorithms=[encoding_algorithm])
except Exception as e:
    sys.stderr.write("{}".format(e))
    sys.stderr.write(" **Error loading licence** \n")
    sys.stderr.flush()
    #sys.exit(1)
