from django.core.management.base import BaseCommand, CommandError
from django.db import transaction
from datetime import *
import csv
import re
propre = re.compile("^\d+\. ")
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
    # 14:00:00
    apm = 'mil'
    t = timestr.split()
    if len(t) == 2: t, apm = t
    else: t = t[0]
    apm = apm.lower()
    hour, min = t.split(':')[:2]
    hour, min = int(hour,10), int(min,10)
    if apm == 'pm' and hour != 12: hour += 12
    return datetime(year=year, month=month, day=day,
                    hour=hour, minute=min)

def dur2dur(durstr):
    if 'all-day' in durstr: return 5
    try:
        dur = int(durstr.split('+')[0], 10)
        if not dur: return 15
        return dur
    except:
        return 15

def spkr2spkr(schedule, pgroup, fullname):
    from django.contrib.auth.models import User, Group

    first = fullname.split()[0]
    last = fullname.split()[-1]
    try:
        return schedule.Presenter.objects.get(name=fullname)
    except schedule.Presenter.DoesNotExist:
        pass

    uu = User.objects.filter(first_name=first, last_name=last)
    if not len(uu):
        p = schedule.Presenter(name = fullname)
        p.save()
        return p
    if len(uu) > 1:
        print "WARNING: multiple users found for speaker (%s):\n" % repr(fullname)
        print "\n        ".join(unicode(u) for u in uu)
    u = uu[0]
    u.groups.add(pgroup)
    u.save()

    try:
        return schedule.Presenter.objects.get(user=u)
    except schedule.Presenter.DoesNotExist:
        pass
    p = schedule.Presenter(user=u)
    p.save()
    return p

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')
            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')

        def invtalk2event(title, dur):
            pid=int(title[:3], 10)
            spkind = title.rfind('(')
            speakers = [spkr2spkr(schedule, pgroup, s.strip()) for s in title[spkind+1:-1].split(',')]
            title = title[5:spkind].strip() + ' (#%d)' % pid
            e = schedule.Event(_summary="TBA", _title=title,
                               _duration=dur2dur(dur), type='E')
            e.save()
            e.presenters = speakers
            e.save()
            return e

        def talk2event(title, dur):
            if propre.match(title) and title.find('.',1,4) > 0:
                pid=int(title[:title.find('.', 1,4)], 10)

                print "title", repr(title), "pid", pid
                try:
                    prop=propmgr.Proposal.objects.get(pk=pid, status='A',
                                                      published=True)
                except propmgr.Proposal.DoesNotExist:
                    if pid < 200: raise
                    return invtalk2event(title, dur)
                prop.submitter.groups.add(pgroup)
                prop.submitter.save()
                for u in prop.coauthors.all():
                    u.groups.add(pgroup)
                    u.save()
                e = schedule.Event(proposal=prop)
                e.save()
                return e
            typ = 'E'
            if 'Lunch' in title: typ='B'
            if 'Break' in title: typ='B'
            if 'Service' in title: typ='B'
            if 'Registration' in title: typ = 'B'
            if 'Keynote' in title: typ = 'P'
            if 'Plenary' in title: typ = 'P'
            if 'Meeting' in title: typ = 'M'
            if 'Sprint' in title: typ = 'M'
            e = schedule.Event(_summary="TBA", _title=title,
                               _duration=dur2dur(dur), type=typ)
            e.save()
            return e

        reader = csv.reader(file(csvfile, "rU"))
        reader.next() ## title
        reader.next() ## blank line
        rooms = reader.next()[3:] ## rooms
        rooms = [ schedule.Room.objects.get(name=n) for n in rooms ]
        for line in reader:
            if len(line) < 3: break
            time, end, dur, talks = line[0], line[1], line[2], line[3:]
            if '\n' in time: time = time.split()[0]
            if '\n' in dur: dur = dur.split()[0]
            dt = timestr2datetime(year, month, day, time)
            for ri, title in enumerate(talks):
                if not title: continue
                room = rooms[ri]
                event = talk2event(title, dur)
                if len(talks)==1 and event.type in ['P', 'B']: room = None
                sch = schedule.ScheduledEvent(event=event, start=dt, room=room)
                sch.save()
                print sch.start, sch.room, sch.event.type, sch.event.duration, sch

        missing = propmgr.Proposal.objects.filter(
            status='A', published=True).exclude(event__isnull=False)
        if missing.count():
            print "Missing the following %d proposals:" % missing.count()
            for prop in missing:
                print prop
