#!/usr/bin/env python2
 
#  Gnome15 - Suite of tools for the Logitech G series keyboards and headsets
#  Copyright (C) 2011 Brett Smith <tanktarta@blueyonder.co.uk>
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <http://www.gnu.org/licenses/>.

"""
DBUS System Service that is intended to replace 'lgsetled', the command line tool initially
used by the kernel driver support to set the brightness of keyboard lights (the device
files of which require root access, as they are in /sys). 
"""

import sys
import os
import glib

# Allow running from local path
path = os.path.abspath(os.path.join(os.path.abspath(os.path.dirname(__file__)), ".."))
if os.path.exists(path):
    sys.path.insert(0, path) 

# Logging
import gnome15.g15logging as g15logging
logger = g15logging.get_root_logger()

# Allow running from local path
path = os.path.abspath(os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])), ".."))
if os.path.exists(path):
    sys.path.insert(0, path) 
    
#
import gobject
gobject.threads_init()

import gconf
import gnome15.g15drivermanager as g15drivermanager
import gnome15.g15devices as g15devices
import gnome15.g15uinput as g15uinput
import gnome15.g15driver as g15driver
import termios, sys, os

TERMIOS = termios
conf_client = gconf.client_get_default()

def getkey():
    fd = sys.stdin.fileno()
    old = termios.tcgetattr(fd)
    new = termios.tcgetattr(fd)
    new[3] = new[3] & ~TERMIOS.ICANON & ~TERMIOS.ECHO
    new[6][TERMIOS.VMIN] = 1
    new[6][TERMIOS.VTIME] = 0
    termios.tcsetattr(fd, TERMIOS.TCSANOW, new)
    c = None
    try:
        c = os.read(fd, 1)
    finally:
        termios.tcsetattr(fd, TERMIOS.TCSAFLUSH, old)
    return c

def list_drivers():
    for driver in g15drivermanager.imported_drivers.values():
        print "Id: %s" % driver.id
        print "\tName: %s" % driver.name
        print "\tDescription: %s" % driver.description

def list_devices():
    for device in g15devices.find_all_devices():
        print "UID: %s" % device.uid
        print "\tModel: %s" % device.model_id
        print "\tUSB ID: 0x%0.4x:0x%0.4x" % ( device.controls_usb_id[0], device.controls_usb_id[1] )
        print "\tLCD BPP: %d" % ( device.bpp )
        print "\tLCD Size: %s" % ( str(device.lcd_size) )
        driver, reconfigured = get_driver(device)
        if driver is None:
            print "\tConfigured Driver: None found"
        else:
            driver_mod = sys.modules[driver.__module__]
            if reconfigured:
                print "\tConfigured Driver: %s (%s) [Next best, configured driver not available]" % ( driver_mod.id, driver_mod.name )
            else:
                print "\tConfigured Driver: %s (%s)" % ( driver_mod.id, driver_mod.name )
            print "\t\tName: %s" % driver.get_name()
            print "\t\tModel: %s" % driver.get_model_name()
            print "\t\tSupported Models: %s" % driver.get_model_names()
            print "\t\tBPP: %s" % driver.get_bpp()
            print "\t\tAntialias: %s" % driver.get_antialias()
            
def get_driver(device):
    reconfigured = False
    try:        
        driver = g15drivermanager.get_driver(conf_client, device)
    except:
        driver = g15drivermanager.get_best_driver(conf_client, device)
        reconfigured = True
    return driver, reconfigured

def _check_hint(hint, value, name, list):
    if value & hint:
        list.append(name)

def controls(uid):
    g15uinput.open_devices()
    device = g15devices.get_device(uid)    
    driver, reconfigured = get_driver(device)
    if driver is None:
        raise Exception("No driver for device with UID of %s." % uid)
    
    for c in driver.get_controls():
        print "%s" % c.id
        print "\tName: %s" % c.name
        print "\tLower: %s" % str(c.lower)
        print "\tHigher: %s" % str(c.upper)
        print "\tValue: %s" % str(c.value)
        print "\tDefault Value: %s" % str(c.default_value)
        hint_names = []
        _check_hint(g15driver.HINT_DIMMABLE, c.hint, "Dimmable", hint_names)
        _check_hint(g15driver.HINT_SHADEABLE, c.hint, "Shadeable", hint_names)
        _check_hint(g15driver.HINT_FOREGROUND, c.hint, "Foreground", hint_names)
        _check_hint(g15driver.HINT_BACKGROUND, c.hint, "Background", hint_names)
        _check_hint(g15driver.HINT_HIGHLIGHT, c.hint, "Highlight", hint_names)
        _check_hint(g15driver.HINT_SWITCH, c.hint, "Switch", hint_names)
        _check_hint(g15driver.HINT_MKEYS, c.hint, "MKeys", hint_names)
        _check_hint(g15driver.HINT_VIRTUAL, c.hint, "Virtual", hint_names)
        _check_hint(g15driver.HINT_RED_BLUE_LED, c.hint, "Red/Blue", hint_names)
        print "\tHints: %s" % ",".join(hint_names)
        
def keytest(uid):
    g15uinput.open_devices()
    device = g15devices.get_device(uid)
    if uid is None:
        raise Exception("No device with UID of %s." % uid)
    driver, reconfigured = get_driver(device)
    if driver is None:
        raise Exception("No driver for device with UID of %s." % uid)
    driver.connect()
    print "Connected, now monitoring macro keys"
    driver.grab_keyboard(handle_key)
    print "Press any standard key to stop monitoring macro keys"
    getkey()
    driver.disconnect()
    
def handle_key(keys, state):
    print "Keys: %s, State: %d" % (keys, state)

if __name__ == "__main__":
    import optparse
    parser = optparse.OptionParser()
    parser.add_option("-l", "--log", dest="log_level", metavar="INFO,DEBUG,WARNING,ERROR,CRITICAL",
        default="warning" , help="Log level")
    (options, args) = parser.parse_args()
    
    if len(args) == 0:
        print "No command"
        sys.exit(1)
        
    if args[0] == "devices":
        list_devices()
    elif args[0] == "drivers":
        list_drivers()
    elif args[0] == "keytest":
        del args[0]
        if len(args) == 0:
            print "No device UID specified. Use 'g15-diag devices' to show devices"
            sys.exit(1)
        keytest(args[0])
    elif args[0] == "controls":
        del args[0]
        if len(args) == 0:
            print "No device UID specified. Use 'g15-diag devices' to show devices"
            sys.exit(1)
        controls(args[0])
    elif args[0] == "control":
        del args[0]
        if len(args) == 0:
            print "No device UID specified. Use 'g15-diag devices' to show devices"
            sys.exit(1)
        device = arg[0]
        del args[0]
        if len(args) == 0:
            print "No control ID specified. Use 'g15-diag controls <device>' to show controls"
            sys.exit(1)
        control(device, args[0])
