##
##   lts.conf dictionary
##
##   Copyright (C) 2007 Canonical Ltd.
##
##   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 2, 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.

"""
ltsconf_dict is a module to validate lts.conf values and to detect 
all possible values in a ltsp chroot

Copyright 2007, Canonical Ltd.
"""

import os
from subprocess import Popen,PIPE

__all__='keymaps','kbmodels','videodrivers','serproto','isboolean','validate'

valid = ['SOUND',
        'SOUND_DAEMON',
        'LOCALDEV',
        'DNS_SERVER',
        'SEARCH_DOMAIN',
        'CONSOLE_KEYMAP',
        'NBD_SWAP',
        'SWAP_SERVER',
        'NBD_PORT',
        'USE_LOCAL_SWAP',
        'PRINTER_0_DEVICE',
        'PRINTER_0_TYPE',
        'PRINTER_0_PORT',
        'PRINTER_0_WRITE_ONLY',
        'PRINTER_0_SPEED',
        'PRINTER_0_FLOWCTRL',
        'PRINTER_0_PARITY',
        'PRINTER_0_DATABITS',
        'PRINTER_0_OPTIONS',
        'USE_XFS',
        'XFS_SERVER',
        'XKBLAYOUT',
        'XKBMODEL',
        'XKBRULES',
        'XKBOPTIONS',
        'XKBVARIANT',
        'NETWORK_COMPRESSION',
        'LDM_REMOTECMD',
        'RCFILE_nn',
        'SCREEN_nn',
        'SERVER',
        'SYSLOG_HOST',
        'MODULE_nn',
        'XF86CONFIG_FILE',
        'XSERVER',
        'X_HORZSYNC',
        'X_VERTREFRESH',
        'X_COLOR_DEPTH',
        'X_MOUSE_DEVICE',
        'X_MOUSE_PROTOCOL',
        'X_MOUSE_EMULATE3BTN',
        'TELNET_HOST',
        'XDM_SERVER']

boolean=['SOUND',
        'LOCALDEV',
        'NBD_SWAP',
        'USE_LOCAL_SWAP',
        'USE_XFS',
        'NETWORK_COMPRESSION',
        'X_MOUSE_EMULATE3BTN']

def keymaps(root):
    """
    returns an array of available X keymaps in root

    root: a full ltsp client chroot path, i.e. /opt/ltsp/i386
    """
    res=[]
    for keymap in os.listdir(root+'/etc/X11/xkb/keymap/'):
        if keymap == 'README':
            continue
        try:
            keymap_file = file(os.path.join(root, 'etc/X11/xkb/keymap',keymap))
        except:
            continue
        else:
            for line in keymap_file:
                if line.find('xkb_keymap') >= 0:
                    res.append(line.split('"')[1])
    return unique(res)

def kbmodels(root):
    """
    returns an array of known X keyboard models in root
    
    root: a full ltsp client chroot path, i.e. /opt/ltsp/i386
    """
    ret = []
    for kbmodel in os.listdir(root+'/etc/X11/xkb/geometry/'):
        if kbmodel == 'README':
            continue
        try:
            kbmodel_file = file(os.path.join(root, 'etc/X11/xkb/geometry',kbmodel))
        except:
            continue
        else:
            for line in kbmodel_file:
                if line.find('xkb_geometry') >= 0:
                    ret.append(line.split('"')[1])
    return ret

def videodrivers(root):
    """
    returns an array of known X drivers in root
    
    root: a full ltsp client chroot path, i.e. /opt/ltsp/i386
    """
    ret=[]
    cardlist = os.listdir(os.path.join(root, 'usr/lib/xorg/modules/drivers'))
    for item in cardlist:
        if item.find('.so') >= 0:
                ret.append(item.split('.')[0].split('_drv')[0])
    print ret

def serproto(root):
    """
    returns an array of known serial mouse protocol options in root
    
    root: a full ltsp client chroot path, i.e. /opt/ltsp/i386
    """
    ret = []
    modelist = Popen(root+'/usr/sbin/inputattach --help', shell=True, bufsize=1024, stdout=PIPE).stdout
    for line in modelist:
        if line.lstrip().startswith('--'):
            ret.append(line.lstrip('  --').split()[0])
    return ret

def unique(s):
             n = len(s)
             if n == 0:
                     return []
             u = {}
             try:
                     for x in s:
                             u[x] = 1
             except TypeError:
                     del u  # move on to the next method
             else:
                     return u.keys()
             
             try:
                     t = list(s)
                     t.sort()
             except TypeError:
                     del t  # move on to the next method
             else:
                     assert n > 0
                     last = t[0]
                     lasti = i = 1
                     while i < n:
                             if t[i] != last:
                                     t[lasti] = last = t[i]
                                     lasti += 1
                             i += 1
                     return t[:lasti]
             
             # Brute force is all that's left.
             u = []
             for x in s:
                     if x not in u:
                             u.append(x)
             return u

def isboolean(var):
    """
    returns True if var is a valid variable for lts.conf

    var: variable name (i.e. 'SOUND')
    """
    if var in boolean:
        return True
    return False

def validate(var):
    """
    returns true if var is a valid variable for lts.conf

    var: variable name (i.e. 'SOUND')
    """
    if var in valid:
        return True
    return False
