#!/usr/bin/python
#
# Author: Christian Dietrich <stettberger@gmx.de>
# Year: 2006
# License: GPL
              
import re, sys, os
ircdir="%s/irc"%os.environ['HOME']
browser="firefox \"%s\""

def read_file_reverse(filename, callback, many=1):
    fd=open(filename, "r")
    fd.seek(0,2)
    buf=""
    match=[]
    while (fd.tell()-10)>0:
        fd.seek(fd.tell()-10)
        buf=fd.read(10)+buf
        fd.seek(fd.tell()-10)
        if '\n' in buf:
            fd.seek(fd.tell()+buf.find('\n'))
            line=buf[buf.find('\n')+1:]
            buf=''
            ret=callback(line)
            if  ret != None:
                fd.close()
                match.append(ret)
                if(len(match)==many):
                    return match
    fd.close()

def parse_url(line):
    regex=".*(?P<url>(?:(?:[hH][tT]{2}[Pp][sS]?)|(?:[fF][Tt][Pp]))://[a-zA-Z&\?.0-9+\-_=~#/]*).*"
    if re.match(regex, line):
        return re.match(regex, line).groups("url")[0]
    return None

class Server:
    colors={"red": "\033[0;40;31m",
            "green": "\033[0;40;32m",
            "yellow": "\033[0;40;33m",
            "blue": "\033[0;40;34m",
            "magenta":"\033[0;40;35m",
            "cyan": "\033[0;40;36m",
            "white": "\033[0;40;37m",
            "normal": "\033[0m"}
    def __init__(self, name, syn):
        self.host=name
        self.channels=[]
        self.add_channel(None, syn, self.colors['white'])
    def add_channel(self, name, syn, color=None):
        if color is None:
            color=self.colors['normal']
        if name != None:
            if len(syn)==0:
                syn=name
            self.channels.append([syn, "%s%s%s"%(color,name,self.colors['normal']), "%s/%s"%(self.host, name)])
        else:
            self.channels.append([syn, "%s%s%s"%(color,self.host ,self.colors['normal']), "%s"%self.host])
    def add_query(self, name, syn, color=None):
        if color is None:
            color=self.colors['normal']
        self.channels.append([syn, "%s%s%s"%(color,name, self.colors['normal']), "%s/query/%s"%(self.host, name)])
    def has_channel(self, syn):
        for i in self.channels:
            if i[0]==syn:
                return True
        return False
    def get_channel(self, syn):
        for i in self.channels:
            if i[0]==syn:
                return i
        return None
    
servers=[]
now=None

def proc_input(line):
    # Auswahl von Server/Channel/Query
    if line[0:3]=="/s ":
        for i in servers:
            if i.has_channel(line[3:]):
                globals()['now']=i.get_channel(line[3:])
    # For Debugging only
    elif line[0:2]=="/p":
        for i in servers:
            print "Server: %s"%i.host
            for x in i.channels:
                print "      %s %s"%(x[0],x[1])
    # Link handling
    elif line[0:5]=="/link":
        tok=re.split("\s+", line)
        if len(tok)==1 or len(tok[1])==0:
            ch=globals()['now'][2]
        else:
            for i in servers:
                if i.has_channel(tok[1]):
                    ch=i.get_channel(tok[1])[2]
        filename="%s/%s/out"%(ircdir,ch)
        urls=read_file_reverse(filename, parse_url)
        if urls==None:
            sys.stdout.write("%sError %s"%(Server.colors['red'], Server.colors['normal']))
            return
        os.system((browser+ "&")%urls[0])
        sys.stdout.write("%sUrl opened %s"%(Server.colors['green'], Server.colors['normal']))
    # Server/Channel/Query adden
    elif line[0:5]=="/add ":
        tokens=re.split(" *", line)
        if len(tokens)<2:
            sys.stdout.write("%sError %s"%(Server.colors['red'], Server.colors['normal']))
            return
        # Add a query
        if tokens[1]=="query":
            if len(tokens)<4:
                sys.stdout.write("%sError %s"%(Server.colors['red'], Server.colors['normal']))
                return
            for i in servers:
                if i.host==tokens[2]:
                    if len(tokens)==4:
                        i.add_query(tokens[3], tokens[3])
                    elif len(tokens)==5:
                        i.add_query(tokens[3], tokens[4])
                    elif len(tokens)>5:
                        i.add_query(tokens[3], tokens[4], Servers.colors[tokens[5]])
                    return
            sys.stdout.write("%sError %s"%(Server.colors['red'], Server.colors['normal']))
        # Add a channel
        elif tokens[1]=="channel":
            if len(tokens)<4:
                sys.stdout.write("%sError %s"%(Server.colors['red'], Server.colors['normal']))
                return
            for i in servers:
                if i.host==tokens[2]:
                    if len(tokens)==4:
                        i.add_channel(tokens[3], tokens[3])
                    elif len(tokens)==5:
                        i.add_channel(tokens[3], tokens[4])
                    elif len(tokens)>5:
                        i.add_channel(tokens[3], tokens[4], Server.colors[tokens[5]])
                    return
            sys.stdout.write("%sError %s"%(Server.colors['red'], Server.colors['normal']))
        # Add a Server
        elif tokens[1]=="server":
            if len(tokens)<3:
                sys.stdout.write("%sError %s"%(Server.colors['red'], Server.colors['normal']))
                return
            if len(tokens)==3:
                servers.append(Server(tokens[2], tokens[2]))
            elif len(tokens)>3:
                servers.append(Server(tokens[2], tokens[3]))
    else:
        if globals()['now'] is None:
            return
        t=open("%s/%s/in"%(ircdir, globals()['now'][2]), "w+")
        t.write("%s\n"%line)
        t.close()

def init():
    ##Servers
    try:
        fd=open("%s/serv.def"%ircdir)
    except:
        print "Error: Couldn't open servers definition"
        sys.exit(-1)
    for i in fd.readlines():
        i=i.split(";", 3)
        if len(i)<3:
            print i, "is not a valid line (serv.def)"
            continue
        servers.append(Server(i[0], i[1]))
    fd.close()
    try:
        fd=open("%s/chan.def"%ircdir)
    except:
        print "Error: Couldn't open channel definition"
    for i in fd.readlines():
        i=i.split(";", 3)
        if len(i)<4:
            print i, "is not a valid line (chan.def)"
            continue
        for s in servers:
            if s.host == i[0]:
                try:
                    s.add_channel(i[1], i[2], Server.colors[i[3].replace("\n","")])
                except:
                    print i, " couldn't be appended (chan.def)"

# Initialize channels
init()

while True:
    if globals()['now']==None:
        if len(servers)==0:
            globals()['now']=['','',None]
        else:
            globals()['now']=servers[0].channels[0]
    try:
        line=raw_input("%s> "%globals()['now'][1])
    except:
        sys.exit(0)
    if len(line)==0:
        continue
    try:
        proc_input(line)
    except:
        sys.stdout.write("%sError %s"%(Server.colors['red'], Server.colors['normal']))
    
