# plugs/lists.py
#
#

""" lists per global/channel/user """

__copyright__ = 'this file is in the public domain'

from gozerbot.commands import cmnds
from gozerbot.examples import examples
from gozerbot.plughelp import plughelp
from gozerbot.users import users
from gozerbot.persist import Persist
from gozerbot.datadir import datadir
from gozerbot.nextid import nextid
import os

plughelp.add('lists', 'maintain lists')

# indx, username, listname, txt
lists = Persist(datadir + os.sep + 'newlists')
if not lists.data:
    lists.data = {}

def size():
    """ return number of lists """
    return len(lists.data)

def getlists(username):
    """ return lists of username """
    try:
        return lists.data[username].keys()
    except KeyError:
        return []

def getlist(username, listname):
    """ get list of username """
    listname = listname.strip()
    try:
        return lists.data[username][listname]
    except KeyError:
        return []

def addtolist(username, listname, item):
    """ add item to list of username """
    listname = listname.strip()
    nid = nextid.next('lists')
    if not lists.data.has_key(username):
        lists.data[username] = {}
    if not lists.data[username].has_key(listname):
        lists.data[username][listname] = []
    lists.data[username][listname].append((nid, item))
    lists.save()

def mergelist(username, listname, itemlist):
    """ merge new list into existing list """
    listname = listname.strip()
    nidlist = nextid.nextlist('lists', len(itemlist))
    if not lists.data.has_key(username):
        lists.data[username] = {}
    if not lists.data[username].has_key(listname):
        lists.data[username][listname] = []
    t = 0
    for i in itemlist:
        nid = nidlist[t]
        lists.data[username][listname].append((nid, i[1]))
        t += 1
    lists.save()

def delfromlist(username, listname, index):
    """ remove item at index from list """
    listname = listname.strip()
    try:
        l = lists.data[username][listname]
    except KeyError:
        return
    for i in range(len(l)-1, -1, -1):
        if l[i][0] == index:
            del l[i]
            lists.save()
            return 1

def handle_listsglobal(bot, ievent):
    """ lists <listname> [',' <item>] .. global lists"""
    if not ievent.rest:
        ievent.missing("<listname> [',' <item>]")
        return
    try:
        listname, item = ievent.rest.split(',', 1)
    except ValueError:
        l = getlist('all', ievent.rest)
        if not l:
            ievent.reply('no %s list available or empty' % ievent.rest)
            return
        result = []
        for i in l:
            result.append("%s) %s" % (i[0], i[1]))
        ievent.reply(result)
        return
    listname = listname.strip().lower()
    item = item.strip()
    if not listname or not item:
        ievent.missing("<listname> [',' <item>]")
        return
    addtolist('all', listname, item)
    ievent.reply('%s added to %s list' % (item, listname))

cmnds.add('lists-global', handle_listsglobal, 'USER')
examples.add('lists-global', "lists-global <listname> [',' <item>] .. show \
content of list or add item to list", '1) lists-global bla 2) lists-global \
bla, mekker')

def handle_listsglobaldel(bot, ievent):
    """ list-globaldel <listname> ',' <listofnrs> .. remove items with \
indexnr from list """
    if not ievent.rest:
        ievent.reply('<listname> , <listofnrs>')
        return
    try:
        listname, nrs = ievent.rest.split(',', 1)
    except ValueError:
        ievent.missing('<listname> , <listofnrs>')
        return
    nrslist = []
    try:
        for i in nrs:
            nrslist.append(int(i))
    except ValueError:
        ievent.reply('%s is not an integer' % i)
        return
    nrslist.sort()
    failed = []
    itemsdeleted = 0
    for i in nrslist:
        if not delfromlist('all', listname, i):
            failed.append(i)
        else:
            itemsdeleted += 1
    if failed:
        ievent.reply('failed to delete %s .. %s item(s) deleted' % \
(str(failed), itemsdeleted))
        return
    ievent.reply('%s item(s) removed' % itemsdeleted)

cmnds.add('lists-globaldel', handle_listsglobaldel, 'USER')
examples.add('lists-globaldel', "lists-globaldel <listname> ',' <listofnrs> \
.. remove items with indexnr from list", '1) lists-globaldel mekker , 1 2) \
lists-globaldel mekker , 0 3 6')

def handle_listsglobalshow(bot, ievent):
    """ show avaiable global lists """
    l = getlists('all')
    if not l:
        ievent.reply('no lists available')
        return
    else:
        ievent.reply("global lists: ", l, dot=True)

cmnds.add('lists-globalshow', handle_listsglobalshow, 'USER')
examples.add('lists-globalshow', 'show available global lists' , \
'lists-globalshow')

def handle_listschan(bot, ievent):
    """ lists-chan <listname> [',' <item>] .. global lists"""
    if not ievent.rest:
        ievent.missing("<listname> [',' <item>]")
        return
    try:
        listname, item = ievent.rest.split(',', 1)
    except ValueError:
        l = getlist(ievent.channel, ievent.rest)
        if not l:
            ievent.reply('no %s list available or empty' % ievent.rest)
            return
        result = []
        for i in l:
            result.append("%s) %s" % (i[0], i[1]))
        ievent.reply(result)
        return
    listname = listname.strip().lower()
    item = item.strip()
    if not listname or not item:
        ievent.missing("<listname> [',' <item>]")
        return
    addtolist(ievent.channel, listname, item)
    ievent.reply('%s added to %s list' % (item, listname))

cmnds.add('lists-chan', handle_listschan, 'USER')
examples.add('lists-chan', "lists-chan <listname> [',' <item>] .. show \
content of list or add item to list", '1) lists-chan bla 2) lists-chan \
bla, mekker')

def handle_listschandel(bot, ievent):
    """ lists-chandel <listname> ',' <listofnrs> .. remove items with \
indexnr from list """
    if not ievent.rest:
        ievent.reply('<listname> , <listofnrs>')
        return
    try:
        listname, nrs = ievent.rest.split(',', 1)
    except ValueError:
        ievent.missing('<listname> , <listofnrs>')
        return
    nrslist = []
    try:
        for i in nrs:
            nrslist.append(int(i))
    except ValueError:
        ievent.reply('%s is not an integer' % i)
        return
    nrslist.sort()
    failed = []
    itemsdeleted = 0
    for i in nrslist:
        if not delfromlist(ievent.channel, listname, i):
            failed.append(i)
        else:
            itemsdeleted += 1
    if failed:
        ievent.reply('failed to delete %s .. %s item(s) deleted' % \
(str(failed), itemsdeleted))
        return
    ievent.reply('%s item(s) removed' % itemsdeleted)

cmnds.add('lists-chandel', handle_listschandel, 'USER')
examples.add('lists-chandel', "lists-chandel <listname> ',' <listofnrs> \
.. remove items with indexnr from list", '1) lists-chandel mekker , 1 2) \
lists-chandel mekker , 0 3 6')

def handle_listschanshow(bot, ievent):
    """ show avaiable lists """
    l = getlists(ievent.channel)
    if not l:
        ievent.reply('no lists available')
        return
    else:
        ievent.reply("channel lists: ", l, dot=True)

cmnds.add('lists-chanshow', handle_listschanshow, 'USER')
examples.add('lists-chanshow', 'show available channel lists' , \
'lists-chanshow')

def handle_lists(bot, ievent):
    """ lists <listname> [',' <item>] .. global lists"""
    if not ievent.rest:
        ievent.missing("<listname> [',' <item>]")
        return
    username = users.getname(ievent.userhost)
    try:
        listname, item = ievent.rest.split(',', 1)
    except ValueError:
        l = getlist(username, ievent.rest)
        if not l:
            ievent.reply('no %s list available or empty' % ievent.rest)
            return
        result = []
        for i in l:
            result.append("%s) %s" % (i[0], i[1]))
        ievent.reply(result)
        return
    listname = listname.strip().lower()
    item = item.strip()
    if not listname or not item:
        ievent.missing("<listname> [',' <item>]")
        return
    addtolist(username, listname, item)
    ievent.reply('%s added to %s list' % (item, listname))

cmnds.add('lists', handle_lists, 'USER')
examples.add('lists', "lists <listname> [',' <item>] .. show content of list \
or add item to list", '1) lists bla 2) lists bla, mekker')

def handle_listsdel(bot, ievent):
    """ lists-del <listname> ',' <listofnrs> .. remove items with indexnr \
from list """
    if not ievent.rest:
        ievent.missing('<listname> , <listofnrs>')
        return
    try:
        listname, nrs = ievent.rest.split(',', 1)
    except ValueError:
        ievent.missing('<listname> , <listofnrs>')
        return
    nrslist = []
    try:
        for i in nrs.split():
            nrslist.append(int(i))
    except ValueError:
        ievent.reply('%s is not an integer' % i)
        return
    username = users.getname(ievent.userhost)
    nrslist.sort()
    failed = []
    itemsdeleted = 0
    for i in nrslist:
        if not delfromlist(username, listname, i):
            failed.append(i)
        else:
            itemsdeleted += 1
    if failed:
        ievent.reply('failed to delete %s .. %s item(s) deleted' % \
(str(failed), itemsdeleted))
        return
    ievent.reply('%s item(s) removed' % itemsdeleted)

cmnds.add('lists-del', handle_listsdel, 'USER')
examples.add('lists-del', "lists-del <listname> ',' <listofnrs> \
.. remove items with indexnr from list", '1) lists-del mekker , 1 2) \
lists-del mekker , 0 3 6')

def handle_listshow(bot, ievent):
    """ show avaiable lists """
    username = users.getname(ievent.userhost)
    l = getlists(username)
    if not l:
        ievent.reply('no lists available')
        return
    else:
        ievent.reply("your lists: ", l, dot=True)

cmnds.add('lists-show', handle_listshow, 'USER')
examples.add('lists-show', 'show available channel lists' , 'lists-show')

def handle_listsmerge(bot, ievent):
    """ merge two lists """
    try:
        (fromlist, tolist) = ievent.args
    except ValueError:
        ievent.missing('<fromlist> <tolist>')
        return
    username = users.getname(ievent.userhost)
    l = getlist(username, fromlist)
    if not l:
        ievent.reply('no %s list exists' % fromlist)
        return
    try:
        mergelist(username, tolist, l)
    except Exception, ex:
        ievent.reply('error: %s' % str(ex))
        return
    ievent.reply('%s items merged' % len(l))

cmnds.add('lists-merge', handle_listsmerge, 'USER')
examples.add('lists-merge', 'merge 2 lists (users lists only)', \
'lists-merge mekker miep')
