# IrcAdmin - handle normal IRC functions one would expect
# Copyright (C) 2010  Brian S. Stephan
#
# 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 3 of the License, 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.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

from ConfigParser import NoOptionError
import signal
import sys

from extlib import irclib

from Module import Module

# All kinds of miscellaneous irc stuff

class IrcAdmin(Module):

    def register_handlers(self, server):
        server.add_global_handler('welcome', self.on_connect)
        server.add_global_handler('pubmsg', self.on_pubmsg)
        server.add_global_handler('privmsg', self.on_privmsg)

        # we define save, so we'll bite the bullet and take SIGINT
        signal.signal(signal.SIGINT, self.sigint_handler)

    def unregister_handlers(self):
        self.server.remove_global_handler('welcome', self.on_connect)
        self.server.remove_global_handler('pubmsg', self.on_pubmsg)
        self.server.remove_global_handler('privmsg', self.on_privmsg)

    def on_connect(self, connection, event):
        """handler for when the bot has connected to IRC
        """

        # user modes
        try:
            nick = self.config.get('dr.botzo', 'nick')
            usermode = self.config.get('dr.botzo', 'usermode')
            connection.mode(nick, usermode)
        except NoOptionError: pass

        # join the specified channels
        try:
            autojoins = self.config.get(self.__class__.__name__, 'autojoin').split(',')
            for channel in autojoins:
                if irclib.is_channel(channel):
                    connection.join(channel)
        except NoOptionError: pass

    def do(self, connection, event, nick, userhost, replypath, what, admin_unlocked):
        # this could be more sophisticated, but i'm too lazy to do a real port
        # right now.
        # TODO: sophisticate. also, document all of these
        self.sub_join_channel(connection, event, nick, userhost, replypath, what, admin_unlocked)
        self.sub_part_channel(connection, event, nick, userhost, replypath, what, admin_unlocked)
        self.sub_quit_irc(connection, event, nick, userhost, replypath, what, admin_unlocked)
        self.sub_autojoin_manipulate(connection, event, nick, userhost, replypath, what, admin_unlocked)
        self.sub_save_config(connection, event, nick, userhost, replypath, what, admin_unlocked)
        self.sub_change_nick(connection, event, nick, userhost, replypath, what, admin_unlocked)

    def sub_join_channel(self, connection, event, nick, userhost, replypath, what, admin_unlocked):
        whats = what.split(' ')
        if whats[0] == 'join' and admin_unlocked and len(whats) >= 2:
            channel = whats[1]
            if irclib.is_channel(channel):
                connection.join(channel)
                replystr = 'joined ' + channel
                return self.reply(connection, replypath, replystr)

    def sub_part_channel(self, connection, event, nick, userhost, replypath, what, admin_unlocked):
        whats = what.split(' ')
        if whats[0] == 'part' and admin_unlocked and len(whats) >= 2:
            channel = whats[1]
            if irclib.is_channel(channel):
                connection.part(channel, ' '.join(whats[2:]))
                replystr = 'parted ' + channel
                return self.reply(connection, replypath, replystr)

    def sub_quit_irc(self, connection, event, nick, userhost, replypath, what, admin_unlocked):
        whats = what.split(' ')
        if whats[0] == 'quit' and admin_unlocked:
            if replypath is not None:
                connection.privmsg(replypath, 'quitting')
            connection.quit(' '.join(whats[1:]))
            self.save_config()
            sys.exit()

    def sub_autojoin_manipulate(self, connection, event, nick, userhost, replypath, what, admin_unlocked):
        whats = what.split(' ')
        if whats[0] == 'autojoin' and admin_unlocked and len(whats) >= 3:
            if whats[1] == 'add':
                try:
                    # get existing list
                    channel = whats[2]
                    if irclib.is_channel(channel):
                        channelset = set(self.config.get(self.__class__.__name__, 'autojoin').split(','))
                        channelset.add(channel)
                        self.config.set(self.__class__.__name__, 'autojoin', ','.join(channelset))
                        replystr = 'added ' + channel + ' to autojoin'
                        return self.reply(connection, replypath, replystr)
                except NoOptionError: pass
            elif whats[1] == 'remove':
                try:
                    # get existing list
                    channel = whats[2]
                    if irclib.is_channel(channel):
                        channelset = set(self.config.get(self.__class__.__name__, 'autojoin').split(','))
                        channelset.discard(channel)
                        self.config.set(self.__class__.__name__, 'autojoin', ','.join(channelset))
                        replystr = 'removed ' + channel + ' from autojoin'
                        return self.reply(connection, replypath, replystr)
                except NoOptionError: pass

    def sub_save_config(self, connection, event, nick, userhost, replypath, what, admin_unlocked):
        whats = what.split(' ')
        if whats[0] == 'config' and whats[1] == 'save' and admin_unlocked:
            with open('dr.botzo.cfg', 'w') as cfg:
                self.config.write(cfg)
            replystr = 'saved config file'
            return self.reply(connection, replypath, replystr)

    def sub_change_nick(self, connection, event, nick, userhost, replypath, what, admin_unlocked):
        whats = what.split(' ')
        if whats[0] == 'nick' and admin_unlocked and len(whats) >= 2:
            newnick = whats[1]
            connection.nick(newnick)
            self.config.set('dr.botzo', 'nick', newnick)
            replystr = 'changed nickname'
            return self.reply(connection, replypath, replystr)

    # Save the config file.
    def save_config(self):
        with open('dr.botzo.cfg', 'w') as cfg:
            self.config.write(cfg)

    # SIGINT signal handler
    def sigint_handler(self, signal, frame):
        self.save_config()
        print('saved config')
        sys.exit()

# vi:tabstop=4:expandtab:autoindent
# kate: indent-mode python;indent-width 4;replace-tabs on;