#! /usr/bin/env python

import os
import sys
import tempfile

RINGTONED = '/usr/bin/ringtoned'
POLICY_FILE = '/usr/share/policy/etc/rx51/syspart.conf'
GROUP = 'telephony'

_app_name = sys.argv[0]

_syntax = '''\
%s add|remove|query

add
    Add ringtoned to the telephony cgroup, so it's not frozen during the
    processing of incoming calls.
    (Takes effect after a reboot.)
add-ui
    Like "add", but if ringtoned wasn't yet in the right cgroup it will
    ask the user to reboot the phone.
remove
    Remove ringtoned from the telephony cgroup, this means it will be
    frozen for a couple of seconds when a call is received.
    (Takes effect after a reboot.)
query
    Prints on screen whether ringtoned is in the telephony cgroup or
    not.
'''

def syntax(exit_code=0):
    if exit_code == 0:
        stream = sys.stdout
    else:
        stream = sys.stderr

    stream.write(_syntax % _app_name)

    raise SystemExit(exit_code)

def error(msg, fatal=True):
    sys.stderr.write(msg)
    sys.stderr.write('\n')

    if fatal:
        raise SystemExit(1)

def parse_config():
    content = []
    start = -1
    end = -1

    try:
        conf = open(POLICY_FILE, 'r')
    except IOError, e:
        error('Cannot parse policy file: %s' % e)

    for i, line in enumerate(conf.readlines()):
        content.append(line)

        if start == -1 and line.strip() == '[classify ' + GROUP + ']':
            start = i + 1
        elif end == -1 and start != -1 and line.startswith('['):
            end = i - 1

    if start < 0:
        error('Cannot find the "' + GROUP + '" group')

    if end < 0:
        end = len(content) -1

    while content[end].strip() == '' and end > start:
        end -= 1

    ringtoned_pos = -1
    for i in range(start, end + 1):
        if content[i].strip() == RINGTONED:
            ringtoned_pos = i
            break

    return content, start, end, ringtoned_pos

def save_config(content):
    out_fd, tmp_path = tempfile.mkstemp(dir='/var/tmp')
    assert out_fd >= 0

    data = ''.join(content)
    out = os.fdopen(out_fd, 'wb')
    out.write(data)
    out.close()

    try:
        os.rename(tmp_path, POLICY_FILE)
    except OSError, e:
        try:
            os.remove(tmp_path)
        except OSError:
            pass
        error ('Cannot write the policy file: %s' % e)

    print 'Policy file updated, the change will take effect after a reboot'

def add():
    content, start, end, ringtoned_pos = parse_config()

    if ringtoned_pos >= 0:
        print 'Ringtoned is already in the "' + GROUP + \
                '" group, cannot add it again'
        return False

    content.insert(end + 1, RINGTONED + '\n')
    save_config(content)

    return True

def add_ui():
    if add():
        msg = 'A reboot of the phone is recommended to make custom ' \
                'ringtones work correctly.'
        # Sorry, I'm very lazy...
        os.system('run-standalone.sh dbus-send --type=method_call '
                '--dest=org.freedesktop.Notifications '
                '/org/freedesktop/Notifications '
                'org.freedesktop.Notifications.SystemNoteDialog '
                'string:"%s" uint32:0 string:"Ok"' %msg)

def remove():
    content, start, end, ringtoned_pos = parse_config()

    if ringtoned_pos < 0:
        print 'Ringtoned is not in the "' + GROUP + \
                '" group, cannot remove it'
        return False

    del content[ringtoned_pos]
    save_config(content)

    return True

def query():
    content, start, end, ringtoned_pos = parse_config()

    if ringtoned_pos >= 0:
        print 'Ringtoned is already in the "' + GROUP + '" group'
    else:
        print 'Ringtoned is NOT in the "' + GROUP + '" group'

def main(argv):
    _app_name = argv[0]

    if len(argv) < 2:
        syntax(1)

    actions = {'add':    add,
               'add-ui': add_ui,
               'remove': remove,
               'query':  query,
               '-h':     syntax,
               '--help': syntax,
               'help':   syntax}

    if argv[1] in actions:
        actions[argv[1]]()
    else:
        error('Unknown command %s\n\n' % argv[1], False)
        syntax(1)

if __name__ == '__main__':
    main(sys.argv)
