from yeelight import *
import time

##---------------------------------------------------------------------------------------##
class Yeelight(object):
##---------------------------------------------------------------------------------------##
    ##-----------------------------------------------------------------------------------##
    def __init__(self, bulbs):
    ##-----------------------------------------------------------------------------------##
        self.bulbs = {}
        self.groups = {}
        for bulb in bulbs:
            try:
                    self.bulbs.update({bulb : Bulb(bulbs[bulb]['ip'],auto_on=True)})
            except:
                print("ERROR: Config not saved for " + bulb)

            try:
                for group in bulbs[bulb]['groups']:
                    groupName = bulbs[bulb]['groups'][group]
                    if(groupName not in self.groups):
                        print("Create new Group " + groupName)
                        self.groups[groupName] = {}

                    self.groups[groupName][bulb] = bulb
            except:
                print(bulb + " ist in keiner Gruppe")

    ##-----------------------------------------------------------------------------------##
    def config(self):
    ##-----------------------------------------------------------------------------------##
        config = {
            "rgb" : {
                "device" : {
                    "name" : "",
                    "ip" : "",
                    "type" : "rgb"
                },
                "power" : {
                    "device" : "name",
                    "state" : "switch"
                },
                "brightness" : {
                    "device" : "name",
                    "state" : "dimmer"
                },
                "temperature" : {
                    "device" : "name",
                    "state" : "dimmer"
                },
                "color" : {
                    "device" : "name",
                    "r" : "dimmer",
                    "g" : "dimmer",
                    "b" : "dimmer"
                }
            },
            "white" : {
                "device" : {
                    "name": "",
                    "ip" : "",
                    "type" : "white"
                },
                "power" : {
                    "device" : "name",
                    "state" : "switch"
                },
                "brightness" : {
                    "device" : "name",
                    "state" : "dimmer"
                },
                "temperature" : {
                    "device" : "name",
                    "state" : "dimmer"
                }
            }
        }
        return config

    ##-----------------------------------------------------------------------------------##
    def state(self):
    ##-----------------------------------------------------------------------------------##
        state = {}
        for bulb in self.bulbs:
            state[bulb] = {}
            try:
                properties = self.bulbs[bulb].get_properties()
            except:
                state[bulb]['offline'] = True
            finally:
                state[bulb]['offline'] = False
                state[bulb]['power'] = properties['power']
                state[bulb]['brightness'] = properties['bright']
                state[bulb]['temperature'] = properties['ct']
                state[bulb]['color'] = properties['rgb']
                state[bulb]['groups'] = {}
                for group in self.groups:
                    if(bulb in self.groups[group]):
                        state[bulb]['groups'][group] = ""
                #r, g, b = tuple(int(properties['rgb'][i:i+2], 16) for i in (0, 2 ,4))
                #print("r:" + str(r) + " g: " + str(g) + " b: " + str(b))
        return state

    ##-----------------------------------------------------------------------------------##
    def command(self, data):
    ##-----------------------------------------------------------------------------------##
        for device in data:
            group = 0
            if device in self.groups:
                group = True
            if(device in self.bulbs or device in self.groups):
                if 'power' in data[device]:
                    self.power(device, group, data[device]['power'])
                    if(data[device]['power'] == "off"):
                        return 0
                if 'brightness' in data[device]:
                    self.brightness(device, group, data[device]['brightness'])
                if 'r' in data[device] or 'g' in data[device] or 'b' in data[device]:
                    if 'r' in data[device]:
                        r = data[device]['r']
                    else:
                        r = "0"
                    if 'g' in data[device]:
                        g = data[device]['g']
                    else:
                        g = "0"
                    if 'b' in data[device]:
                        b = data[device]['b']
                    else:
                        b = "0"
                    self.color(device, group, r, g, b)
                if 'temperature' in data[device]:
                    self.temperature(device, group, data[device]['temperature'])

    ##-----------------------------------------------------------------------------------##
    def power(self, device, group=None, state=None):
    ##-----------------------------------------------------------------------------------##
        if(state==None):
            return -1

        if(device==None):
            for bulb in self.bulbs:
                self.powerBulb(device, state)
        if(group == True):
            for bulb in self.groups[device]:
                self.powerBulb(bulb, state)
        else:
            if(device in self.bulbs):
                self.powerBulb(device, state)

    ##-----------------------------------------------------------------------------------##
    def powerBulb(self, device, state):
    ##-----------------------------------------------------------------------------------##
        if(device in self.bulbs):
            error = False
            try:
                oldState = self.bulbs[device].get_properties()
            except:
                print(device + ": Konnte nicht angesteuert werden")
                error = True
            finally:
                oldState = self.bulbs[device].get_properties()
                if(str(oldState['power']) != str(state)):
                    if(state=="on"):
                        self.bulbs[device].turn_on()
                        print(device + " turned on")
                    else:
                        self.bulbs[device].turn_off()
                        print(device + " turned off")
        if(error == True):
            for count in range(0,10):
                try:
                    oldState = self.bulbs[device].get_properties()
                except:
                    print(device + ": Konnte nicht angesteuert werden")
                finally:
                    oldState = self.bulbs[device].get_properties()
                    if(str(oldState['power']) != str(state)):
                        if(state=="on"):
                            self.bulbs[device].turn_on()
                            print(device + " turned on")
                        else:
                            self.bulbs[device].turn_off()
                            print(device + " turned off")
                try:
                    oldState = self.bulbs[device].get_properties()
                except:
                    print(device + " keine Veraenderung")
                finally:
                    if(oldState['power'] == str(state)):
                        break

    ##-----------------------------------------------------------------------------------##
    def brightness(self, device, group, state=None):
    ##-----------------------------------------------------------------------------------##
        if(state==None):
            return -1

        if(device==None):
            for bulb in self.bulbs:
                self.brightnessBulb(device, state)
        if(group == True):
            for bulb in self.groups[device]:
                self.brightnessBulb(bulb, state)
        else:
            if(device in self.bulbs):
                self.brightnessBulb(device, state)

    ##-----------------------------------------------------------------------------------##
    def brightnessBulb(self, device, state):
    ##-----------------------------------------------------------------------------------##
        if(device in self.bulbs):
            error = False
            try:
                oldState = self.bulbs[device].get_properties()
                print(oldState)
            except:
                print(device + ": Konnte nicht angesteuert werden")
                error = True
            finally:
                oldState = self.bulbs[device].get_properties()
                if(str(oldState['bright']) != str(state)):
                    self.bulbs[device].set_brightness(int(state))
                    print(device + " turned brightness to " + str(state))
        if(error == True):
            for count in range(0,10):
                try:
                    oldState = self.bulbs[device].get_properties()
                except:
                    print(device + ": Konnte nicht angesteuert werden")
                finally:
                    oldState = self.bulbs[device].get_properties()
                    if(str(oldState['bright']) != str(state)):
                        self.bulbs[device].set_brightness(int(state))
                    print(device + " turned brightness to " + str(state))
                try:
                    oldState = self.bulbs[device].get_properties()
                except:
                    print(device + " keine Veraenderung")
                finally:
                    if(oldState['bright'] == str(state)):
                        break

    ##-----------------------------------------------------------------------------------##
    def temperature(self, device, group, state=None):
    ##-----------------------------------------------------------------------------------##
        if(state==None):
            return -1

        if(device==None):
            for bulb in self.bulbs:
                self.temperatureBulb(device, state)
        if(group == True):
            for bulb in self.groups[device]:
                self.temperatureBulb(bulb, state)
        else:
            if(device in self.bulbs):
                self.temperatureBulb(device, state)

    ##-----------------------------------------------------------------------------------##
    def temperatureBulb(self, device, state):
    ##-----------------------------------------------------------------------------------##
        if(device in self.bulbs):
            error = False
            try:
                oldState = self.bulbs[device].get_properties()
            except:
                print(device + ": Konnte nicht angesteuert werden")
                error = True
            finally:
                oldState = self.bulbs[device].get_properties()
                if(str(oldState['ct']) != str(state)):
                    self.bulbs[device].set_color_temp(int(state))
                    print(device + " turned temperature to " + str(state))
        if(error == True):
            for count in range(0,10):
                try:
                    oldState = self.bulbs[device].get_properties()
                except:
                    print(device + ": Konnte nicht angesteuert werden")
                finally:
                    oldState = self.bulbs[device].get_properties()
                    if(str(oldState['ct']) != str(state)):
                        self.bulbs[device].set_color_temp(int(state))
                    print(device + " turned temperature to " + str(state))
                try:
                    oldState = self.bulbs[device].get_properties()
                except:
                    print(device + " keine Veraenderung")
                finally:
                    if(oldState['ct'] == str(state)):
                        break

    ##-----------------------------------------------------------------------------------##
    def color(self, device, group, r, g, b):
    ##-----------------------------------------------------------------------------------##
        if(device==None):
            for bulb in self.bulbs:
                self.colorBulb(device, r, g, b)
        if(group == True):
            for bulb in self.groups[device]:
                self.colorBulb(bulb, r, g, b)
        else:
            if(device in self.bulbs):
                self.colorBulb(device, r, g, b)

    ##-----------------------------------------------------------------------------------##
    def colorBulb(self, device, r, g, b):
    ##-----------------------------------------------------------------------------------##
        bulbCount = 0
        bulbCheck = 0
        if(device in self.bulbs):
            error = False
            try:
                bulbCount = bulbCount + 1
                oldState = self.bulbs[device].get_properties()
            except:
                print(device + ": Konnte nicht angesteuert werden")
                error = True
            finally:
                self.bulbs[device].set_rgb(int(r), int(g), int(b))
                print(device + " color r:" + str(r) + " g:" + str(g) + " b:" + str(b))
                bulbCheck = bulbCheck + 1
            if(bulbCount != bulbCheck):
                for count in range(0,10):
                    bulbCount = 0
                    bulbCheck = 0
                    try:
                        bulbCount = bulbCount + 1
                        oldState = self.bulbs[device].get_properties()
                    except:
                        print(device + ": Konnte nicht angesteuert werden")
                        error = True
                    finally:
                        self.bulbs[device].set_rgb(int(r), int(g), int(b))
                        print(device + " color r:" + str(r) + " g:" + str(g) + " b:" + str(b))
                        bulbCheck = bulbCheck + 1
                    if(bulbCheck==bulbCount):
                        return 0

    ##-----------------------------------------------------------------------------------##
    def temperatureTransition(self, startTemp=1700, endTemp=6500, startBrightness=100,
                                endBrightness=100, seconds=0, count=None):
    ##-----------------------------------------------------------------------------------##
        if(count==None):
            count=10

        duration = seconds*1000
        transitions = [
            TemperatureTransition(startTemp, duration, startBrightness),
            SleepTransition(duration),
            TemperatureTransition(endTemp, duration, endBrightness)
        ]
        flow = Flow(
            count=1,
            action=Flow.actions.recover,
            transitions=transitions
        )
        self.temperature(startBrightness)
        self.brightness(startBrightness)

        bulbCount = 0
        bulbCheck = 0
        for bulb in self.bulbs:
            bulbCount = bulbCount + 1
            try:
                oldState = self.bulbs[bulb].get_properties()
            except:
                print(bulb + ": Konnte nicht angesteuert werden")
            finally:
                self.bulbs[bulb].start_flow(flow)
                print(bulb + " Flow")
                bulbCheck = bulbCheck + 1

        if(bulbCount == bulbCheck):
            return 0
        else:
            if(count!=0):
               time.sleep(.250)
               temperatureTransition(startTemp, endTemp, startBrightness, endBrightness,seconds,count-1)
            else:
                print("Zu viele Versuche. Fehlgeschlagen!")
                return -1
        return 0

    ##-----------------------------------------------------------------------------------##
    def stopTransition(self, count=None):
    ##-----------------------------------------------------------------------------------##
        if(count==None):
            count=10
        bulbCount = 0
        bulbCheck = 0
        for bulb in self.bulbs:
            bulbCount = bulbCount + 1
            try:
                oldState = self.bulbs[bulb].get_properties()
            except:
                print(bulb + ": Konnte nicht angesteuert werden")
            finally:
                self.bulbs[bulb].stop_flow()
                bulbCheck = bulbCheck + 1

        if(bulbCount == bulbCheck):
            return 0
        else:
            if(count!=0):
               time.sleep(.250)
               stopTransition(count-1)
            else:
                print("Zu viele Versuche. Fehlgeschlagen!")
                return -1
        return 0