# libShelly.py
"""
25.04.2021
"""
import http.client as httplib
import logging
from mylib2 import *
import json
import socket
import base64
import http.client as httplib
from mysql.connector import errorcode


# GLOBALE VARIABLEN
# global logger 

# TODO
class Shelly():
    # Konstruktor
    def __init__(self, base_ip):
        self.base_ip = base_ip # 192.168.168.
    # Shelly.__init__()

    # Formatter
    def __str__(self):
        return ('.base_ip:{}'.format(self.base_ip))
    # Shelly.__str__()

    # IP-Adresse
    def set(self, base_ip = None):
        if base_ip != None:
            self.base_ip = base_ip
    # ShellyUni.set

    # http_get()
    def http_get(self, id, url, username=None, password=None, log_error=False, logger=None):
        """Send HTTP GET request"""
        res = ""
        success = False
        conn = None
        host = '{}{}'.format(self.base_ip, id)
        try:
            #logger.debug("shg: http://%s%s", host, url)
            conn = httplib.HTTPConnection(host, timeout=5)
            headers = {"Connection": "close"}
            conn.request("GET", url, None, headers)
            resp = conn.getresponse()

            if resp.status == 401 and \
                    username is not None and password is not None:
                combo = '%s:%s' % (username, password)
                auth = str(
                    base64.b64encode(combo.encode()))  # .replace('\n', '')
                headers["Authorization"] = "Basic %s" % auth
                conn.request("GET", url, None, headers)
                resp = conn.getresponse()

            if resp.status == 200:
                body = resp.read()
                # print("Body: %s", body)
                res = json.loads(body)
                success = True
                #logger.debug("shg: http://%s%s - Ok %s", host, url, res)
            else:
                res = "shg: Error, {} {} http://{}{}".format(
                    resp.status, resp.reason, host, url)
                logger.warning(res)
        except Exception as ex:
            success = False
            if (type(ex) == socket.timeout):
                msg = "shg: Timeout connecting to http://" + host + url
                try:
                    res = socket.gethostbyaddr(host)[0]
                    msg += " [" + res + "]"
                except Exception as ex:
                    pass
                logger.error(msg)
            else:
                res = str(ex)
                if log_error:
                    logger.debug("Error http GET: %s %s %s", host, url, res)
                #else:
                #    logger.error("Fail http GET: %s %s %s", host, url, res)
        finally:
            if conn:
                conn.close()

        return success, res
    # shelly.http_get()
# class Shelly

# Geraet
class Geraet():

    # Konstruktor
    def __init__(self, id, typ, name='', raum='', shelly=None, logger=None):
        self.id = id
        self.typ = typ
        self.name = name
        self.raum = raum
        self.shelly = shelly
        self.loffer = logger
    # Geraet.__init__()

    # Formatter
    def __str__(self):
        return ('.shelly:{} .id:{} .typ:{} .name:{} .raum:{}'.format(self.shelly, self.id, self.typ, self.name, self.raum))
    # Geraet.str()

    #
    def dict(self):
        d = {str(self.id): self} # {Geräte-ID : Gerät}
        # logger.debug('d: {}'.format(d))
        return d
    # Geraet.dict()

    # Kommando an Gerät übertragen
    def kommando(self, kdos):
        # kdos = {'EIN': None, 'TIMER':30}

        CKDOS = {
            'SHSW-1': {
                'uri': '/relay/0', 
                'EIN': 'turn=on',
                'AUS': 'turn=off',
                'UMS': 'turn=toggle',
                'TIMER': 'timer=',
                'ISON': 'ison'},
            'SHBDUO-1': {
                'uri': '/light/0', 
                'EIN': 'turn=on',
                'AUS': 'turn=off',
                'HELL': 'helligkeit=',
                'FARBE': 'white=',
                'UMS': 'turn=toggle',
                'TIMER': 'timer='},
            }
        # logger.debug('KDOS: {}'.format(KDOS['SWSS']))

        uri = CKDOS.get(self.typ).get('uri', None)
        if uri is None:
            logger.error('{}: Kommando uri für {} nicht definiert'.format(self.id, self.typ))
            return -1
        c = '?'
        #print(kdos)
        for kdo, par in kdos.items():
            k = CKDOS.get(self.typ).get(kdo)
            if k is None:
                logger.error('{}: Kommando {} für {} nicht definiert'.format(self.id, kdo, self.typ))
                return -1
            uri += c + k
            if par != None:
                uri += str(par)
            c ='&'
        success, res = self.shelly.http_get(self.id, uri)
        return success, res
    # Geraet.kommando()

    def read(self, attr):
        res = ""
        uri = "/status"
        success = False
        conn = None
        # Attribut auslesen
        success, res = self.shelly.http_get(self.id, uri)
        pass # TODO
    # Geraet.read()
# class Geraet

# Class Relais
class Relais(Geraet):

    # Konstruktor
    def __init__(self, id, lfd=0, name=None, raum='Lager', shelly=None):
        if name == None:
            name = 'ShellyRelais{}.{}'.format(id, lfd)
        super().__init__(id, 'SHSW-1', name, raum, shelly)
        self.lfd = lfd
    # Relais.__init__()

    # Zustand Relais
    def status(self, logger=None):
        ret, res = self.shelly.http_get(self.id, "/status", logger=logger)
        ison = -1
        if ret:
            ison = res.get('relays', -2)[self.lfd].get('ison', -3)
        #logger.debug('relais.ison: {}'.format(ison))
        return ison
    # Relais.status()

    # Relais an
    def turn_on(self, logger=None):
        ret, res = self.shelly.http_get(self.id, "/relay/{}?turn=on".format(self.lfd), logger=logger)
    # Relais.turn_on()

    # Relais aus
    def turn_off(self, logger=None):
        ret, res = self.shelly.http_get(self.id, "/relay/{}?turn=off".format(self.lfd), logger=logger)
    # Relais.turn_of()

# class Relais

class ShellyMotion(Geraet):

    # Konstruktor
    def __init__(self, id, name=None, raum='Lager', shelly=None):
        if name == None:
            name = 'ShellyMotion{}'.format(id)
        super().__init__(id, 'MOTION', name, raum, shelly)
        self.state = None
    # Relais.__init__()

    # Gesamtstatus
    def status(self, logger=None, attr=None):
        logger.debug('> ShellyMotion.status({})'.format(attr))
        ret, res = self.shelly.http_get(self.id, "/status", logger=logger)
        if res != None:
            #logger.debug('result: {}'.format(res))
            #return res['ison']
            if (attr != None):
                res = res.get(attr).get('value', -1)
                logger.debug('{}: {}'.format(attr, res))
        else:
            logger.error('ret: {}'.format(ret))
        return ret, res
    # ShellyMotion.status()

    # Spannungsmessung ADC
    def voltage(self, logger=None):
        #logger.debug('> ShellyUni.voltage()')
        ret, res = self.status(logger=logger)
        volt = -1
        if res != None:
            try:
                volt = res['adcs'][0]['voltage']
            except:
                volt = -2
            #logger.debug('voltage: {} V'.format(volt))
        return volt
    # ShellyUni.voltage

# class ShellyUni

class ShellyUni(Geraet):

    # Konstruktor
    def __init__(self, id, name=None, raum='Lager', shelly=None):
        if name == None:
            name = 'ShellyUni{}'.format(id)
        super().__init__(id, 'SHUNI-1', name, raum, shelly)
        self.state = None
    # Relais.__init__()

    # Gesamtstatus
    def status(self, logger=None):
        logger.debug('> ShellyUni.status()')
        ret, res = self.shelly.http_get(self.id, "/status", logger=logger)
        if res != None:
            #logger.debug('result: {}'.format(res))
            #return res['ison']
            pass
        else:
            logger.error('ret: {}'.format(ret))
        return ret, res
    # ShellyUni.status()

    # Spannungsmessung ADC
    def voltage(self, logger=None):
        logger.debug('> ShellyUni.voltage()')
        ret, res = self.status(logger=logger)
        logger.debug('result: {}'.format(res))
        volt = -1
        if res != None:
            try:
                volt = res['adcs'][0]['voltage']
            except:
                volt = -2
            #logger.debug('voltage: {} V'.format(volt))
        return volt
    # ShellyUni.voltage

# class ShellyUni
