import fnmatch
from irc.modes import parse_channel_modes
from common.networkservices import ChanServ
from common import do_everything_to, userstatus, log
from events.common import Aggressiveness, Lastact

bold = "\x02"
italic = "\x1D"
underline = "\x1F"
reverse = "\x16" 	# swap background and foreground colors ("reverse video")
reset = "\x0F"
blue = "\x0302"
green = "\x0303"
red = "\x0304"
grey = "\x0314"

def process_event(self, connection, event):
    log.info(event)
    
    # Update protectees.
    if event.target == self.homechannel:    # Home channel
        if any(mode in event.arguments[0][-1:] for mode in ("q", "a", "o", "h")):  # Atleast halfop.
            connection.who(event.arguments[1])  # Get whorepy to update protectees.
    
    # Update last act.
    Lastact.update(self, event.source.nick, "mode", lastact=event.target)
    
    # React.
    modes = parse_channel_modes(" ".join(event.arguments))
    behaviour = self.db.one("SELECT aggressiveness FROM channels WHERE name='" + event.target + "' AND network='" + self.network + "'")
    for idx, mode in enumerate(modes):
        
        # Report.
        if not event.target == self.homechannel:    # Not in home channel.
            for protectee in self.protectees:
                if mode[1] == "b" and fnmatch.fnmatch(self.protectees[protectee]['ident'], mode[2]) and mode[0] == "+":   # Protectee banned.
                    connection.privmsg(self.homechannel, red + protectee + reset + " banned from " + red + event.target + reset + " by " + red + event.source.nick + reset + ": " + green + mode[2])

                if mode[1] == "e" and fnmatch.fnmatch(self.protectees[protectee]['ident'], event.arguments[idx + 1]) and mode[0] == "-":   # Protectee's exception removed.
                    connection.privmsg(self.homechannel, red + protectee + reset + " has had their exception removed from " + red + event.target + reset + " by " + red + event.source.nick + reset + ": " + green + event.arguments[idx + 1])
    
        # Track channel keys.
        if mode[1] == "k":  # Channel key changed.
            if mode[0] == "+":  # Key set.
                self.db.run("UPDATE channels SET key='" + mode[2] + "' WHERE name='" + event.target + "' AND network='" + self.network + "'")
            else:   # Key removed.
                self.db.run("UPDATE channels SET key=NULL WHERE name='" + event.target + "' AND network='" + self.network + "'")
        
        # Unban if bot is banned from home channel
        if mode[1] == "b" and fnmatch.fnmatch(self.protectees[connection.get_nickname()]['ident'], mode[2]) and mode[0] == "+" and event.target == self.homechannel:
            connection.privmsg("ChanServ", "UNBAN")
            do_everything_to.unban(connection, event.target, connection.get_nickname(), mode[2])
            connection.mode(event.target, "-b " + mode[2])
        
        # Stop if not present in home channel.
        if not self.homechannel in self.channels:
            return
        
        # Stop if offender is bot or bot owner
        if event.source.nick == connection.get_nickname() or self.channels[self.homechannel].is_owner(event.source.nick):
            return
        
        for protectee in self.protectees:
            
            # Stop if offender is atleast halfop in the home channel and offended is not owner.
            if userstatus.atleast_halfop(self, event.source.nick, self.homechannel) and not self.channels[self.homechannel].is_owner(protectee):
                return
            
            try:    # Had "IndexError: list index out of range" on "if modes[1] == "b" and mode[0] == "+":  # Ban.".
                if behaviour == "passive":    # Passive behaviour.
                    return
                elif behaviour == "defense_only":   # Defensive only behaviour.
                    if mode[1] == "b" and mode[0] == "+":  # Ban.
                        if fnmatch.fnmatch(self.protectees[protectee]['ident'], mode[2]):  # Protectee.
                            do_everything_to.unban(connection, event.target, protectee, mode[2])
                    elif mode[1] == "e" and mode[0] == "-":  # Removed exception.
                        if fnmatch.fnmatch(self.protectees[protectee]['ident'], event.arguments[idx + 1]):  # Protectee.
                            connection.mode(event.target, "+e " + mode[2])
                    elif mode[0] == "-" and mode[1] in ["q", "a", "o", "h", "v"]:   # Channel right taken.
                        ChanServ.give_mode(connection, event.target, mode[2], mode[1])
                        connection.mode(event.target, mode[0] + mode[1] + " " + mode[2])
                elif behaviour == "equal_retalliation":   # Equal retaliatory behaviour.
                    if modes[1] == "b" and mode[0] == "+":  # Ban.
                        if fnmatch.fnmatch(self.protectees[protectee]['ident'], mode[2]):  # Protectee.
                            do_everything_to.unban(connection, event.target, protectee, mode[2])
                            if protectee == connection.get_nickname():  # Bot banned.
                                ChanServ.ban(connection, event.target, event.source.nick, "Aggression channel function = equal_retalliation.")
                            else:
                                ChanServ.ban(connection, event.target, event.source.nick, "Aggression channel function = equal_retalliation: " + protectee + " is an operator of " + connection.get_nickname() + ".")
                            connection.mode(event.target, "+b " + event.source)
                    elif mode[1] == "e" and mode[0] == "-":  # Removed exception.
                        if fnmatch.fnmatch(self.protectees[protectee]['ident'], event.arguments[idx + 1]):  # Protectee.
                            connection.mode(event.target, "+e " + event.arguments[idx + 1])
                    elif mode[0] == "-" and mode[1] in ["q", "a", "o", "h", "v"]:   # Channel right taken.
                        ChanServ.give_mode(connection, event.target, mode[2], mode[1])
                        connection.mode(event.target, mode[0] + mode[1] + " " + mode[2])
                        ChanServ.take_all_modes(connection, event.target, mode[2])
                        connection.mode(event.target, "-vhoaq " + mode[2] + " " + mode[2]+ " " + mode[2]+ " " + mode[2]+ " " + mode[2])
                elif behaviour == "battlebot":  # Battlebot behaviour.
                    if mode[0] == "-" and mode[1] in ["q", "a", "o", "h", "v"]:   # Channel right taken.
                        ChanServ.give_mode(connection, event.target, mode[2], mode[1])
                        connection.mode(event.target, mode[0] + mode[1] + " " + mode[2])
                        do_everything_to.unban(connection, event.target, protectee, mode[2])
                        do_everything_to.ban(connection, event.target, event.source.nick, event.source, Aggressiveness.retalliation_reason(self, connection, protectee, behaviour))
                        connection.mode(event.target, "+e " + mode[2])
                        ChanServ.akick_add(connection, event.target, event.source.nick)
                        do_everything_to.kick(connection, event.target, event.source.nick, Aggressiveness.retalliation_reason(self, connection, protectee, behaviour))
                    if mode[1] == "b" and mode[0] == "+":  # Ban.
                        if fnmatch.fnmatch(self.protectees[protectee]['ident'], mode[2]):  # Protectee.
                            do_everything_to.unban(connection, event.target, protectee, mode[2])
                            do_everything_to.ban(connection, event.target, event.source.nick, event.source, Aggressiveness.retalliation_reason(self, connection, protectee, behaviour))
                            connection.mode(event.target, "+e " + mode[2])
                            ChanServ.akick_add(connection, event.target, event.source.nick)
                            do_everything_to.kick(connection, event.target, event.source.nick, Aggressiveness.retalliation_reason(self, connection, protectee, behaviour))
                    elif mode[1] == "e" and mode[0] == "-":  # Removed exception.
                        #for protectee in self.protectees:
                        if fnmatch.fnmatch(self.protectees[protectee]['ident'], event.arguments[idx + 1]):  # Protectee.
                            do_everything_to.ban(connection, event.target, event.source.nick, event.source, Aggressiveness.retalliation_reason(self, connection, protectee, behaviour))
                            connection.mode(event.target, "+e " + event.arguments[idx + 1])
                            ChanServ.akick_add(connection, event.target, event.source.nick)
                            do_everything_to.kick(connection, event.target, event.source.nick, Aggressiveness.retalliation_reason(self, connection, protectee, behaviour))
            except:
                pass
