#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function

##################

def_away = 30
def_na = 60
def_poll = 3 * 60

# http://developer.pidgin.im/wiki/DbusHowto
from collections import namedtuple
status = namedtuple('Status', ' '.join((
	'offline', 'available', 'unavailable', 'invisible',
	'away', 'xaway', 'mobile', 'tune' )))(*xrange(1, 9))

##################


from optparse import OptionParser
parser = OptionParser(usage='%prog [options]',
	description='Set pidgin status according to idle time')

parser.add_option('-p', '--poll-interval',
	action='store', dest='poll',
	type='int', metavar='SEC', default=def_away,
	help='Minimal interval between idle time checks (default: {0})'.format(def_poll))
parser.add_option('-a', '--away',
	action='store', dest='away',
	type='int', metavar='MINUTES', default=def_away,
	help='Timeout to set Away status (default: {0})'.format(def_away))
parser.add_option('-n', '--na',
	action='store', dest='na',
	type='int', metavar='MINUTES', default=def_na,
	help='Timeout to set N/A (extended away) status (default: {0})'.format(def_na))

parser.add_option('--debug',
	action='store_true', dest='debug',
	help='Verbose mode.')
optz, argz = parser.parse_args()

if argz: parser.error('This command takes no arguments.')
if optz.away >= optz.na: parser.error('Away timeout must be higher than N/A.')
optz.away *= 60
optz.na *= 60

import logging
logging.basicConfig(level=(logging.DEBUG if optz.debug else logging.WARNING))
log = logging.getLogger('pidgin_status_control')


from subprocess import Popen, PIPE
status_name = lambda st_type: next(
	name for name,idx in it.izip(status._fields, status) if idx == st_type )

def get_idle():
	proc = Popen(['xprintidle'], stdout=PIPE)
	idle = int(proc.stdout.read().strip()) // 1000
	proc.wait()
	return idle


import itertools as it, functools as ft, operator as op
import os, sys, dbus
from time import sleep


def status_loop():
	while True:
		idle = get_idle()
		if idle > optz.away:
			if idle > optz.na:
				iface.PurpleSavedstatusActivate(st_na)
				log.debug('Switched status to N/A (idle: {0})'.format(idle//60))
			else:
				iface.PurpleSavedstatusActivate(st_away)
				log.debug('Switched status to away (idle: {0})'.format(idle//60))
			sleep(optz.poll)
		else:
			if iface.PurpleSavedstatusGetType(
					iface.PurpleSavedstatusGetCurrent() ) in (status.away, status.xaway):
				iface.PurpleSavedstatusActivate(st)
				log.debug('Restored original status (idle: {0})'.format(idle//60))
			sleep(optz.away)


while True:
	try:
		pidgin = dbus.SessionBus().get_object(
			'im.pidgin.purple.PurpleService', '/im/pidgin/purple/PurpleObject' )
	except dbus.exceptions.DBusException:
		log.debug('Pidgin doesnt seem to be running')
		sleep(optz.away) # no need to check earlier
		continue
	else: iface = dbus.Interface(pidgin, 'im.pidgin.purple.PurpleInterface')

	st = iface.PurpleSavedstatusGetCurrent()
	st_type = iface.PurpleSavedstatusGetType(st)
	st_msg = iface.PurpleSavedstatusGetMessage(st)
	log.debug('Initial status: {0}, "{1}"'.format(status_name(st_type), st_msg))

	st_away = iface.PurpleSavedstatusNew('', status.away)
	iface.PurpleSavedstatusSetMessage(
		st_away, 'AFK (>{0}m)'.format(optz.away // 60) )
	st_na = iface.PurpleSavedstatusNew('', status.xaway)
	iface.PurpleSavedstatusSetMessage(
		st_na, 'AFK for quite a while (>{0}m)'.format(optz.na // 60) )

	try: status_loop()
	except dbus.exceptions.DBusException: pass # pidgin died

