import re
import asyncio
from base64 import b64encode
from decloak import Decloak
from netinfo import NetInfo
from checkvpn import CheckVPN
from checkrbl import CheckRBL

from config import ircbot as config

class IRCClientProtocol(asyncio.Protocol):
    def __init__(self):
        self.recvqueue = ""
        self.nick = config["nick"]
        self.reportchan = config["report_channel"]
        self.netinfo = NetInfo(self)
        self.checkvpn = CheckVPN(self, config["proxy_channel"],
                                 config["hotspot_channel"])
        self.checkrbl = CheckRBL(self)

    def send_message(self, message):
        print(message)
        fullmsg = "{}\r\n".format(message)
        self.transport.write(fullmsg.encode())

    def sendtochannel(self, message):
        self.send_message("PRIVMSG {} :{}".format(self.reportchan, message))

    def connection_made(self, transport):
        self.transport = transport
        self.send_message("CAP REQ :sasl")
        self.send_message("NICK %s" % self.nick)
        self.send_message("USER %s 8 * %s" % (self.nick, self.nick))

    def data_received(self, data):
        self.recvqueue += data.decode()
        messages = re.split("\r\n", self.recvqueue)
        # To prevent half of a message being processed
        self.recvqueue = messages.pop()
        [self.parse_message(msg) for msg in messages]

    def parse_message(self, msg):
        print(msg)
        if msg == "":
            return
        rawmsg = re.split("(:\S+\s)?(\S+)(.*)", msg)
        prefix = rawmsg[1]
        if prefix is not None:
            prefix = prefix.strip()
        command = rawmsg[2]
        params = re.split("\s(.*)\s:(.*)", rawmsg[3])
        message = ""
        if len(params) is 4:
            message = params[2]
            params = re.split("\s", params[1])
        else:
            params = re.split("\s", params[0].strip())
            if params[0].startswith(":"):
                message = " ".join(params[0:]).lstrip(":")
                params = []

        if command == "CAP":
            self.send_message("AUTHENTICATE PLAIN")
        elif command == "AUTHENTICATE":
            authstring = b64encode(bytes("\0%s\0%s" %
                                     (self.nick, config["password"]), "UTF-8"))
            self.send_message("AUTHENTICATE %s" % authstring.decode())
        elif command == "900":
            self.send_message("CAP END")
        elif command == "376":
            for channel in config["allchannels"]:
                self.send_message("JOIN %s" % channel)
        elif command == "PING":
            self.send_message("PONG %s" % message)
        elif command == "PRIVMSG":
            messageparams = re.split("\s", message)
            if params[0] == self.reportchan:
                if "decloak" in messageparams[0]:
                    self.currentdecloak = Decloak(
                        messageparams[1], self.reportchan, self)
                elif "netinfo" in messageparams[0]:
                    self.netinfo.lookupIP(messageparams[1])
                elif "checkrbl" in messageparams[0]:
                    self.checkrbl.check(messageparams[1])
            elif params[0] == config["hotspot_channel"]:
                if "check" in messageparams[0]:
                    self.checkvpn.check_hotspot(messageparams[1])
            elif params[0] == "##openvpn-bans":
                if "check" in messageparams[0]:
                    self.checkvpn.check_openvpn(messageparams[1])
            elif params[0] == config["proxy_channel"]:
                if "check" in messageparams[0]:
                    self.checkvpn.checkproxy(messageparams[1])
        elif command == "MODE":
            if len(params) > 1 and params[1] == "-q" and self.currentdecloak:
                self.currentdecloak.nextsubnet(params[2].lstrip("*!@"))


loop = asyncio.get_event_loop()
conn = loop.create_connection(IRCClientProtocol, config["host"],
                              config["port"], ssl=True)
loop.run_until_complete(conn)
loop.run_forever()
loop.close()

