#           Kodi Plugin
#
#           Author:     Dnpwwo, 2016
#
"""
<plugin key="Kodi" name="Kodi Players" author="dnpwwo" version="1.0.1" wikilink="http://www.domoticz.com/wiki/plugins/Kodi.html" externallink="https://kodi.tv/">
    <params>
        <param field="Address" label="IP Address" width="200px" required="true" default="127.0.0.1"/>
        <param field="Port" label="Port" width="30px" required="true" default="9090"/>
        <param field="Mode1" label="MAC Address" width="150px" required="false"/>
        <param field="Mode2" label="Shutdown Command" width="100px">
            <options>
                <option label="Hibernate" value="Hibernate"/>
                <option label="Suspend" value="Suspend"/>
                <option label="Shutdown" value="Shutdown"/>
                <option label="Ignore" value="Ignore" default="true" />
            </options>
        </param>
        <param field="Mode3" label="Notifications" width="75px">
            <options>
                <option label="True" value="True"/>
                <option label="False" value="False"  default="true" />
            </options>
        </param>
        <param field="Mode6" label="Debug" width="75px">
            <options>
                <option label="True" value="Debug"/>
                <option label="False" value="Normal"  default="true" />
            </options>
        </param>
    </params>
</plugin>
"""
import Domoticz
import json

isConnected = False
nextConnect = 3
oustandingPings = 0
canShutdown = False
canSuspend = False
canHibernate = False

# player status
playerState = 0
playerID = -1
mediaLevel=0
mediaDescrption = ""
percentComplete = 0

# other
playlistName = ""
playlistPos = 0

# Domoticz call back functions
def onStart():
    global playerState, mediaLevel
    if Parameters["Mode6"] == "Debug":
        Domoticz.Debugging(1)
    if (len(Devices) == 0):
        Domoticz.Device(Name="Status",  Unit=1, Type=17,  Switchtype=17).Create()
        Domoticz.Device(Name="Source",  Unit=2, Type=244, Subtype=62, Switchtype=18, Image=12, Options="LevelActions:fHx8fA==;LevelNames:T2ZmfFZpZGVvfE11c2ljfFRWIFNob3dzfExpdmUgVFY=;LevelOffHidden:ZmFsc2U=;SelectorStyle:MA==").Create()
        Domoticz.Device(Name="Volume",  Unit=3, Type=244, Subtype=73, Switchtype=7,  Image=8).Create()
        Domoticz.Device(Name="Playing", Unit=4, Type=244, Subtype=73, Switchtype=7,  Image=12).Create()
        Domoticz.Log("Devices created.")
    else:
        if (1 in Devices): playerState = Devices[1].nValue
        if (2 in Devices): mediaLevel = Devices[2].nValue
    DumpConfigToLog()
    Domoticz.Transport("TCP/IP", Parameters["Address"], Parameters["Port"])
    Domoticz.Protocol("JSON")
    Domoticz.Heartbeat(10)
    Domoticz.Connect()
    return True

def onConnect(Status, Description):
    global isConnected, playerState
    if (Status == 0):
        isConnected = True
        Domoticz.Log("Connected successfully to: "+Parameters["Address"]+":"+Parameters["Port"])
        playerState = 1
        Domoticz.Send('{"jsonrpc":"2.0","method":"System.GetProperties","params":{"properties":["canhibernate","cansuspend","canshutdown"]},"id":1007}')
        Domoticz.Send('{"jsonrpc":"2.0","method":"Application.GetProperties","id":1011,"params":{"properties":["volume","muted"]}}')
        Domoticz.Send('{"jsonrpc":"2.0","method":"Player.GetActivePlayers","id":1001}')
    else:
        isConnected = False
        Domoticz.Log("Failed to connect ("+str(Status)+") to: "+Parameters["Address"]+":"+Parameters["Port"])
        Domoticz.Debug("Failed to connect ("+str(Status)+") to: "+Parameters["Address"]+":"+Parameters["Port"]+" with error: "+Description)
        # Turn devices off in Domoticz
        for Key in Devices:
            UpdateDevice(Key, 0, Devices[Key].sValue)
    return True

def onMessage(Data):
    global oustandingPings
    global canShutdown, canSuspend, canHibernate
    global playerState, playerID, mediaLevel, mediaDescrption, percentComplete, playlistName, playlistPos
    
    Response = json.loads(Data)
    if ('error' in Response):
        # Kodi has signalled and error
        if (Response["id"] == 1010):
            Domoticz.Log("Addon execution request failed: "+Data)
        elif (Response["id"] == 2002):
            Domoticz.Send('{"jsonrpc":"2.0","method":"Playlist.Add","params":{"playlistid":1,"item":{"directory":"special://profile/playlists/music/'+playlistName+'.xsp\", "media":"music"}},"id":2003}')
        elif (Response["id"] == 2003):
            Domoticz.Error("Playlist '"+playlistName+"' could not be added, probably does not exist.")
        else:
            Domoticz.Error("Unhandled error response: "+Data)
    elif ('id' not in Response):
        # Events do not have an 'id' because we didn't request them
        if (Response["method"] == "Application.OnVolumeChanged"):
            Domoticz.Debug("Application.OnVolumeChanged recieved.")
            if (Response["params"]["data"]["muted"] == True):
                UpdateDevice(3, 0, int(Response["params"]["data"]["volume"]))
            else:
                UpdateDevice(3, 2, int(Response["params"]["data"]["volume"]))
        elif (Response["method"] == "Player.OnStop") or(Response["method"] == "System.OnWake"):
            Domoticz.Debug("Player.OnStop recieved.")
            ClearDevices()
        elif (Response["method"] == "Player.OnPlay"):
            Domoticz.Debug("Player.OnPlay recieved, Player ID: "+str(playerID))
            playerID = Response["params"]["data"]["player"]["playerid"]
            if (Response["params"]["data"]["item"]["type"] == "picture"):
                playerState = 6
            elif (Response["params"]["data"]["item"]["type"] == "episode"):
                playerState = 4
            elif (Response["params"]["data"]["item"]["type"] == "channel"):
                playerState = 4
            elif (Response["params"]["data"]["item"]["type"] == "movie"):
                playerState = 4
            elif (Response["params"]["data"]["item"]["type"] == "song"):
                playerState = 5
            elif (Response["params"]["data"]["item"]["type"] == "musicvideo"):
                playerState = 4
            else:
                playerState = 9
            if (playerID != -1):
                Domoticz.Send('{"jsonrpc":"2.0","method":"Player.GetItem","id":1003,"params":{"playerid":' + str(playerID) + ',"properties":["artist","album","year","channel","showtitle","season","episode","title"]}}')
        elif (Response["method"] == "Player.OnPause"):
            Domoticz.Debug("Player.OnPause recieved, Player ID: "+str(playerID))
            playerState = 2
            SyncDevices()
        elif (Response["method"] == "Player.OnSeek"):
            if (playerID != -1):
                Domoticz.Send('{"jsonrpc":"2.0","method":"Player.GetProperties","id":1002,"params":{"playerid":' + str(playerID) + ',"properties":["live","percentage","speed"]}}')
            else:
                Domoticz.Send('{"jsonrpc":"2.0","method":"Player.GetActivePlayers","id":1005}')
            Domoticz.Debug("Player.OnSeek recieved, Player ID: "+str(playerID))
        elif (Response["method"] == "System.OnQuit") or (Response["method"] == "System.OnSleep") or (Response["method"] == "System.OnRestart"):
            Domoticz.Debug("System.OnQuit recieved.")
            ClearDevices()
        else:
            Domoticz.Debug("Unhandled unsolicited response: "+Data)
    else:
        Domoticz.Debug(str(Response["id"])+" response received: "+Data)
        # Responses to requests made by the plugin
        if (Response["id"] == 1001):    # PING call when nothing is playing
            if playerState == 0: playerState = 1
            oustandingPings = oustandingPings - 1
            if (len(Response["result"]) > 0) and ('playerid' in Response["result"][0]):
                playerID = Response["result"][0]["playerid"]
                Domoticz.Send('{"jsonrpc":"2.0","method":"Player.GetItem","id":1003,"params":{"playerid":' + str(playerID) + ',"properties":["artist",
"album","year","channel","sho
wtitle","season","episode","title"]}}')
            else:
                ClearDevices()
       