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)


class Command(BaseCommand):
    args = 'yyyy/mm/dd <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) != 2:
            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)
        if not datere.match(args[0]):
            raise CommandError(args[0] + " is not a valid year/month/day")

        year, month, day = [int(x, 10) for x in args[0].split('/')]
        csvfile = args[1]

        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 = attreg.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):
            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=title,
                               _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.split(',') ]
            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

        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
