# plugs/jcoll.py
#
#

""" jabber collective """

from gozerbot.callbacks import jcallbacks
from gozerbot.generic import lockdec, waitforqueue, rlog
from gozerbot.plughelp import plughelp
from gozerbot.commands import cmnds
from gozerbot.persist import Persist
from gozerbot.plugins import plugins
from gozerbot.datadir import datadir
from gozerbot.dol import Dol
from gozerbot.config import config
from gozerbot.users import users
from gozerbot.thr import start_new_thread
if config['jabberenable']:
    from gozerbot.jabbermsg import Jabbermsg
import os, Queue, time, thread, random


plughelp.add('jcoll', 'the jcoll plugin implements the jabber collective .. \
a way to query other jabber bots (so far untested)')

jcoll = Persist(datadir + os.sep + 'jcoll')

if not jcoll.data:
    jcoll.data = {}
if not jcoll.data.has_key('enable'):
    jcoll.data['enable'] = 1
if not jcoll.data.has_key('jidlist'):
    jcoll.data['jidlist'] = []
if not jcoll.data.has_key('allowlist'):
    jcoll.data['allowlist'] = []

jcollqueues = {}
jcollcounts = {}

def jcheck(bot, msg):
    """ check if message is ment for the jabber collective """
    rlog(0, 'jcoll', 'checking %s' % msg.userhost)
    if 'dojcoll' in str(msg.id) and msg.stripped in jcoll.data['allowlist']:
        if plugins.woulddispatch(bot, msg):
            rlog(10, 'jcoll', 'starting jcoll dispatch %s %s' % \
(msg.userhost, msg.txt))
            msg.id = str(msg.id)[2:]
            start_new_thread(plugins.trydispatch, (bot, msg))
            return
    if 'jcoll' in str(msg.id) and msg.stripped in jcoll.data['jidlist']:
        if jcollqueues.has_key(msg.id):
            try:
                jcollcounts[msg.id] += 1
            except IndexError:
                jcollcounts[msg.id] = 1
            rlog(10, 'rcoll', 'adding to %s queue' % msg.id)
            jcollqueues[msg.id].put_nowait((msg.nick, msg.txt))
            if jcollcounts[msg.id] >= len(jcoll.data['jidlist']):
                jcollqueues[msg.id].put_nowait(None)
            
jcolllock = thread.allocate_lock()
locked = lockdec(jcolllock)

def init():
    """ init the jabber collective """
    if not config['jabberenable']:
        return 0
    if not jcoll.data['enable']:
        return 0
    cmnds.add('jcoll-enable', handle_jcollenable, 'OPER')
    cmnds.add('jcoll-disable', handle_jcolldisable, 'OPER')
    cmnds.add('jcoll-add', handle_jcolladd, 'OPER')
    cmnds.add('jcoll-del', handle_jcolldel, 'OPER')
    cmnds.add('jcoll-list', handle_jcolllist, 'OPER')
    cmnds.add('jcoll-allow', handle_jcollallow, 'OPER')
    cmnds.add('jcoll-deny', handle_jcolldeny, 'OPER')
    cmnds.add('jcoll', handle_jcoll, 'USER')
    jcallbacks.add('Message', jcheck)
    return 1

def handle_jcollenable(bot, msg):
    """ enable the jabber collective """
    jcoll.data['enable'] = True
    jcoll.save()
    msg.reply('jabber collective is enabled')

def handle_jcolldisable(bot, msg):
    """ disable the jabber collective """
    jcoll.data['enable'] = False
    jcoll.save()
    plugins.reload('gozerplugs.plugs', 'jcoll')
    msg.reply('jabber collective is disabled')

def handle_jcolladd(bot, msg):
    """ add a node to the jabber collective """
    try:
        jid = msg.args[0]
    except IndexError:
        msg.missing('<jid>')
        return
    if jid not in jcoll.data['jidlist']:
        jcoll.data['jidlist'].append(jid)
        jcoll.save()
        msg.reply('%s added' % jid)
    else:
        msg.reply('%s is already in jidlist' % jid)

def handle_jcolldel(bot, msg):
    """ delete a node from the jabber collective """
    try:
        jid = msg.args[0]
    except IndexError:
        msg.missing('<jid>')
        return
    if jid in jcoll.data['jidlist']:
        jcoll.data['jidlist'].remove(jid)
        jcoll.save()
        msg.reply('%s removed' % jid)
    else:
        msg.reply('%s is not in jidlist' % jid)

def handle_jcollallow(bot, msg):
    """ allow a jid access to the jabber collective """
    try:
        jid = msg.args[0]
    except IndexError:
        msg.missing('<jid>')
        return
    if jid not in jcoll.data['allowlist']:
        jcoll.data['allowlist'].append(jid)
        if not users.getname(jid):
            users.add(jid, [jid, ], ['JCOLL', ])
        jcoll.save()
        msg.reply('%s added' % jid)
    else:
        msg.reply('%s is already in allowlist' % jid)

def handle_jcolldeny(bot, msg):
    """ deny a jid access to jabber collective  """
    try:
        jid = msg.args[0]
    except IndexError:
        msg.missing('<jid>')
        return
    if jid in jcoll.data['allowlist']:
        jcoll.data['allowlist'].remove(jid)
        users.delete(jid)
        jcoll.save()
        msg.reply('%s removed' % jid)
    else:
        msg.reply('%s is not in allowlist' % jid)

def handle_jcolllist(bot, msg):
    """ list allowed and jid lists """
    msg.reply("jid: %s allow: %s" % (jcoll.data['jidlist'], \
jcoll.data['allowlist']))

@locked
def handle_jcoll(bot, msg):
    """ do a query on the jabber collective """
    global jcollqueues
    cmnd = msg.rest
    id = 'jcoll' + str(random.randint(10000, 20000))
    for i in jcoll.data['jidlist']:
        jmsg = Jabbermsg(msg)
        jmsg.toirc(bot)
        jmsg.setType('chat')
        jmsg.setTo(i)
        jmsg.setID('do' + id)
        jmsg.setBody(cmnd)
        bot.send(jmsg)
    resultlist = []
    total = len(jcoll.data['jidlist'])
    starttime = time.time()
    teller = 0
    got = Dol()
    q = jcollqueues[id] = Queue.Queue()
    result = waitforqueue(q, 5)
    for i in result:
        got.add(i[1], i[0])
    for i, j  in got.iteritems():
        count = 0
        for z in j:
            count += 1
            teller += 1
            if count > 1:
                nodestxt = "-||(%s nodes)||-" % count
            else:
                nodestxt = "-||%s||-" % z
        resultlist.append("%s %s" % (nodestxt, i))
    if resultlist:
        resultlist.insert(0, '%s out of %s (%s)' % (teller, total, \
        time.time() - starttime))
        msg.reply(resultlist)
    else:
        msg.reply('no results found')
    del jcollqueues[id]
