#!/usr/bin/python

import sys
import os
import struct
import socket
import subprocess
import signal
from gi.repository import GLib
from gi.repository import LightDM

loop = GLib.MainLoop ()

def sigterm_cb (data):
    status_notify ('GREETER %s TERMINATE SIGNAL=%d' % (os.getenv ('DISPLAY'), signal.SIGTERM))
    loop.quit ()
GLib.unix_signal_add (GLib.PRIORITY_DEFAULT, signal.SIGTERM, sigterm_cb, None)

status_socket = None

def status_notify (message):
    if status_socket is not None:
        status_socket.send (struct.pack ('i', len (message)) + message)
    else:
        sys.stderr.write ('%s\n' % message)

def request_cb (channel, condition):
    length = status_socket.recv (4)
    if len (length) == 0:
        loop.quit ();
        return False
    if len (length) > 0:
        (l,) = struct.unpack ('i', length)
        request = status_socket.recv (l)

    r = 'GREETER %s AUTHENTICATE' % os.getenv ('DISPLAY')
    if request == r:
        greeter.authenticate (None)

    r = 'GREETER %s AUTHENTICATE USERNAME=' % os.getenv ('DISPLAY')
    if request.startswith (r):
        greeter.authenticate (request[len(r):])

    r = 'GREETER %s AUTHENTICATE-GUEST' % os.getenv ('DISPLAY')
    if request == r:
        greeter.authenticate_as_guest ()

    r = 'GREETER %s AUTHENTICATE-AUTOLOGIN' % os.getenv ('DISPLAY')
    if request == r:
        greeter.authenticate_autologin ()

    r = 'GREETER %s AUTHENTICATE-REMOTE SESSION=' % os.getenv ('DISPLAY')
    if request.startswith (r):
        greeter.authenticate_remote (request[len(r):], None)

    r = 'GREETER %s RESPOND TEXT=\"' % os.getenv ('DISPLAY')
    if request.startswith (r):
        greeter.respond (request[len (r):-1])

    r = 'GREETER %s CANCEL-AUTHENTICATION' % os.getenv ('DISPLAY')
    if request == r:
        greeter.cancel_authentication ()

    r = 'GREETER %s START-SESSION' % os.getenv ('DISPLAY')
    if request == r:
        if not greeter.start_session_sync (None):
            status_notify ('GREETER %s SESSION-FAILED' % os.getenv ('DISPLAY'))

    r = 'GREETER %s START-SESSION SESSION=' % os.getenv ('DISPLAY')
    if request.startswith (r):
        if not greeter.start_session_sync (request[len(r):]):
            status_notify ('GREETER %s SESSION-FAILED' % os.getenv ('DISPLAY'))

    r = 'GREETER %s LOG-LAYOUT' % os.getenv ('DISPLAY')
    if request == r:
        layout = LightDM.get_layout ().get_name ()
        status_notify ('GREETER %s LOG-LAYOUT LAYOUT=%s' % (os.getenv ('DISPLAY'), layout))

    r = 'GREETER %s LOG-LAYOUT USERNAME=' % os.getenv ('DISPLAY')
    if request.startswith (r):
        username = request[len(r):]
        user = LightDM.UserList.get_instance ().get_user_by_name (username)
        layout = user.get_layout ()
        if layout is None:
            layout = ''
        status_notify ('GREETER %s LOG-LAYOUT USERNAME=%s LAYOUT=%s' % (os.getenv ('DISPLAY'), username, layout))

    r = 'GREETER %s LOG-LANGUAGE USERNAME=' % os.getenv ('DISPLAY')  
    if request.startswith (r):
        username = request[len(r):]
        user = lightdm_user_list_get_user_by_name (lightdm_user_list_get_instance (), username)
        language = lightdm_user_get_language (user)
        if language is None:
            language = ''
        status_notify ('GREETER %s LOG-LANGUAGE USERNAME=%s LANGUAGE=%s' % (os.getenv ('DISPLAY'), username, language))

    return True

path = os.getenv ('LIGHTDM_TEST_ROOT') + '/.status-socket'
status_socket = socket.socket (socket.AF_UNIX, socket.SOCK_STREAM)
status_socket.connect (path)
GLib.io_add_watch (status_socket.fileno (), GLib.IO_IN | GLib.IO_HUP, request_cb)

status_notify ('GREETER %s START' % os.getenv ('DISPLAY'))

# NOTE: There don't seem to be any good X bindings so we have to mock up our own...
(host, display) = os.getenv ('DISPLAY').split (':')
if host == '':
    x_socket = socket.socket (socket.AF_UNIX, socket.SOCK_STREAM)
    x_socket.connect ('/tmp/.X11-unix/X%s' % display)
else:
    x_socket = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
    x_socket.connect ((host, 6000 + int (display)))
authority = subprocess.check_output(['xauth', 'list']).split ()
auth_name = ''
auth_data = ''
if len (authority) >= 3:
    auth_name = authority[1]
    hex = authority[2]
    while len (hex) >= 2:
        auth_data += chr (int (hex[:2], 16))
        hex = hex[2:]
def pad (value):
    if len (value) % 4 != 0:
        return value + '\x00' * (4 - len (value) % 4)
    else:
        return value
x_socket.send (struct.pack ('!cxHHHHxx', 'B', 11, 0, len (auth_name), len (auth_data)) + pad (auth_name) + pad (auth_data))
data = x_socket.recv (1024)
if ord (data[0]) != 1:
    status_notify ('GREETER %s FAIL-CONNECT-XSERVER' % os.getenv ('DISPLAY'))
    exit (1)

status_notify ('GREETER %s CONNECT-XSERVER' % (os.getenv ('DISPLAY')))

def show_message_cb (greeter, text, type):
    status_notify ('GREETER %s SHOW-MESSAGE TEXT=\"%s\"' % (os.getenv ('DISPLAY'), text))

def show_prompt_cb (greeter, text, type):
    status_notify ('GREETER %s SHOW-PROMPT TEXT=\"%s\"' % (os.getenv ('DISPLAY'), text))

def authentication_complete_cb (greeter):
    if greeter.get_is_authenticated ():
        is_authenticated = 'TRUE'
    else:
        is_authenticated = 'FALSE'
    if greeter.get_authentication_user () is not None:
        status_notify ('GREETER %s AUTHENTICATION-COMPLETE USERNAME=%s AUTHENTICATED=%s' % (os.getenv ('DISPLAY'), greeter.get_authentication_user (), is_authenticated))
    else:
        status_notify ('GREETER %s AUTHENTICATION-COMPLETE AUTHENTICATED=%s' % (os.getenv ('DISPLAY'), is_authenticated))

def autologin_timer_expired_cb (greeter):
    status_notify ('GREETER %s AUTOLOGIN-TIMER-EXPIRED' % os.getenv ('DISPLAY'))

greeter = LightDM.Greeter ()
greeter.connect ('show-message', show_message_cb)
greeter.connect ('show-prompt', show_prompt_cb)
greeter.connect ('authentication-complete', authentication_complete_cb)
greeter.connect ('autologin-timer-expired', autologin_timer_expired_cb)

status_notify ('GREETER %s CONNECT-TO-DAEMON' % os.getenv ('DISPLAY'))
if not greeter.connect_sync ():
    status_notify ('GREETER %s FAIL-CONNECT-DAEMON' % os.getenv ('DISPLAY'))
    exit (1)

status_notify ('GREETER %s CONNECTED-TO-DAEMON' % os.getenv ('DISPLAY'))

if greeter.get_select_user_hint () is not None:
    status_notify ('GREETER %s SELECT-USER-HINT USERNAME=%s' % (os.getenv ('DISPLAY'), greeter.get_select_user_hint ()))
if greeter.get_lock_hint ():
    status_notify ('GREETER %s LOCK-HINT' % os.getenv ('DISPLAY'));

loop.run ()
