"""
log.py: written by Scaevolus 2009
"""

import os
import codecs
import time
import re

from util import hook


log_fds = {}  # '%(net)s %(chan)s': (filename, fd)

timestamp_format = '%H:%M:%S'

formats = {
    'PRIVMSG': '<%(nick)s> %(msg)s',
    'PART': '-!- %(nick)s [%(user)s@%(host)s] has left %(chan)s',
    'JOIN': '-!- %(nick)s [%(user)s@%(host)s] has joined %(param0)s',
    'MODE': '-!- mode/%(chan)s [%(param_tail)s] by %(nick)s',
    'KICK': '-!- %(param1)s was kicked from %(chan)s by %(nick)s [%(msg)s]',
    'TOPIC': '-!- %(nick)s changed the topic of %(chan)s to: %(msg)s',
    'QUIT': '-!- %(nick)s has quit [%(msg)s]',
    'PING': '',
    'NOTICE': '-%(nick)s- %(msg)s'
}

ctcp_formats = {
    'ACTION': '* %(nick)s %(ctcpmsg)s',
    'VERSION': '%(nick)s has requested CTCP %(ctcpcmd)s from %(chan)s: %(ctcpmsg)s',
    'PING': '%(nick)s has requested CTCP %(ctcpcmd)s from %(chan)s: %(ctcpmsg)s',
    'TIME': '%(nick)s has requested CTCP %(ctcpcmd)s from %(chan)s: %(ctcpmsg)s',
    'FINGER': '%(nick)s has requested CTCP %(ctcpcmd)s from %(chan)s: %(ctcpmsg)s'
}

irc_color_re = re.compile(r'(\x03(\d+,\d+|\d)|[\x0f\x02\x16\x1f])')


def get_log_filename(dir, server, chan):
    return os.path.join(dir, 'log', gmtime('%Y'), server, chan,
                        (gmtime('%%s.%m-%d.log') % chan).lower())


def gmtime(format):
    return time.strftime(format, time.gmtime())


def beautify(input):
    format = formats.get(input.command, '%(raw)s')
    args = dict(input)

    leng = len(args['paraml'])
    for n, p in enumerate(args['paraml']):
        args['param' + str(n)] = p
        args['param_' + str(abs(n - leng))] = p

    args['param_tail'] = ' '.join(args['paraml'][1:])
    args['msg'] = irc_color_re.sub('', args['msg'])

    if input.command == 'PRIVMSG' and input.msg.count('\x01') >= 2:
        ctcp = input.msg.split('\x01', 2)[1].split(' ', 1)
        if len(ctcp) == 1:
            ctcp += ['']
        args['ctcpcmd'], args['ctcpmsg'] = ctcp
        format = ctcp_formats.get(args['ctcpcmd'],
                                  '%(nick)s [%(user)s@%(host)s] requested unknown CTCP '
                                  '%(ctcpcmd)s from %(chan)s: %(ctcpmsg)s')

    return format % args


def get_log_fd(dir, server, chan):
    fn = get_log_filename(dir, server, chan)
    cache_key = '%s %s' % (server, chan)
    filename, fd = log_fds.get(cache_key, ('', 0))

    if fn != filename:  # we need to open a file for writing
        if fd != 0:     # is a valid fd
            fd.flush()
            fd.close()
        dir = os.path.split(fn)[0]
        if not os.path.exists(dir):
            os.makedirs(dir)
        fd = codecs.open(fn, 'a', 'utf-8')
        log_fds[cache_key] = (fn, fd)

    return fd


@hook.singlethread
@hook.event('*')
def log(paraml, input=None, bot=None):
    timestamp = gmtime(timestamp_format)

    fd = get_log_fd(bot.persist_dir, input.server, 'raw')
    fd.write(timestamp + ' ' + input.raw + '\n')

    if input.command == 'QUIT':  # these are temporary fixes until proper
        input.chan = 'quit'      # presence tracking is implemented
    if input.command == 'NICK':
        input.chan = 'nick'

    beau = beautify(input)

    if beau == '':  # don't log this
        return

    if input.chan:
        fd = get_log_fd(bot.persist_dir, input.server, input.chan)
        fd.write(timestamp + ' ' + beau + '\n')

    print timestamp, input.chan, beau.encode('utf8', 'ignore')
