from django.core.management.base import BaseCommand, CommandError
from django.db import transaction
from datetime import *
import csv
import re
tutre = re.compile("^[APE][MV][0-9X]: ")
datere = re.compile("^(?P<year>20\d{2})/(?P<month>0?[1-9]|10|11|12)/(?P<day>0?[1-9]|1[0-9]|2[0-9]|3[0-2])$")

def timestr2datetime(year, month, day, timestr):
    # 11:25 am
    t, ap = timestr.split()
    hour, min = t.split(':')
    hour, min = int(hour,10), int(min,10)
    if ap == 'pm' and hour != 12: hour += 12
    return datetime(year=year, month=month, day=day,
                    hour=hour, minute=min)

def split_name(name):
    """
    Return (last, first) for accountless registrants.
    Not perfect, but better than nothing.
    """
    s = name.split()
    if len(s) == 2:
        return (s[1], s[0])
    if len(s) < 2:
        return (name, u'')
    if u'.' in s[0] and len(s[0]) > 2:
        # "Mr.", "Ms.", etc.
        s.pop(0)
    if u'.' in s[-1] and len(s[-1]) > 2:
        # "Esq." etc?
        s.pop()
    if len(s) < 2:
        return (s[0], u'')
    return (s[-1], s[0])


class Command(BaseCommand):
    args = '<filename>'

    @transaction.commit_on_success
    def handle(self, *args, **options):
        from django.db import models
        from pycon.core import safe_ascii_encode
        if len(args) != 1:
            raise CommandError('Enter a valid date and input file.')
        try:
            schedule = models.get_app('schedule')
            propmgr  = models.get_app('propmgr')
            #attreg   = models.get_app('attendeereg')
            auth     = models.get_app('auth')
        except (ImproperlyConfigured, ImportError), e:
            raise CommandError(
                "%s. Are you sure your INSTALLED_APPS setting is correct?" % e)

        tutfile = args[0]


        pgroup = auth.Group.objects.get(name='Presenters')
        tgroup = auth.Group.objects.get(name='Teachers')
        presenter_cache={}
        def auth2presenter(authname):
            if authname in presenter_cache:
                return presenter_cache[authname]
            last, first = split_name(authname)
            users = auth.User.objects.filter(first_name__iexact=first,
                                             last_name__iexact=last)
            if users.count() == 1:
                ## RED_FLAG: we are making a gross assumption
                u = users[0]
                u.groups.add(pgroup)
                u.groups.add(tgroup)
                u.save()
                p = schedule.Presenter(user=u)
            else:
                print 'Presenter Not Found:', authname, '|', first, '|', last, '|', users
                p = schedule.Presenter(name=authname)
            p.save()
            presenter_cache[authname] = p
            return p

        def tut2event(text, dur, authors):
            #try:
            #    title, authors = text.strip().split("\n")
            #except:
            #    print text
            #    raise
            #assert(tutre.match(title))
            #name=title[:3]
            #tutorial = attreg.Tutorial.objects.get(name=name)
            #title = tutorial.title
            #ind = title.rfind('(')
            #if ind: title=title[:ind]
            #title += u'(' + tutorial.name + u')'
            e = schedule.Event(_summary="TBA", _title=text,
                               _duration=dur, type='T')
            #if tutorial.pageurl: e.url = tutorial.pageurl
            e.save()
            #tutorial.popurl = e.get_tooltip_url()
            #tutorial.save()
            presenters = [ auth2presenter(auth.strip())
                           for auth in authors ]
            e.presenters = presenters
            e.save()
            return e

        def mkbreak(start, stop, duration, title, summary):
            e = schedule.Event(_summary=summary, _title=title,
                               _duration=duration, type='B')
            e.save()
            sch = schedule.ScheduledEvent(event=e, start=start, stop=stop)
            sch.save()
            print 'BRK:', sch

        def ssd(trange):
            start, stop = [ timestr2datetime(year, month, day, t.strip())
                            for t in trange.split('-') ]
            delta = stop - start
            return start, stop, delta.seconds/60

        for line in file(tutfile, "U"):
            date, time, dur, room, title = line.strip().split("\t")[:5]
            m, d, y = [ int(x, 10) for x in date.strip().split('/')]
            h, mi, s = [ int(x, 10) for x in time.strip().split(':')]
            spkrs = line.strip().split("\t")[5:]
            e = tut2event(title, dur, spkrs)
            start = datetime(y, m, d, h, mi)
            try:
                r = schedule.Room.objects.get(name=room.strip())
            except schedule.Room.DoesNotExist:
                print "Could not find room:", room
                raise
            se = schedule.ScheduledEvent(event=e, room=r, start=start)
            se.save()


def JUNK():
        reader = csv.reader(file(csvfile, "rU"))
        reader.next() ## title
        reader.next() ## blank line
        reader.next() ## session heading
        times = reader.next()
        assert(times[0] == 'Times')
        times.pop(0)
        food_breaks = [ ssd(range) for range in times[1::2] ]
        sessions = [ [ssd(r) for r in rs.split('\n')] for rs in times[::2] ]
        snack_breaks = [ ( e1, s2, (s2-e1).seconds/60 )
                         for (s1, e1, d1), (s2, e3, d2) in sessions ]
        for s, e, d in food_breaks:  mkbreak(s, e, d, 'Food Break', 'Food Break\n\nTBD')
        for s, e, d in snack_breaks: mkbreak(s, e, d, 'Break',      'Snack Break\n\nTBD')
        durations = reader.next()
        assert(durations[0] == 'Duration')
        durations.pop(0)
        durations = [ int(d.split()[0], 10) for d in durations[::2] ]
        assert(len(durations) == len(sessions))
        for line in reader:
            if len(line) < 2: break
            room_name = line.pop(0).split('\n')[0].strip()
            room = schedule.Room.objects.get(name=room_name)
            tuts = line[::2]
            assert(len(tuts) == len(sessions))
            for session, duration, data in zip(sessions, durations, tuts):
                if not tutre.match(data): continue
                event = tut2event(data, duration)
                for start, stop, dur in session:
                    sch = schedule.ScheduledEvent(event=event, room=room,
                                                  start=start, stop=stop)
                    sch.save()
                print "TUT:", event
