#!/usr/bin/python

from __future__ import with_statement

import ConfigParser
import nntplib
import os
import re
import socket
import time
import urllib2
from datetime import datetime
from StringIO import StringIO


try:
    from ncpp_local import processPatch
except ImportError as e:
    print(e)
    # I've seen this error happen multiple times at 6AM on Sundays,
    # coinciding with the AFS restart. Wait five minutes for the
    # servers to come back.
    time.sleep(300)
    from ncpp_local import processPatch

STATEFILE = '/mit/ncurses/auto/state.ini'
STATE = ConfigParser.ConfigParser()
STATE.read(STATEFILE)
state = dict(STATE.items('ncurses'))

## Patch processing
subjectPattern = re.compile('(?:ANN: )?([^ ]*ncurses-\d+.\d+(?:-\d{8})?(?:.patch.gz)?)')
patchPattern = re.compile(' (\S*ncurses-\d+.\d+(?:-\d{8})?.patch.gz)')
vPatchPattern = re.compile('(?:ANN: )?ncurses-%s-\d{8}(?:.patch.gz)?' % state['version'])

def isPatch(subject):
    if subjectPattern.match(subject):
        if vPatchPattern.match(subject):
            return True
        print "Unexpected version number in subject:\n%s\n" % subject
    return False

def findPatchURI(body):
    return [line.group(0) for line in map(patchPattern.match, body) if line]

## NNTP
def respOK(resp):
    # As per http://www.faqs.org/rfcs/rfc977.html
    # 2xx - Command ok
    return resp[0] == '2'

def getSubjects(s, group, last_seen, version, **kw):
    last_seen = 8300
    resp, count, first, last, name = s.group(group)
    if not respOK(resp):
        print "Unexpected response [%s]" % resp
    elif int(first) < int(last_seen) < int(last):
        resp, subjects = s.xhdr('subject','%i-%s' % (int(last_seen)+1,last))
        if not respOK(resp):
            print "Unexpected response [%s]" % resp
        return subjects
    return None

def processPatchArticles(s, articles):
    articles = filter(lambda x: isPatch(x[1]), articles)
    for id, subject in articles:
        print id, subject
        resp, id, msgid, body = s.body(id)
        if respOK(resp):
            with open('/mit/ncurses/cron-working/msgs/%s.msg' % id, 'w') as f:
                f.write('\n'.join(body))
            # uris = findPatchURI(body)
            # if len(uris) != 1:
            #     # Unexpected URI count, send mail.
            #     print "Unexpected number of URIs: %s" % uris
            #     return -1
            # try:
            #     ret = processPatch(uris[0].strip())
            #     if ret != 0:
            #         return ret
            # except urllib2.URLError as e:
            #     print "URLError: %s" % e.reason
            #     print "URL was: %s" % uris[0].strip()
        return 0
    return 0


## High-level
def doconnect():
    tryCount = 0
    while True:
        try:
            svr = nntplib.NNTP(state['server'])
            return svr
        except (socket.error, socket.gaierror, nntplib.NNTPError, nntplib.NNTPTemporaryError):
            if tryCount < 9:
                tryCount += 1
                time.sleep(30)
            else:
                raise # Giving up

def main():
    svr = doconnect()
    subjects = getSubjects(svr, **state)
    if subjects:
        new_last = subjects[-1][0]
        #STATE.set('ncurses', 'last_seen', new_last)
        ret = processPatchArticles(svr, subjects)
        #STATE.set('ncurses', 'stop', ret)
        #with open(STATEFILE,'wb') as f:
        #    STATE.write(f)

#if state['stop'] == '0':
main()
