import socket
from util import readline, magicdict
from protocol import tokenize, OutputBuilder, Event

class Bot(object):
    config = None
    socket = None
    state = None
    
    def __init__(self, config):
        self.config = config
        self.state = magicdict()
    
    def start(self):
        self.connect()
        
        for line in readline(self.socket):
            if self.config.debug_in:
                print ">", line.strip()
            self.parse(line)
        
        self.cleanup()
    
    def connect(self):
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.socket.connect((self.config.host, self.config.port))
    
    def cleanup(self):
        self.socket.close()
    
    def parse(self, line):
        event_name,  match = tokenize(line)
        if event_name is not None:
            if hasattr(self, 'handle_'+event_name.upper()):
                getattr(self, 'handle_'+event_name.upper())(event_name, Event(event_name, match, line), line, OutputBuilder(self))
            else:
                if self.config.debug:
                    print "Unhandled event", event_name

    
    def handle_SNOTICE(self, name, event, line, out):
        if not self.state.registered:
            out.sendPass(self.config.auth)
            out.sendNick(self.config.nick)
            out.sendUser(self.config.ident, '*', '*', self.config.realname)
            self.state.registered = True
    
    def handle_001(self, name, event, line, out):
        if not self.state.joined_chans:
            for channel in self.config.autojoins:
                out.sendJoin(channel)
            self.state.joined_chans = True
    
    def handle_JOIN(self, name, event, line, out):
        if event.nick == self.config.nick:
            out.sendWho(event.channel)
            out.sendUmode(event.channel, 'qb') # not really a umode but only has 2 args
            out.sendPrivmsg('chanserv', 'info '+event.channel)
            out.sendPrivmsg('chanserv', 'access '+event.channel+' list')
    
    def handle_376(self, name, event, line, out):
        if not self.state.set_own_modes:
            out.sendUmode(self.config.nick, self.config.umodes)
            self.state.set_own_modes = True
    
    def handle_PING(self, name, event, line, out):
        out.sendPong(event.arg)

    def handle_PRIVMSG(self, name, event, line, out):
        if event.hostname == self.config.owner_hostmask:
            cmd_args = event.message.split(" ")
            cmd = cmd_args[0].lower()
            args = cmd_args[1:]
            if cmd.startswith("&"):
                cmd = cmd[1:] # remove prefix &
                if cmd == 'join':
                    if len(args) != 1:
                        out.sendNotice(event.nick, "Invalid number of arguments for command " + cmd + ", expected 1, got " + len(args))
                    else:
                        out.sendJoin(args[0])
                        out.sendNotice(event.nick, "Joining channel "+args[0])
                elif cmd == 'part':
                    if len(args) != 1:
                        out.sendNotice(event.nick, "Invalid number of arguments for command " + cmd + ", expected 1, got " + len(args))
                    else:
                        out.sendPart(args[0])
                        out.sendNotice(event.nick, "Parting channel "+args[0])
                elif cmd == 'quit':
                    out.sendNotice(event.nick, "Quitting.")
                    out.sendQuit("Requested.")
                else:
                    out.sendNotice(event.nick, "Unknown command "+cmd)
