from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

from rowers.views.statements import *
from rowsandall_app.settings import SITE_URL
from rowers.scoring import *

# List Courses
def courses_view(request):
    r = getrower(request.user)

    courses = GeoCourse.objects.all().order_by("country","name")

    # add search processing
    query = request.GET.get('q')
    if query:
        query_list = query.split()
        courses = GeoCourse.objects.filter(
            reduce(operator.and_,
                   (Q(name__icontains=q) for q in query_list)) |
            reduce(operator.and_,
                   (Q(country__icontains=q) for q in query_list)) |
            reduce(operator.and_,
                   (Q(notes__icontains=q) for q in query_list))
            )
        searchform = SearchForm(initial={'q':query})
    else:
        searchform = SearchForm()

    return render(request,'list_courses.html',
                  {'courses':courses,
                   'active':'nav-racing',
                   'searchform':searchform,
                   'rower':r,
                   })

# List Courses
def standards_view(request):
    r = getrower(request.user)

    standards = StandardCollection.objects.filter(active=True).order_by("name")

    # add search processing
    query = request.GET.get('q')
    if query:
        query_list = query.split()
        standards = StandardCollection.objects.filter(
            reduce(operator.and_,
                   (Q(name__icontains=q) for q in query_list)) |
            reduce(operator.and_,
                   (Q(notes__icontains=q) for q in query_list))
            )
        searchform = SearchForm(initial={'q':query})
    else:
        searchform = SearchForm()


    return render(request,'list_standards.html',
                  {'standards':standards,
                   'active':'nav-racing',
                   'searchform':searchform,
                   'rower':r,
                   })



# for ajax calls
def course_map_view(request,id=0):
    try:
        course = GeoCourse.objects.get(id=id)
    except GeoCourse.DoesNotExist:
        return Http404("Course doesn't exist")

    script,div = course_map(course)

    breadcrumbs = [
        {
            'url': reverse('virtualevents_view'),
            'name': 'Challenges'
        },
        {
            'url': reverse(courses_view),
            'name': 'Courses'
        },
        {
            'url': reverse(course_view,kwargs={'id':course.id}),
            'name': course.name
        },
        {
            'url': reverse(course_map_view,kwargs={'id':course.id}),
            'name': 'Map'
        }
    ]

    r = getrower(request.user)


    return render(request,
                  'coursemap.html',
                  {
                      'mapdiv':div,
                      'course':course,
                      'mapscript':script,
                      'active':'nav-racing',
                      'rower':r,
                      'breadcrumbs':breadcrumbs,
                  })


@login_required()
@permission_required('course.change_course',fn=get_course_by_pk,raise_exception=True)
def course_replace_view(request,id=0):
    course = get_object_or_404(GeoCourse,pk=id)

    r = getrower(request.user)

    thecourses = GeoCourse.objects.filter(manager=r).exclude(id=id)

    if request.method == 'POST':
        form = CourseSelectForm(request.POST)
        if form.is_valid():
            course2 = form.cleaned_data['course']
            res = courses.replacecourse(course,course2)

            url =  reverse(course_view,
                           kwargs = {
                               'id':course2.id
                               })

            return HttpResponseRedirect(url)
    else:

        form = CourseSelectForm()
        form.fields["course"].queryset = thecourses

    script,div = course_map(course)

    breadcrumbs = [
        {
            'url': reverse('virtualevents_view'),
            'name': 'Challenges'
        },
        {
            'url': reverse(courses_view),
            'name': 'Courses'
        },
        {
            'url': reverse(course_view,kwargs={'id':course.id}),
            'name': course.name
        },
        {
            'url': reverse(course_replace_view,kwargs={'id':course.id}),
            'name': 'Replace Markers'
            }
        ]

    return render(request,
                  'course_replace.html',
                  {'course':course,
                   'active':'nav-racing',
                   'breadcrumbs':breadcrumbs,
                   'rower':r,
                   'mapdiv':div,
                   'mapscript':script,
                   'form':form})

@login_required()
@permission_required('course.delete_course',fn=get_course_by_pk,raise_exception=True)
def course_delete_view(request,id=0):
    course = get_object_or_404(GeoCourse,pk=id)

    r = getrower(request.user)

    ps = PlannedSession.objects.filter(course=course)
    nosessions = len(ps) == 0

    if nosessions:
        course.delete()

    url = reverse(courses_view)

    return HttpResponseRedirect(url)

@login_required()
@permission_required('course.change_course',fn=get_course_by_pk,raise_exception=True)
def course_edit_view(request,id=0):
    course = get_object_or_404(GeoCourse,pk=id)

    r = getrower(request.user)

    ps = PlannedSession.objects.filter(course=course)
    nosessions = len(ps) == 0

    script,div = course_map(course)

    if request.method == 'POST':
        form = GeoCourseEditForm(request.POST)
        if form.is_valid():
            name = form.cleaned_data['name']
            country = form.cleaned_data['country']
            notes = form.cleaned_data['notes']

            course.name = name
            course.country = country
            course.notes = notes
            course.save()

    form = GeoCourseEditForm(instance=course)

    breadcrumbs = [
        {
            'url': reverse('virtualevents_view'),
            'name': 'Challenges'
        },
        {
            'url': reverse(courses_view),
            'name': 'Courses'
        },
        {
            'url': reverse(course_view,kwargs={'id':course.id}),
            'name': course.name
        },
        {
            'url': reverse(course_edit_view,kwargs={'id':course.id}),
            'name': 'Edit'
            }
        ]

    return render(request, 'course_edit_view.html',
                  {
                      'course':course,
                      'active':'nav-racing',
                      'breadcrumbs':breadcrumbs,
                      'mapscript':script,
                      'mapdiv':div,
                      'nosessions':nosessions,
                      'rower':r,
                      'form':form,
                      }
                  )

#@login_required()
def course_view(request,id=0):
    try:
        course = GeoCourse.objects.get(id=id)
    except GeoCourse.DoesNotExist:
        return Http404("Course doesn't exist")

    r = getrower(request.user)

    script,div = course_map(course)

    breadcrumbs = [
        {
            'url': reverse('virtualevents_view'),
            'name': 'Challenges'
        },
        {
            'url': reverse(courses_view),
            'name': 'Courses'
        },
        {
            'url': reverse(course_view,kwargs={'id':course.id}),
            'name': course.name
        },
        ]

    return render(request, 'course_view.html',
                  {
                      'active':'nav-racing',
                      'breadcrumbs':breadcrumbs,
                      'course':course,
                      'mapscript':script,
                      'mapdiv':div,
                      'nosessions':False,
                      'rower':r,
                      }
                  )

def standard_view(request,id=0):
    try:
        collection = StandardCollection.objects.get(id=id)
    except StandardCollection.DoesNotExist:
        return Http404("Standard Collection does not exist")

    r = getrower(request.user)

    orderby = request.GET.get('order_by')

    if orderby is not None:
        standards = CourseStandard.objects.filter(
            standardcollection=collection
            ).order_by(orderby,"-referencespeed","agemax","agemin","sex","name")
    else:
        standards = CourseStandard.objects.filter(
            standardcollection=collection
            ).order_by("-referencespeed","agemax","agemin","sex","name")

    breadcrumbs = [
        {
            'url': reverse('virtualevents_view'),
            'name': 'Challenges'
        },
        {
            'url': reverse(standards_view),
            'name': 'Standards'
        },
        {
            'url': reverse(standard_view,kwargs={'id':collection.id}),
            'name': collection.name
        },
        ]

    return render(request, 'standard_view.html',
                  {
                  'active':'nav-racing',
                  'breadcrumbs':breadcrumbs,
                  'collection':collection,
                  'standards':standards,
                  'rower':r,
     }
                  )

@login_required()
@permission_required('racelogo.delete_logo',fn=get_logo_by_pk,raise_exception=True)
def logo_delete_view(request,id=0):
    logo = get_object_or_404(RaceLogo,pk=id)


    if logo.user == request.user:
        logo.delete()
        messages.info(request,"Logo Deleted")

    url = reverse('virtualevents_view')

    return HttpResponseRedirect(url)

@login_required()
@permission_required('virtualevent.change_race',fn=get_virtualevent_by_pk,raise_exception=True)
def virtualevent_setlogo_view(request,id=0,logoid=0):
    race = get_object_or_404(VirtualRace,pk=id)
    logo = get_object_or_404(RaceLogo,pk=logoid)

    otherlogos = race.logos.all()
    for otherlogo in otherlogos:
        otherlogo.race.remove(race)


    logo.race.add(race)
    logo.save()

    url = reverse('virtualevent_view',
                  kwargs={'id':id})

    return HttpResponseRedirect(url)

# Image upload to virtual event
@login_required()
def virtualevent_uploadimage_view(request,id=0):
    is_ajax = False
    if request.is_ajax():
        is_ajax = True

    r = getrower(request.user)

    race = get_object_or_404(VirtualRace,pk=id)

    logos = RaceLogo.objects.filter(user=request.user).order_by("-creationdatetime")

    breadcrumbs = [
        {
            'url': reverse('virtualevents_view'),
            'name': 'Challenges'
            },
        {
            'url': reverse('virtualevent_view',kwargs={'id':id}),
            'name': race.name
            },
        {
            'url': reverse(virtualevent_uploadimage_view,
                           kwargs={'id':id}),
            'name': 'Add Image'
            }
        ]

    if request.method == 'POST':
        if len(logos) >= 6:
            messages.error(request,"You cannot have more than 6 logos")
            url = reverse(virtualevent_imageupload_view,
                          kwargs={'id':id})

            return HttpResponseRedirect(url)

        form = ImageForm(request.POST, request.FILES)
        if form.is_valid():
            f = form.cleaned_data['file']

            if f is not None:
                filename, path_and_filename = handle_uploaded_image(f)
                try:
                    width, height = Image.open(path_and_filename).size
                except:
                    message = "Not a valid image"
                    messages.error(request,message)
                    os.remove(path_and_filename)
                    url = reverse(virtualevent_image_view,
                                  kwargs={'id':id})

                    if is_ajax:
                        return JSONResponse({'result':0, 'url':0})
                    else:
                        return HttpResponseRedirect(url)

                otherlogos = race.logos.all()
                for logo in otherlogos:
                    logo.race.remove(race)

                logo = RaceLogo(user = request.user,
                                creationdatetime=timezone.now(),
                                filename = path_and_filename,
                                width=width, height=height)
                logo.save()
                logo.race.add(race)
                logo.save()


                url = reverse('virtualevent_view',
                              kwargs={'id':id})

                if is_ajax:
                    return JSONResponse({'result':1, 'url':url})
                else:
                    return HttpResponseRedirect(url)
            else:
                messages.error(request,"Something went wrong - no file attached")
                url = reverse(virtualevent_uploadimage_view,
                              kwargs = {'id':id})

                if is_ajax:
                    return JSONResponse({'result':0,'url':1})
                else:
                    return HttpResponseRedirect(url)
    else:

        form = ImageForm()


    if is_ajax:
        return {'result':0}


    return render(request,'logo_form.html',
                  {'form':form,
                   'rower':r,
                   'logos':logos,
                   'active':'nav-racing',
                   'breadcrumbs':breadcrumbs,
                   'race':race,
                  })


# Course upload
@login_required()
def course_upload_view(request):
    is_ajax = False
    if request.is_ajax():
        is_ajax = True

    r = getrower(request.user)

    if request.method == 'POST':
        form = CourseForm(request.POST,request.FILES)

        if form.is_valid():
            f = form.cleaned_data['file']
            name = form.cleaned_data['name']
            notes = form.cleaned_data['notes']
            if f is not None:
                filename,path_and_filename = handle_uploaded_file(f)

                cs = courses.kmltocourse(path_and_filename)


                for course in cs:
                    cname = name+' - '+course['name']
                    cnotes = notes+'\n\n'+course['description']
                    polygons = course['polygons']

                    course = courses.createcourse(r,cname,polygons,notes=cnotes)

                os.remove(path_and_filename)

                url = reverse(courses_view)
                if is_ajax:
                    return JSONResponse({'result':1,'url':url})
                else:
                    return HttpResponseRedirect(url)
            else:
                messages.error(request,'Something went wrong - no file attached')
                url = reverse(course_upload_view)

                if is_ajax:
                    return JSONResponse({'result':0,'url':0})
                else:
                    return HttpResponseRedirect(url)
        else:
            messages.error(request,'Form is not valid')
            return render(request,'course_form.html',
                          {'form':form,
                           })

    else:
        if not is_ajax:
            form = CourseForm()
            return render(request,'course_form.html',
                          {'form':form,
                           'active':'nav-racing',
                           })
        else:
            return {'result':0}

# Standards deactivate
@login_required()
def standard_deactivate_view(request,id=0):
    is_ajax = False
    if request.is_ajax():
        is_ajax = True

    r = getrower(request.user)

    try:
        collection = StandardCollection.objects.get(id=id)
    except StandardCollection.DoesNotExist:
        raise Http404("Does not exist")

    if request.user != collection.manager:
        raise PermissionDenied("You cannot change this set of time standards")

    collection.active = False
    collection.save()

    url = reverse(standards_view)

    return HttpResponseRedirect(url)

def standards_download_view(request,id=0):
    try:
        collection = StandardCollection.objects.get(id=id)
    except StandardCollection.DoesNotExist:
        raise Http404("Does not exist")

    filename = 'Standard Times {name} {id} {date}.csv'.format(
        id=id,
        name=collection.name,
        date=timezone.now().strftime("%Y-%m-%d %H:%M:%S %Z")
        )

    standards = CourseStandard.objects.filter(standardcollection=collection)
    df = pd.DataFrame.from_records(standards.values())

    response = HttpResponse(df.to_csv())

    response['Content-Disposition'] = 'attachment; filename="%s"' % filename
    response['Content-Type'] = 'application/octet-stream'

    return response


# Standards upload
@login_required()
def standards_upload_view(request,id=0):
    is_ajax = False
    if request.is_ajax():
        is_ajax = True
        r = getrower(request.user)

    if id != 0:
        collection = StandardCollection.objects.get(id=id)
        if request.user != collection.manager:
            raise PermissionDenied("You cannot change this set of time standards")


    if request.method == 'POST':
        form = StandardsForm(request.POST,request.FILES)

        if form.is_valid():
            f = form.cleaned_data['file']
            name = form.cleaned_data['name']
            notes = form.cleaned_data['notes']
            if f is not None:
                filename,path_and_filename = handle_uploaded_file(f)

                id = save_scoring(name,request.user,path_and_filename,notes=notes,id=id)


                os.remove(path_and_filename)



                if id==0:
                    url = reverse(standards_view)
                else:
                    url = reverse(standard_view,kwargs={'id':id})

                if is_ajax:
                    return JSONResponse({'result':1,'url':url})

                return HttpResponseRedirect(url)

            else:
                messages.error(request,'Something went wrong - no file attached')
                url = reverse(standards_upload_view)
                if is_ajax:
                    return JSONResponse({'result':0,'url':0})

                return HttpResponseRedirect(url)
        else:
            messages.error(request,'Form is not valid')
            return render(request,'standard_form.html',
                          {'form':form,
                           'active':'nav-racing',
                           'id':id,
                           })

    else:
        if not is_ajax:
            form = StandardsForm()
            if id != 0:
                collection = StandardCollection.objects.get(id=id)
                form = StandardsForm(initial={
                    'name':collection.name,
                    'notes': collection.notes,
                })
            return render(request,'standard_form.html',
                          {'form':form,
                           'active':'nav-racing',
                           'id':id,
                           })
        return {'result':0}


def virtualevents_view(request):
    is_ajax = False
    if request.is_ajax():
        is_ajax = True

    # default races
    races1 = VirtualRace.objects.filter(
        startdate__gte=datetime.date.today(),
    )
    races2 = VirtualRace.objects.filter(
        startdate__lte=datetime.date.today(),
        evaluation_closure__gte=timezone.now()-datetime.timedelta(days=3),
    )


    races = (races1 | races2).order_by("startdate","start_time")

    if len(races) == 0:
        races = VirtualRace.objects.all().order_by("-startdate")

    if not request.user.is_anonymous:
        r = getrower(request.user)
    else:
        r = None

    if request.method == 'POST':
        # process form
        form = VirtualRaceSelectForm(request.POST)
        if form.is_valid():
            cd = form.cleaned_data
            country = cd['country']
            regattatype = cd['regattatype']
            if country == 'All':
                countries = VirtualRace.objects.order_by('country').values_list('country').distinct()
            else:
                countries = [country,
                             'Indoor']

            if regattatype == 'upcoming':
                races1 = VirtualRace.objects.filter(
                    startdate__gte=datetime.date.today(),
                    country__in=countries
                )
                races2 = VirtualRace.objects.filter(
                    startdate__lte=datetime.date.today(),
                    evaluation_closure__gte=timezone.now(),
                    country__in=countries
                    )


                races = (races1 | races2).order_by("startdate","start_time")


            elif regattatype == 'previous':
                races = VirtualRace.objects.filter(
                    evaluation_closure__lt=timezone.now(),
                    country__in=countries
                    ).order_by("-startdate","-start_time")
            elif regattatype == 'ongoing':
                races = VirtualRace.objects.filter(
                    startdate__lte=datetime.date.today(),
                    evaluation_closure__gte=timezone.now(),
                    country__in=countries
                    ).order_by("startdate","start_time")
            elif regattatype == 'my':
                mysessions = get_my_session_ids(r)
                races = VirtualRace.objects.filter(
                    id__in=mysessions,
                    country__in=countries
                    ).order_by("startdate","start_time")
            elif regattatype == 'all':
                races = VirtualRace.objects.filter(
                    country__in=countries
                    ).order_by("startdate","start_time")
    else:
        form = VirtualRaceSelectForm()

    if is_ajax:
        return render(request,'racelist.html',
                      { 'races':races,
                        'rower':r,
                        })

    breadcrumbs = [
        {
            'url':reverse('virtualevents_view'),
            'name': 'Challenges'
            },
        ]

    return render(request,'virtualevents.html',
                  { 'races':races,
                    'form':form,
                    'breadcrumbs':breadcrumbs,
                    'active':'nav-racing',
                    'rower':r,
                  }
    )

@login_required()
@permission_required('virtualevent.change_race',fn=get_virtualevent_by_pk,raise_exception=True)
def virtualevent_disqualify_view(request,id=0,recordid=0):

    r = getrower(request.user)
    race = get_object_or_404(VirtualRace,pk=id)


    if race.sessiontype == 'race':
        recordobj = VirtualRaceResult
    else:
        recordobj = IndoorVirtualRaceResult

    # datum moet voor race evaluation date zijn (ook in template controleren)

    try:
        record = recordobj.objects.get(id=recordid)
    except recordobj.DoesNotExist:
        messages.error(request,"We couldn't find the record")

    if timezone.now() > race.evaluation_closure+datetime.timedelta(hours=1):
        messages.error(request,"The evaluation is already closed and the results are official")
        url = reverse('virtualevent_view',kwargs={'id':raceid})

        return HttpResponseRedirect(url)

    if request.method == 'POST':
        form = DisqualificationForm(request.POST)
        if form.is_valid():
            message = form.cleaned_data['message']
            reason = form.cleaned_data['reason']
            disqualifier = disqualifiers[reason]

            r = Rower.objects.get(id=record.userid)
            name = record.username

            job = myqueue(queue,handle_send_disqualification_email,
                          r.user.email, name,
                          disqualifier,message,race.name)

            messages.info(request,"We have invalidated the result for: "+str(record))

            record.coursecompleted = False
            record.startsecond = 0
            record.endsecond = 0
            record.save()

            url = reverse('virtualevent_view',kwargs={'id':raceid})

            return HttpResponseRedirect(url)

    else:
        form = DisqualificationForm(request.POST)

    workout = Workout.objects.get(id=record.workoutid)

    g = GraphImage.objects.filter(workout=workout).order_by("-creationdatetime")
    for i in g:
        try:
            width,height = Image.open(i.filename).size
            i.width = width
            i.height = height
            i.save()
        except:
            pass

    script, div = interactive_chart(record.workoutid)

    f1 = workout.csvfilename
    rowdata = rdata(f1)
    hascoordinates = 1
    if rowdata != 0:
        try:
            latitude = rowdata.df[' latitude']
            if not latitude.std():
                hascoordinates = 0
        except (KeyError, AttributeError):
            hascoordinates = 0
    else:
        hascoordinates = 0

    if hascoordinates:
        mapscript, mapdiv = leaflet_chart(rowdata.df[' latitude'],
                                          rowdata.df[' longitude'],
                                          workout.name)
    else:
        mapscript = ""
        mapdiv = ""

    breadcrumbs = [
        {
            'url':reverse('virtualevents_view'),
            'name': 'Challenges'
            },
        {
            'url':reverse('virtualevent_view',
                          kwargs={'id':race.id}),
            'name': race.name
            },
        {
            'url':reverse(virtualevent_disqualify_view,
                          kwargs={'id':id,
                                  'recordid':recordid}),
            'name': 'Disqualify Entry'
            },
        ]

    buttons = []

    if not request.user.is_anonymous:
        if race_can_register(r,race):
            buttons += ['registerbutton']

        if race_can_adddiscipline(r,race):
            buttons += ['adddisciplinebutton']

        if race_can_submit(r,race):
            buttons += ['submitbutton']

        if race_can_resubmit(r,race):
            buttons += ['resubmitbutton']

        if race_can_withdraw(r,race):
            buttons += ['withdrawbutton']

        if race_can_edit(r,race):
            buttons += ['editbutton']

    return render(request,"disqualification_view.html",
                  {'workout':workout,
                   'active':'nav-racing',
                   'graphs':g,
                   'buttons':buttons,
                   'interactiveplot':script,
                   'the_div':div,
                   'mapscript':mapscript,
                   'mapdiv':mapdiv,
                   'form':form,
                   'race':race,
                   'record':record,
                   })

@login_required()
def virtualevent_withdrawresult_view(request,id=0,recordid=0):

    r = getrower(request.user)
    race = get_object_or_404(VirtualRace,pk=id)


    if race.sessiontype == 'race':
        recordobj = VirtualRaceResult
    else:
        recordobj = IndoorVirtualRaceResult

    # datum moet voor race evaluation date zijn (ook in template controleren)

    try:
        record = recordobj.objects.get(id=recordid)
    except recordobj.DoesNotExist:
        messages.error(request,"We couldn't find the record")

    if r.id != record.userid:
        raise PermissionDenied("You are not the owner of this result")

    if timezone.now() > race.evaluation_closure+datetime.timedelta(hours=1):
        messages.error(request,"The evaluation is already closed and the results are official")
        url = reverse('virtualevent_view',kwargs={'id':raceid})

        return HttpResponseRedirect(url)

    if request.method == 'POST':
        form = DisqualificationForm(request.POST)
        if form.is_valid():
            message = form.cleaned_data['message']
            reason = form.cleaned_data['reason']
            disqualifier = disqualifiers[reason]

            r = Rower.objects.get(id=record.userid)
            name = record.username

            job = myqueue(queue,handle_send_withdraw_email,
                          r.user.email, name,
                          disqualifier,message,race.name)

            messages.info(request,"We have invalidated the result for: "+str(record))

            record.coursecompleted = False
            record.startsecond = 0
            record.endsecond = 0
            record.save()

            url = reverse('virtualevent_view',kwargs={'id':id})

            return HttpResponseRedirect(url)

    else:
        form = DisqualificationForm(request.POST)

    try:
        workout = Workout.objects.get(id=record.workoutid)
        g = GraphImage.objects.filter(workout=workout).order_by("-creationdatetime")
        for i in g:
            try:
                width,height = Image.open(i.filename).size
                i.width = width
                i.height = height
                i.save()
            except:
                pass

        script, div = interactive_chart(record.workoutid)

        f1 = workout.csvfilename
        rowdata = rdata(f1)
        hascoordinates = 1
        if rowdata != 0:
            try:
                latitude = rowdata.df[' latitude']
                if not latitude.std():
                    hascoordinates = 0
            except (KeyError, AttributeError):
                hascoordinates = 0
        else:
            hascoordinates = 0

        if hascoordinates:
            mapscript, mapdiv = leaflet_chart(rowdata.df[' latitude'],
                                              rowdata.df[' longitude'],
                                              workout.name)
        else:
            mapscript = ""
            mapdiv = ""
    except Workout.DoesNotExist:
        mapscript = ""
        mapdiv = ""
        workout = None
        script = ""
        div = ""
        g = None



    breadcrumbs = [
        {
            'url':reverse('virtualevents_view'),
            'name': 'Challenges'
            },
        {
            'url':reverse('virtualevent_view',
                          kwargs={'id':race.id}),
            'name': race.name
            },
        {
            'url':reverse(virtualevent_disqualify_view,
                          kwargs={'id':id,
                                  'recordid':recordid}),
            'name': 'Disqualify Entry'
            },
        ]

    buttons = []

    if not request.user.is_anonymous:
        if race_can_register(r,race):
            buttons += ['registerbutton']

        if race_can_adddiscipline(r,race):
            buttons += ['adddisciplinebutton']

        if race_can_submit(r,race):
            buttons += ['submitbutton']

        if race_can_resubmit(r,race):
            buttons += ['resubmitbutton']

        if race_can_withdraw(r,race):
            buttons += ['withdrawbutton']

        if race_can_edit(r,race):
            buttons += ['editbutton']

    return render(request,"withdraw_view.html",
                  {'workout':workout,
                   'active':'nav-racing',
                   'graphs':g,
                   'buttons':buttons,
                   'interactiveplot':script,
                   'the_div':div,
                   'mapscript':mapscript,
                   'mapdiv':mapdiv,
                   'form':form,
                   'race':race,
                   'record':record,
                   })


def virtualevent_view(request,id=0):

    results = []

    if not request.user.is_anonymous:
        r = getrower(request.user)
    else:
        r = None


    try:
        race = VirtualRace.objects.get(id=id)
    except VirtualRace.DoesNotExist:
        raise Http404("Virtual Challenge does not exist")

    if race.sessiontype == 'race':
        script,div = course_map(race.course)
        resultobj = VirtualRaceResult
    else:
        script = ''
        div = ''
        resultobj = IndoorVirtualRaceResult

    records = resultobj.objects.filter(race=race)


    buttons = []

    # to-do - add DNS
    dns = []
    if timezone.now() > race.evaluation_closure:
        dns = resultobj.objects.filter(
            race=race,
            workoutid__isnull=True,
        )


    if not request.user.is_anonymous:
        if race_can_register(r,race):
            buttons += ['registerbutton']

        if race_can_adddiscipline(r,race):
            buttons += ['adddisciplinebutton']

        if race_can_submit(r,race):
            buttons += ['submitbutton']

        if race_can_resubmit(r,race):
            buttons += ['resubmitbutton']

        if race_can_withdraw(r,race):
            buttons += ['withdrawbutton']

        if race_can_edit(r,race):
            buttons += ['editbutton']

    if request.method == 'POST':
        form = RaceResultFilterForm(request.POST,records=records)
        if form.is_valid():
            cd = form.cleaned_data
            try:
                sex = cd['sex']
            except KeyError:
                sex = ['female','male','mixed']

            try:
                boattype = cd['boattype']
            except KeyError:
                boattype = mytypes.waterboattype

            try:
                boatclass = cd['boatclass']
            except KeyError:
                if race.sessiontype == 'race':
                    boatclass = [t for t in mytypes.otwtypes]
                else:
                    boatclass = [t for t in mytypes.otetypes]

            age_min = cd['age_min']
            age_max = cd['age_max']

            try:
                weightcategory = cd['weightcategory']
            except KeyError:
                weightcategory = ['hwt','lwt']

            try:
                adaptiveclass = cd['adaptiveclass']
            except KeyError:
                adaptiveclass = ['None','PR1','PR2','PR3','FES']

            try:
                entrycategory = cd['entrycategory']
            except KeyError:
                entrycategory = None

            if race.sessiontype == 'race':
                results = resultobj.objects.filter(
                    race=race,
                    workoutid__isnull=False,
                    boatclass__in=boatclass,
                    boattype__in=boattype,
                    sex__in=sex,
                    weightcategory__in=weightcategory,
                    adaptiveclass__in=adaptiveclass,
                    age__gte=age_min,
                    age__lte=age_max,
                ).order_by("duration")
            else:
                results = resultobj.objects.filter(
                    race=race,
                    workoutid__isnull=False,
                    boatclass__in=boatclass,
                    sex__in=sex,
                    weightcategory__in=weightcategory,
                    adaptiveclass__in=adaptiveclass,
                    age__gte=age_min,
                    age__lte=age_max,
                ).order_by("duration","-distance")

            if entrycategory is not None:
                results = results.filter(entrycategory__in=entrycategory)

            # to-do - add DNS
            dns = []
            if timezone.now() > race.evaluation_closure:
                dns = resultobj.objects.filter(
                    race=race,
                    workoutid__isnull=True,
                    boatclass__in=boatclass,
                    sex__in=sex,
                    weightcategory__in=weightcategory,
                    adaptiveclass__in=adaptiveclass,
                    age__gte=age_min,
                    age__lte=age_max
                )
    else:
        results = resultobj.objects.filter(
            race=race,
            workoutid__isnull=False,
            coursecompleted=True,
        ).order_by("duration","-distance")

        if results:
            form = RaceResultFilterForm(records=records)
        else:
            form = None

    breadcrumbs = [
        {
            'url':reverse('virtualevents_view'),
            'name': 'Challenges'
            },
        {
            'url':reverse('virtualevent_view',
                          kwargs={'id':race.id}
                          ),
            'name': race.name
            }
        ]

    orderby = request.GET.get('order_by')
    if orderby is not None:
        results = results.order_by(orderby)

    racelogos = race.logos.all()

    if racelogos:
        racelogo = racelogos[0]
    else:
        racelogo = None

    comments = PlannedSessionComment.objects.filter(plannedsession=race).order_by("created")


    return render(request,'virtualevent.html',
                  {
                      'coursescript':script,
                      'coursediv':div,
                      'breadcrumbs':breadcrumbs,
                      'race':race,
                      'rower':r,
                      'results':results,
                      'buttons':buttons,
                      'dns':dns,
                      'records':records,
                      'racelogo':racelogo,
                      'form':form,
                      'active':'nav-racing',
                      'comments':comments
                      })

def do_encode(x):
    try:
        return encoder.encode_hex(int(x))
    except:
        return x

@login_required()
@permission_required('virtualevent.change_race',fn=get_virtualevent_by_pk,raise_exception=True)
def virtualevent_results_download_view(request,id=0):
    r = getrower(request.user)

    try:
        race = VirtualRace.objects.get(id=id)
    except VirtualRace.DoesNotExist:
        raise Http404("Virtual Challenge does not exist")

    if race.sessiontype == 'race':
        resultobj = VirtualRaceResult
    else:
        resultobj = IndoorVirtualRaceResult

    records = resultobj.objects.filter(race=race)

    filename = 'Challenge Results {name} {id} {date}.csv'.format(
        id=id,
        name=race.name,
        date=timezone.now().strftime("%Y-%m-%d %H:%M:%S %Z")
        )

    df = pd.DataFrame.from_records(records.values())
    df['workoutid'] = df['workoutid'].apply(lambda x:do_encode(x))

    response = HttpResponse(df.to_csv())

    response['Content-Disposition'] = 'attachment; filename="%s"' % filename
    response['Content-Type'] = 'application/octet-stream'

    return response


def virtualevent_ranking_view(request,id=0):

    results = []

    if not request.user.is_anonymous:
        r = getrower(request.user)
    else:
        r = None


    try:
        race = VirtualRace.objects.get(id=id)
    except VirtualRace.DoesNotExist:
        raise Http404("Virtual Challenge does not exist")

    if race.sessiontype == 'race':
        script,div = course_map(race.course)
        resultobj = VirtualRaceResult
    else:
        script = ''
        div = ''
        resultobj = IndoorVirtualRaceResult

    records = resultobj.objects.filter(race=race)


    buttons = []

    # to-do - add DNS
    dns = []
    if timezone.now() > race.evaluation_closure:
        dns = resultobj.objects.filter(
            race=race,
            workoutid__isnull=True,
        )


    if not request.user.is_anonymous:
        if race_can_register(r,race):
            buttons += ['registerbutton']

        if race_can_adddiscipline(r,race):
            buttons += ['adddisciplinebutton']

        if race_can_submit(r,race):
            buttons += ['submitbutton']

        if race_can_resubmit(r,race):
            buttons += ['resubmitbutton']

        if race_can_withdraw(r,race):
            buttons += ['withdrawbutton']

        if race_can_edit(r,race):
            buttons += ['editbutton']

    if request.method == 'POST':
        form = RaceResultFilterForm(request.POST,records=records)
        if form.is_valid():
            cd = form.cleaned_data
            try:
                sex = cd['sex']
            except KeyError:
                sex = ['female','male','mixed']

            try:
                boattype = cd['boattype']
            except KeyError:
                boattype = mytypes.waterboattype

            try:
                boatclass = cd['boatclass']
            except KeyError:
                if race.sessiontype == 'race':
                    boatclass = [t for t in mytypes.otwtypes]
                else:
                    boatclass = [t for t in mytypes.otetypes]

            age_min = cd['age_min']
            age_max = cd['age_max']

            try:
                weightcategory = cd['weightcategory']
            except KeyError:
                weightcategory = ['hwt','lwt']

            try:
                adaptiveclass = cd['adaptiveclass']
            except KeyError:
                adaptiveclass = ['None','PR1','PR2','PR3','FES']

            if race.sessiontype == 'race':
                results = resultobj.objects.filter(
                    race=race,
                    workoutid__isnull=False,
                    boatclass__in=boatclass,
                    boattype__in=boattype,
                    sex__in=sex,
                    weightcategory__in=weightcategory,
                    adaptiveclass__in=adaptiveclass,
                    age__gte=age_min,
                    age__lte=age_max
                ).order_by("duration")
            else:
                results = resultobj.objects.filter(
                    race=race,
                    workoutid__isnull=False,
                    boatclass__in=boatclass,
                    sex__in=sex,
                    weightcategory__in=weightcategory,
                    adaptiveclass__in=adaptiveclass,
                    age__gte=age_min,
                    age__lte=age_max
                ).order_by("duration","-distance")


            # to-do - add DNS
            dns = []
            if timezone.now() > race.evaluation_closure:
                dns = resultobj.objects.filter(
                    race=race,
                    workoutid__isnull=True,
                    boatclass__in=boatclass,
                    sex__in=sex,
                    weightcategory__in=weightcategory,
                    adaptiveclass__in=adaptiveclass,
                    age__gte=age_min,
                    age__lte=age_max
                )
    else:
        results = resultobj.objects.filter(
            race=race,
            workoutid__isnull=False,
            coursecompleted=True,
        ).order_by("duration","-distance")

        if results:
            form = RaceResultFilterForm(records=records)
        else:
            form = None



    breadcrumbs = [
        {
            'url':reverse('virtualevents_view'),
            'name': 'Challenges'
            },
        {
            'url':reverse('virtualevent_view',
                          kwargs={'id':race.id}
                          ),
            'name': race.name
            }
        ]

    racelogos = race.logos.all()

    if racelogos:
        racelogo = racelogos[0]
    else:
        racelogo = None

    return render(request,'virtualeventranking.html',
                  {
                      'coursescript':script,
                      'coursediv':div,
                      'breadcrumbs':breadcrumbs,
                      'race':race,
                      'rower':r,
                      'results':results,
                      'buttons':buttons,
                      'dns':dns,
                      'records':records,
                      'racelogo':racelogo,
                      'form':form,
                      'active':'nav-racing',
                      })


@login_required()
def virtualevent_withdraw_view(request,id=0,recordid=None):
    r = getrower(request.user)

    try:
        race = VirtualRace.objects.get(id=id)
    except VirtualRace.DoesNotExist:
        raise Http404("Virtual Challenge does not exist")

    if race_can_withdraw(r,race):
        remove_rower_race(r,race,recordid=recordid)
        messages.info(request,
                      "You have successfully withdrawn from this race.")
    else:
        messages.error(request,"You cannot withdraw from this race")

    url = reverse('virtualevent_view',
                  kwargs = {
                      'id':race.id
                      })

    return HttpResponseRedirect(url)

@login_required()
def virtualevent_addboat_view(request,id=0):
    r = getrower(request.user)
    try:
        race = VirtualRace.objects.get(id=id)
    except VirtualRace.DoesNotExist:
        raise Http404("Virtual Challenge does not exist")

    categories = None
    if race.coursestandards is not None:
        categories = CourseStandard.objects.filter(
            standardcollection=race.coursestandards).order_by("name")


    if not race_can_adddiscipline(r,race):
        messages.error(request,"You cannot register for this race")

        url = reverse('virtualevent_view',
                      kwargs = {
                          'id':race.id
                      })

        return HttpResponseRedirect(url)

    records = VirtualRaceResult.objects.filter(
        userid = r.id,
        race = race
        )

    boattypes = [record.boattype for record in records]
    boatclasses = [record.boatclass for record in records]
    allowedboats = tuple([ type for type in mytypes.boattypes if type[0] not in boattypes] )


    # we're still here
    if request.method == 'POST':
        # process form
        form = VirtualRaceResultForm(request.POST,categories=categories)
        if form.is_valid():
            cd = form.cleaned_data
            teamname = cd['teamname']
            boattype = cd['boattype']
            boatclass = cd['boatclass']
            weightcategory = cd['weightcategory']
            adaptiveclass = cd['adaptiveclass']
            age = cd['age']
            mix = cd['mix']

            sex = r.sex
            if mix:
                sex = 'mixed'

            if boattype == '1x' and r.birthdate:
                age = calculate_age(r.birthdate)
                sex = r.sex

            if sex == 'not specified':
                sex = 'male'

            if boattype in boattypes and boatclass in boatclasses and race.coursestandards is None:
                # check if different sexes
                therecords = records.filter(
                    boattype=boattype,
                    boatclass=boatclass)

                thesexes = [record.sex for record in therecords]
                if sex in thesexes:

                    messages.error(
                        request,
                        "You have already registered in that boat class/type"
                    )
                    url = reverse('virtualevent_view',
                                  kwargs = {
                                      'id': race.id
                                  }
                              )

                    return HttpResponseRedirect(url)

            coursestandard = None
            referencespeed = 5.0

            if race.coursestandards is not None:
                coursestandard = cd['entrycategory']
                thegroups = [record.entrycategory for record in records]
                if coursestandard in thegroups:
                    messages.error(request,"You have already registered in that group")
                    url = reverse('virtualevent_view',
                                  kwargs = {
                                      'id': race.id
                                  }
                              )

                    return HttpResponseRedirect(url)

                referencespeed = coursestandard.referencespeed
                boattype = coursestandard.boattype
                boatclass = coursestandard.boatclass
                weightcategory = coursestandard.weightclass
                adaptiveclass = coursestandard.adaptiveclass
                skillclass = coursestandard.skillclass

                returnurl = reverse(virtualevent_register_view,
                                    kwargs={'id':race.id})

                if age < coursestandard.agemin:
                    messages.error(request,'You are younger than the minimum age for this group')
                    return HttpResponseRedirect(returnurl)

                if age > coursestandard.agemax:
                    messages.error(request,'You are older than the maximum age for this group')
                    return HttpResponseRedirect(returnurl)

                if sex == 'male' and coursestandard.sex != 'male':
                    messages.error(request,'Men are not allowed to enter this category')
                    return HttpResponseRedirect(returnurl)

                if sex == 'mixed' and coursestandard.sex not in ['mixed','male']:
                    messages.error(request,'Mixed crews are not allowed to enter this category')
                    return HttpResponseRedirect(returnurl)


            record = VirtualRaceResult(
                userid=r.id,
                teamname=teamname,
                race=race,
                username = u'{f} {l}'.format(
                    f = r.user.first_name,
                    l = r.user.last_name
                ),
                weightcategory=weightcategory,
                adaptiveclass=adaptiveclass,
                duration=datetime.time(0,0),
                boattype=boattype,
                boatclass=boatclass,
                coursecompleted=False,
                referencespeed=referencespeed,
                entrycategory=coursestandard,
                sex=sex,
                age=age,
                )

            record.save()

            add_rower_race(r,race)



            messages.info(
                request,
                "You have successfully registered for this race. Good luck!"
            )

            otherrecords = VirtualRaceResult.objects.filter(
                race = race).exclude(userid = r.id)

            for otherrecord in otherrecords:
                otheruser = Rower.objects.get(id=otherrecord.userid)
                othername = otheruser.user.first_name+' '+otheruser.user.last_name
                registeredname = r.user.first_name+' '+r.user.last_name
                if otherrecord.emailnotifications:
                    job = myqueue(
                        queue,
                        handle_sendemail_raceregistration,
                        otheruser.user.email, othername,
                        registeredname,
                        race.name,
                        race.id
                    )

            followers = VirtualRaceFollower.objects.filter(race = race)

            for follower in followers:
                othername = ''
                if follower.user:
                    othername = follower.user.first_name+' '+follower.user.last_name

                registeredname = r.user.first_name+' '+r.user.last_name
                email = follower.emailaddress
                job = myqueue(
                    queue,
                    handle_sendemail_raceregistration,
                    email, othername,
                    registeredname,race.name,race.id,
                    )

            url = reverse('virtualevent_view',
                          kwargs = {
                              'id':race.id
                          })

            return HttpResponseRedirect(url)

    else:
        initial = {
            'age': calculate_age(r.birthdate),
            'weightcategory': r.weightcategory,
            'adaptiveclass': r.adaptiveclass,
            }

        categories = None
        if race.coursestandards is not None:
            categories = CourseStandard.objects.filter(
                standardcollection=race.coursestandards).order_by("name")


        form = VirtualRaceResultForm(initial=initial,categories=categories)

    breadcrumbs = [
        {
            'url':reverse('virtualevents_view'),
            'name': 'Challenges'
            },
        {
            'url':reverse('virtualevent_view',
                          kwargs={'id':race.id}
                          ),
            'name': race.name
            },
        {
            'url': reverse('virtualevent_addboat_view',
                           kwargs = {'id':race.id}
                           ),
            'name': 'Add Discipline'
            }
        ]


    buttons = []

    if not request.user.is_anonymous:
        if race_can_register(r,race):
            buttons += ['registerbutton']

        if race_can_adddiscipline(r,race):
            buttons += ['adddisciplinebutton']

        if race_can_submit(r,race):
            buttons += ['submitbutton']

        if race_can_resubmit(r,race):
            buttons += ['resubmitbutton']

        if race_can_withdraw(r,race):
            buttons += ['withdrawbutton']

        if race_can_edit(r,race):
            buttons += ['editbutton']

    return render(request,'virtualeventregister.html',
                  {
                      'form':form,
                      'buttons':buttons,
                      'breadcrumbs':breadcrumbs,
                      'race':race,
                      'userid':r.user.id,
                      'active': 'nav-racing',
                  })

@login_required()
def virtualevent_register_view(request,id=0):
    r = getrower(request.user)
    try:
        race = VirtualRace.objects.get(id=id)
    except VirtualRace.DoesNotExist:
        raise Http404("Virtual Challenge does not exist")

    categories = None
    if race.coursestandards is not None:
        categories = CourseStandard.objects.filter(
            standardcollection=race.coursestandards).order_by("name")

    if not race_can_register(r,race):
        messages.error(request,"You cannot register for this race")

        url = reverse('virtualevent_view',
                      kwargs = {
                          'id':race.id
                      })

        return HttpResponseRedirect(url)

    # we're still here
    if request.method == 'POST':
        # process form
        form = VirtualRaceResultForm(request.POST,categories=categories)
        if form.is_valid():
            cd = form.cleaned_data
            teamname = cd['teamname']
            boattype = cd['boattype']
            boatclass = cd['boatclass']
            weightcategory = cd['weightcategory']
            adaptiveclass = cd['adaptiveclass']
            age = cd['age']
            mix = cd['mix']

            sex = r.sex
            if mix:
                sex = 'mixed'

            if boattype == '1x' and r.birthdate:
                age = calculate_age(r.birthdate)
                sex = r.sex

            if sex == 'not specified':
                sex = 'male'


            coursestandard = None
            referencespeed = 5.0

            if race.coursestandards is not None:
                coursestandard = cd['entrycategory']
                referencespeed = coursestandard.referencespeed
                boattype = coursestandard.boattype
                boatclass = coursestandard.boatclass
                weightcategory = coursestandard.weightclass
                adaptiveclass = coursestandard.adaptiveclass
                skillclass = coursestandard.skillclass

                returnurl = reverse(virtualevent_register_view,
                                    kwargs={'id':race.id})

                if age < coursestandard.agemin:
                    messages.error(request,'You are younger than the minimum age for this group')
                    return HttpResponseRedirect(returnurl)

                if age > coursestandard.agemax:
                    messages.error(request,'You are older than the maximum age for this group')
                    return HttpResponseRedirect(returnurl)

                if sex == 'male' and coursestandard.sex != 'male':
                    messages.error(request,'Men are not allowed to enter this category')
                    return HttpResponseRedirect(returnurl)

                if sex == 'mixed' and coursestandard.sex not in ['mixed','male']:
                    messages.error(request,'Mixed crews are not allowed to enter this category')
                    return HttpResponseRedirect(returnurl)



            record = VirtualRaceResult(
                userid=r.id,
                teamname=teamname,
                race=race,
                username = u'{f} {l}'.format(
                    f = r.user.first_name,
                    l = r.user.last_name
                ),
                weightcategory=weightcategory,
                adaptiveclass=adaptiveclass,
                duration=datetime.time(0,0),
                boatclass=boatclass,
                boattype=boattype,
                coursecompleted=False,
                sex=sex,
                age=age,
               entrycategory=coursestandard,
               referencespeed=referencespeed,
                )

            record.save()

            add_rower_race(r,race)

            # remove followers
            myfollows = VirtualRaceFollower.objects.filter(user=r.user,race=race)
            for f in myfollows:
                f.delete()

            otherrecords = VirtualRaceResult.objects.filter(
                race = race).exclude(userid = r.id)

            for otherrecord in otherrecords:
                otheruser = Rower.objects.get(id=otherrecord.userid)
                othername = otheruser.user.first_name+' '+otheruser.user.last_name
                registeredname = r.user.first_name+' '+r.user.last_name
                if otherrecord.emailnotifications:
                    job = myqueue(
                        queue,
                        handle_sendemail_raceregistration,
                        otheruser.user.email, othername,
                        registeredname,
                        race.name,
                        race.id
                    )

            followers = VirtualRaceFollower.objects.filter(race = race)

            for follower in followers:
                othername = ''
                if follower.user:
                    othername = follower.user.first_name+' '+follower.user.last_name

                registeredname = r.user.first_name+' '+r.user.last_name
                email = follower.emailaddress
                job = myqueue(
                    queue,
                    handle_sendemail_raceregistration,
                    email, othername,
                    registeredname,race.name,race.id,
                    )


            messages.info(
                request,
                "You have successfully registered for this race. Good luck!"
            )

            url = reverse('virtualevent_view',
                          kwargs = {
                              'id':race.id
                          })

            return HttpResponseRedirect(url)

    else:
        initial = {
            'age': calculate_age(r.birthdate),
            'weightcategory': r.weightcategory,
            'adaptiveclass': r.adaptiveclass,
            }

        categories = None
        if race.coursestandards is not None:
            categories = CourseStandard.objects.filter(
                standardcollection=race.coursestandards).order_by("name")

        form = VirtualRaceResultForm(initial=initial,categories=categories)

    breadcrumbs = [
        {
            'url':reverse('virtualevents_view'),
            'name': 'Challenges'
            },
        {
            'url':reverse('virtualevent_view',
                          kwargs={'id':race.id}
                          ),
            'name': race.name
            },
        {
            'url': reverse(virtualevent_register_view,
                           kwargs = {'id':race.id}
                           ),
            'name': 'Register'
            }
        ]

    buttons = []

    if not request.user.is_anonymous:
        if race_can_register(r,race):
            buttons += ['registerbutton']

        if race_can_adddiscipline(r,race):
            buttons += ['adddisciplinebutton']

        if race_can_submit(r,race):
            buttons += ['submitbutton']

        if race_can_resubmit(r,race):
            buttons += ['resubmitbutton']

        if race_can_withdraw(r,race):
            buttons += ['withdrawbutton']

        if race_can_edit(r,race):
            buttons += ['editbutton']

    return render(request,'virtualeventregister.html',
                  {
                      'form':form,
                      'buttons':buttons,
                      'breadcrumbs':breadcrumbs,
                      'race':race,
                      'userid':r.user.id,

                  })

@login_required()
def virtualevent_toggle_email_view(request,id=0):
    r = getrower(request.user)
    race = VirtualRace.objects.get(id=id)
    records = VirtualRaceResult.objects.filter(userid=r.id,race=race)

    if True in [record.emailnotifications for record in records]:
        newsetting = False
    else:
        newsetting = True

    for record in records:
        record.emailnotifications = newsetting
        record.save()

    url = reverse('virtualevent_view',
                  kwargs={'id':race.id})

    return HttpResponseRedirect(url)

@login_required()
def indoorvirtualevent_toggle_email_view(request,id=0):
    r = getrower(request.user)
    race = VirtualRace.objects.get(id=id)

    records = IndoorVirtualRaceResult.objects.filter(userid=r.id,
                                                     race=race)

    if True in [record.emailnotifications for record in records]:
        newsetting = False
    else:
        newsetting = True

    for record in records:
        record.emailnotifications = newsetting
        record.save()

    url = reverse('virtualevent_view',
                  kwargs={'id':race.id})

    return HttpResponseRedirect(url)

@login_required()
def indoorvirtualevent_register_view(request,id=0):
    r = getrower(request.user)
    try:
        race = VirtualRace.objects.get(id=id)
    except VirtualRace.DoesNotExist:
        raise Http404("Virtual Challenge does not exist")

    categories = None
    if race.coursestandards is not None:
        categories = CourseStandard.objects.filter(
            standardcollection=race.coursestandards).order_by("name")

    if not race_can_register(r,race):
        messages.error(request,"You cannot register for this race")

        url = reverse('virtualevent_view',
                      kwargs = {
                          'id':race.id
                      })

        return HttpResponseRedirect(url)

    # we're still here
    if request.method == 'POST':
        # process form
        form = IndoorVirtualRaceResultForm(request.POST,categories=categories)
        if form.is_valid():
            cd = form.cleaned_data
            teamname = cd['teamname']
            weightcategory = cd['weightcategory']
            adaptiveclass = cd['adaptiveclass']
            age = cd['age']
            boatclass = cd['boatclass']

            sex = r.sex

            if r.birthdate:
                age = calculate_age(r.birthdate)
                sex = r.sex

            if sex == 'not specified':
                sex = 'male'

            coursestandard = None
            referencespeed = 5.0

            if race.coursestandards is not None:
                coursestandard = cd['entrycategory']
                referencespeed = coursestandard.referencespeed
                boatclass = coursestandard.boatclass
                weightcategory = coursestandard.weightclass
                adaptiveclass = coursestandard.adaptiveclass
                skillclass = coursestandard.skillclass

                returnurl = reverse(virtualevent_register_view,
                                    kwargs={'id':race.id})

                if age < coursestandard.agemin:
                    messages.error(request,'You are younger than the minimum age for this group')
                    return HttpResponseRedirect(returnurl)

                if age > coursestandard.agemax:
                    messages.error(request,'You are older than the maximum age for this group')
                    return HttpResponseRedirect(returnurl)

                if sex == 'male' and coursestandard.sex != 'male':
                    messages.error(request,'Men are not allowed to enter this category')
                    return HttpResponseRedirect(returnurl)

                if sex == 'mixed' and coursestandard.sex not in ['mixed','male']:
                    messages.error(request,'Mixed crews are not allowed to enter this category')
                    return HttpResponseRedirect(returnurl)



            record = IndoorVirtualRaceResult(
                userid=r.id,
                teamname=teamname,
                race=race,
                username = u'{f} {l}'.format(
                    f = r.user.first_name,
                    l = r.user.last_name
                ),
                weightcategory=weightcategory,
                adaptiveclass=adaptiveclass,
                duration=datetime.time(0,0),
                boatclass=boatclass,
                coursecompleted=False,
                sex=sex,
                age=age,
                entrycategory=coursestandard,
                referencespeed=referencespeed
                )

            record.save()

            add_rower_race(r,race)

            # remove followers
            myfollows = VirtualRaceFollower.objects.filter(user=r.user,race=race)
            for f in myfollows:
                f.delete()

            otherrecords = IndoorVirtualRaceResult.objects.filter(
                race = race).exclude(userid = r.id)

            for otherrecord in otherrecords:
                otheruser = Rower.objects.get(id=otherrecord.userid)
                othername = otheruser.user.first_name+' '+otheruser.user.last_name
                registeredname = r.user.first_name+' '+r.user.last_name
                if otherrecord.emailnotifications:
                    job = myqueue(
                        queue,
                        handle_sendemail_raceregistration,
                        otheruser.user.email, othername,
                        registeredname,
                        race.name,
                        race.id
                    )

            followers = VirtualRaceFollower.objects.filter(race = race)

            for follower in followers:
                othername = ''
                if follower.user:
                    othername = follower.user.first_name+' '+follower.user.last_name

                registeredname = r.user.first_name+' '+r.user.last_name
                email = follower.emailaddress
                job = myqueue(
                    queue,
                    handle_sendemail_raceregistration,
                    email, othername,
                    registeredname,race.name,race.id,
                    )


            messages.info(
                request,
                "You have successfully registered for this race. Good luck!"
            )

            url = reverse('virtualevent_view',
                          kwargs = {
                              'id':race.id
                          })

            return HttpResponseRedirect(url)

    else:
        initial = {
            'age': calculate_age(r.birthdate),
            'weightcategory': r.weightcategory,
            'adaptiveclass': r.adaptiveclass,
            }

        categories = None
        if race.coursestandards is not None:
            categories = CourseStandard.objects.filter(
                standardcollection=race.coursestandards).order_by("name")

        form = IndoorVirtualRaceResultForm(initial=initial,categories=categories)

    breadcrumbs = [
        {
            'url':reverse('virtualevents_view'),
            'name': 'Challenges'
            },
        {
            'url':reverse('virtualevent_view',
                          kwargs={'id':race.id}
                          ),
            'name': race.name
            },
        {
            'url': reverse(indoorvirtualevent_register_view,
                           kwargs = {'id':race.id}
                           ),
            'name': 'Register'
            }
        ]

    buttons = []

    if not request.user.is_anonymous:
        if race_can_register(r,race):
            buttons += ['registerbutton']

        if race_can_adddiscipline(r,race):
            buttons += ['adddisciplinebutton']

        if race_can_submit(r,race):
            buttons += ['submitbutton']

        if race_can_resubmit(r,race):
            buttons += ['resubmitbutton']

        if race_can_withdraw(r,race):
            buttons += ['withdrawbutton']

        if race_can_edit(r,race):
            buttons += ['editbutton']

    return render(request,'virtualeventregister.html',
                  {
                      'form':form,
                      'buttons':buttons,
                      'race':race,
                      'breadcrumbs':breadcrumbs,
                      'userid':r.user.id,

                  })

@login_required()
def indoorvirtualevent_create_view(request):
    r = getrower(request.user)

    if request.method == 'POST':
        racecreateform = IndoorVirtualRaceForm(request.POST)
        if racecreateform.is_valid():
            cd = racecreateform.cleaned_data
            startdate = cd['startdate']
            start_time = cd['start_time']
            enddate = cd['enddate']
            end_time = cd['end_time']
            comment = cd['comment']
            sessionunit = cd['sessionunit']
            sessionvalue = cd['sessionvalue']
            name = cd['name']
            registration_form = cd['registration_form']
            registration_closure = cd['registration_closure']
            evaluation_closure = cd['evaluation_closure']
            contact_phone = cd['contact_phone']
            contact_email = cd['contact_email']
            coursestandards = cd['coursestandards']

            # correct times

            timezone_str = cd['timezone']

            startdatetime = datetime.datetime.combine(startdate,start_time)
            enddatetime = datetime.datetime.combine(enddate,end_time)


            startdatetime = pytz.timezone(timezone_str).localize(
                startdatetime
            )
            enddatetime = pytz.timezone(timezone_str).localize(
                enddatetime
            )
            evaluation_closure = pytz.timezone(timezone_str).localize(
                evaluation_closure.replace(tzinfo=None)
            )

            if registration_form == 'manual':
                try:
                    registration_closure = pytz.timezone(
                        timezone_str
                    ).localize(
                        registration_closure.replace(tzinfo=None)
                    )
                except AttributeError:
                    registration_closure = startdatetime
            elif registration_form == 'windowstart':
                registration_closure = startdatetime
            elif registration_form == 'windowend':
                registration_closure = enddatetime
            else:
                registration_closure = evaluation_closure

            if sessionunit == 'min':
                sessionmode = 'time'
            else:
                sessionmode = 'distance'

            vs = VirtualRace(
                name=name,
                startdate=startdate,
                preferreddate = startdate,
                start_time = start_time,
                enddate=enddate,
                end_time=end_time,
                comment=comment,
                sessiontype = 'indoorrace',
                sessionunit = sessionunit,
                sessionmode = sessionmode,
                sessionvalue = sessionvalue,
                course=None,
                timezone=timezone_str,
                coursestandards=coursestandards,
                evaluation_closure=evaluation_closure,
                registration_closure=registration_closure,
                contact_phone=contact_phone,
                contact_email=contact_email,
                country = 'Indoor',
                manager=request.user,
            )

            vs.save()

            # create Site Announcement & Tweet
            if settings.DEBUG or settings.TESTING:
                dotweet = False
            elif 'dev' in settings.SITE_URL:
                dotweet = False
            else:
                dotweet = True

            announcementshort = "New Virtual Indoor Challenge on rowsandall.com: {name}".format(
                name = name,
            )

            announcement = announcementshort + " {siteurl}/rowers/virtualevent/{raceid}/".format(
                siteurl = SITE_URL,
                raceid = vs.id
            )


            if len(announcement)>250:
                announcement = announcementshort

            sa = SiteAnnouncement(
                announcement = announcement,
                dotweet = dotweet
            )

            sa.save()

            url = reverse('virtualevents_view')
            return HttpResponseRedirect(url)
    else:

        racecreateform = IndoorVirtualRaceForm(timezone=r.defaulttimezone)


    breadcrumbs = [
        {
            'url':reverse('virtualevents_view'),
            'name': 'Challenges'
            },
        {
            'url':reverse('indoorvirtualevent_create_view',
                          ),
            'name': 'New Indoor Virtual Regatta'
            },
        ]

    return render(request,'indoorvirtualeventcreate.html',
                  {
                      'form':racecreateform,
                      'breadcrumbs':breadcrumbs,
                      'rower':r,
                      'active':'nav-racing',

                  })

@login_required()
def virtualevent_create_view(request):
    r = getrower(request.user)

    if request.method == 'POST':
        racecreateform = VirtualRaceForm(request.POST)
        if racecreateform.is_valid():
            cd = racecreateform.cleaned_data
            startdate = cd['startdate']
            start_time = cd['start_time']
            enddate = cd['enddate']
            end_time = cd['end_time']
            comment = cd['comment']
            course = cd['course']
            name = cd['name']
            registration_form = cd['registration_form']
            registration_closure = cd['registration_closure']
            evaluation_closure = cd['evaluation_closure']
            contact_phone = cd['contact_phone']
            contact_email = cd['contact_email']
            coursestandards = cd['coursestandards']

            # correct times

            geocourse = GeoCourse.objects.get(id= course.id)
            timezone_str = get_course_timezone(geocourse)

            startdatetime = datetime.datetime.combine(startdate,start_time)
            enddatetime = datetime.datetime.combine(enddate,end_time)


            startdatetime = pytz.timezone(timezone_str).localize(
                startdatetime
            )
            enddatetime = pytz.timezone(timezone_str).localize(
                enddatetime
            )
            evaluation_closure = pytz.timezone(timezone_str).localize(
                evaluation_closure.replace(tzinfo=None)
            )

            if registration_form == 'manual':
                try:
                    registration_closure = pytz.timezone(
                        timezone_str
                    ).localize(
                        registration_closure.replace(tzinfo=None)
                    )
                except AttributeError:
                    registration_closure = startdatetime
            elif registration_form == 'windowstart':
                registration_closure = startdatetime
            elif registration_form == 'windowend':
                registration_closure = enddatetime
            else:
                registration_closure = evaluation_closure


            vs = VirtualRace(
                name=name,
                startdate=startdate,
                preferreddate = startdate,
                start_time = start_time,
                enddate=enddate,
                end_time=end_time,
                course=geocourse,
                comment=comment,
                sessiontype = 'race',
                timezone=timezone_str,
                evaluation_closure=evaluation_closure,
                registration_closure=registration_closure,
                contact_phone=contact_phone,
                coursestandards=coursestandards,
                contact_email=contact_email,
                country = course.country,
                manager=request.user,
            )

            vs.save()

            # create Site Announcement & Tweet
            if settings.DEBUG or settings.TESTING:
                dotweet = False
            elif 'dev' in settings.SITE_URL:
                dotweet = False
            else:
                dotweet = True

            announcementshort = "New Virtual Challenge on rowsandall.com: {name} on course {course}".format(
                name = name,
                course = course.name,
            )

            announcement = announcementshort + " {siteurl}/rowers/virtualevent/{raceid}/".format(
                siteurl = SITE_URL,
                raceid = vs.id
            )


            if len(announcement)>250:
                announcement = announcementshort

            sa = SiteAnnouncement(
                announcement = announcement,
                dotweet = dotweet
            )

            sa.save()
            url = reverse('virtualevents_view')
            return HttpResponseRedirect(url)
    else:

        racecreateform = VirtualRaceForm()


    breadcrumbs = [
        {
            'url':reverse('virtualevents_view'),
            'name': 'Challenges'
            },
        {
            'url':reverse(virtualevent_create_view,
                          ),
            'name': 'New Virtual Regatta'
            },
        ]
    return render(request,'virtualeventcreate.html',
                  {
                      'form':racecreateform,
                      'breadcrumbs':breadcrumbs,
                      'rower':r,
                      'active':'nav-racing',

                  })

@login_required()
@permission_required('virtualevent.change_race',fn=get_virtualevent_by_pk,raise_exception=True)
def virtualevent_edit_view(request,id=0):
    r = getrower(request.user)
    race = get_object_or_404(VirtualRace,pk=id)



    start_time = race.start_time
    start_date = race.startdate
    startdatetime = datetime.datetime.combine(start_date,start_time)
    startdatetime = pytz.timezone(race.timezone).localize(
        startdatetime
        )

    if timezone.now() > startdatetime:
        messages.error(request,"You cannot edit a race after the start of the race window")
        url = reverse('virtualevent_view',
                      kwargs={
                          'id':race.id,
                          })

    if request.method == 'POST':
        racecreateform = VirtualRaceForm(request.POST,instance=race)
        if racecreateform.is_valid():
            cd = racecreateform.cleaned_data

            res, message = update_virtualrace(race,cd)

            if res:
                messages.info(request,message)
            else:
                messages.error(request,message)

            url = reverse('virtualevent_view',
                          kwargs = {
                              'id':race.id
                              })

            return HttpResponseRedirect(url)

    else:

        racecreateform = VirtualRaceForm(instance=race)

    breadcrumbs = [
        {
            'url':reverse('virtualevents_view'),
            'name': 'Challenges'
            },
        {
            'url':reverse('virtualevent_view',
                          kwargs={'id':race.id}
                          ),
            'name': race.name
            },
        {
            'url': reverse(virtualevent_edit_view,
                           kwargs = {'id':race.id}
                           ),
            'name': 'Edit'
            }
        ]

    buttons = []

    if not request.user.is_anonymous:
        if race_can_register(r,race):
            buttons += ['registerbutton']

        if race_can_adddiscipline(r,race):
            buttons += ['adddisciplinebutton']

        if race_can_submit(r,race):
            buttons += ['submitbutton']

        if race_can_resubmit(r,race):
            buttons += ['resubmitbutton']

        if race_can_withdraw(r,race):
            buttons += ['withdrawbutton']

        if race_can_edit(r,race):
            buttons += ['editbutton']

    return render(request,'virtualeventedit.html',
                  {
                      'form':racecreateform,
                      'breadcrumbs':breadcrumbs,
                      'buttons':buttons,
                      'rower':r,
                      'race':race,

                  })

@login_required()
@permission_required('virtualevent.change_race',fn=get_virtualevent_by_pk,raise_exception=True)
def indoorvirtualevent_edit_view(request,id=0):
    r = getrower(request.user)
    race = get_object_or_404(VirtualRace,pk=id)

    start_time = race.start_time
    start_date = race.startdate
    startdatetime = datetime.datetime.combine(start_date,start_time)
    startdatetime = pytz.timezone(race.timezone).localize(
        startdatetime
        )

    if timezone.now() > startdatetime:
        messages.error(request,"You cannot edit a race after the start of the race window")
        url = reverse('virtualevent_view',
                      kwargs={
                          'id':race.id,
                          })

    if request.method == 'POST':
        racecreateform = IndoorVirtualRaceForm(request.POST,instance=race)
        if racecreateform.is_valid():
            cd = racecreateform.cleaned_data

            res, message = update_indoorvirtualrace(race,cd)

            if res:
                messages.info(request,message)
            else:
                messages.error(request,message)

            url = reverse('virtualevent_view',
                          kwargs = {
                              'id':race.id
                              })

            return HttpResponseRedirect(url)

    else:

        racecreateform = IndoorVirtualRaceForm(instance=race)


    breadcrumbs = [
        {
            'url':reverse('virtualevents_view'),
            'name': 'Challenges'
            },
        {
            'url':reverse('virtualevent_view',
                          kwargs={'id':race.id}
                          ),
            'name': race.name
            },
        {
            'url': reverse(indoorvirtualevent_edit_view,
                           kwargs = {'id':race.id}
                           ),
            'name': 'Edit'
            }
        ]

    buttons = []

    if not request.user.is_anonymous:
        if race_can_register(r,race):
            buttons += ['registerbutton']

        if race_can_adddiscipline(r,race):
            buttons += ['adddisciplinebutton']

        if race_can_submit(r,race):
            buttons += ['submitbutton']

        if race_can_resubmit(r,race):
            buttons += ['resubmitbutton']

        if race_can_withdraw(r,race):
            buttons += ['withdrawbutton']

        if race_can_edit(r,race):
            buttons += ['editbutton']


    return render(request,'virtualeventedit.html',
                  {
                      'form':racecreateform,
                      'buttons':buttons,
                      'breadcrumbs':breadcrumbs,
                      'rower':r,
                      'race':race,

                  })


@login_required()
def virtualevent_submit_result_view(request,id=0,workoutid=0):

    r = getrower(request.user)

    try:
        race = VirtualRace.objects.get(id=id)
    except VirtualRace.DoesNotExist:
        raise Http404("Virtual Challenge does not exist")

    start_time = race.start_time
    start_date = race.startdate
    startdatetime = datetime.datetime.combine(start_date, start_time)
    startdatetime = pytz.timezone(race.timezone).localize(startdatetime)

    end_time = race.end_time
    end_date = race.enddate
    enddatetime = datetime.datetime.combine(end_date, end_time)
    enddatetime = pytz.timezone(race.timezone).localize(enddatetime)

    can_submit = race_can_submit(r,race) or race_can_resubmit(r,race)

    if race.sessiontype == 'race':
        resultobj = VirtualRaceResult
    else:
        resultobj = IndoorVirtualRaceResult

    records = resultobj.objects.filter(
        userid = r.id,
        race=race
        )


    entrychoices = []

    for record in records:
        rtpl = (record.id, record.__str__())
        entrychoices.append(rtpl)

    entries = {}
    entries['choices'] = entrychoices
    entries['initial'] = [records[0].id]

    if not can_submit:
        messages.error(request,'You cannot submit a result to this race')
        url = reverse('virtualevent_view',
                      kwargs = {
                          'id':id
                          }
                      )
        return HttpResponseRedirect(url)

    ws = Workout.objects.filter(
        user=r,
        workouttype__in=mytypes.rowtypes,
        startdatetime__gte=startdatetime,
        startdatetime__lte=enddatetime,
        ).order_by("date","startdatetime","id")

    if not ws:
        messages.info(
            request,
            'You have no workouts executed during the race window. Please upload a result or enter it manually.'
        )

        url = reverse('virtualevent_view',
                      kwargs = {
                          'id':id
                          })

        return HttpResponseRedirect(url)


    initialworkouts = [w.id for w in Workout.objects.filter(
        user=r,plannedsession=race
    )]

    workoutdata = {}
    workoutdata['initial'] = []

    choices = []

    for w in ws:
        wtpl = (w.id, w.__str__())
        choices.append(wtpl)
        if w.id in initialworkouts:
            workoutdata['initial'].append(w.id)

    workoutdata['choices'] = tuple(choices)

    if request.method == 'POST':
        w_form = WorkoutRaceSelectForm(workoutdata,entries,request.POST)

        if w_form.is_valid():
            selectedworkout = w_form.cleaned_data['workouts']
            splitsecond = 0
            recordid = w_form.cleaned_data['record']
        else:
            selectedworkout = None


        if selectedworkout is not None:


            workouts = Workout.objects.filter(id=selectedworkout)
            if race.sessiontype == 'race':
                result,comments,errors,jobid = add_workout_race(
                    workouts,race,r,
                    splitsecond=splitsecond,recordid=recordid)
            else:
                result,comments,errors,jobid = add_workout_indoorrace(
                    workouts,race,r,recordid=recordid)


            for c in comments:
                messages.info(request,c)
            for er in errors:
                messages.error(request,er)

            if jobid:
                try:
                    request.session['async_tasks'] += [(jobid,'submit_race')]
                except KeyError:
                    request.session['async_tasks'] = [(jobid,'submit_race')]

                messages.info(request,"We are evaluating your result. The page will reload when we're done. Your result will show up if you adhered to the course")

            if result:
                otherrecords = resultobj.objects.filter(race = race).exclude(userid = r.id)
                if not jobid:
                    messages.info(request,"Result submitted successfully.")


                for otherrecord in otherrecords:
                    try:
                        otheruser = Rower.objects.get(id=otherrecord.userid)
                        othername = otheruser.user.first_name+' '+otheruser.user.last_name
                        registeredname = r.user.first_name+' '+r.user.last_name
                        if otherrecord.emailnotifications:
                            job = myqueue(
                                queue,
                                handle_sendemail_racesubmission,
                                otheruser.user.email, othername,
                                registeredname,
                                race.name,
                                race.id
                                )
                    except Rower.DoesNotExist:
                        pass

                followers = VirtualRaceFollower.objects.filter(race = race)

                for follower in followers:
                    othername = ''
                    if follower.user:
                        othername = follower.user.first_name+' '+follower.user.last_name

                    registeredname = r.user.first_name+' '+r.user.last_name
                    email = follower.emailaddress
                    job = myqueue(
                        queue,
                        handle_sendemail_racesubmission,
                        email, othername,
                        registeredname,race.name,race.id,
                        )


            # redirect to race page
            url = reverse('virtualevent_view',
                          kwargs = {
                              'id':race.id
                          })

            return HttpResponseRedirect(url)

    else:
        if workoutid:
            workoutdata['initial'] = encoder.decode_hex(workoutid)
        w_form = WorkoutRaceSelectForm(workoutdata,entries)



    breadcrumbs = [
        {
            'url':reverse('virtualevents_view'),
            'name': 'Challenges'
            },
        {
            'url':reverse('virtualevent_view',
                          kwargs={'id':race.id}
                          ),
            'name': race.name
            },
        {
            'url': reverse(virtualevent_submit_result_view,
                           kwargs = {'id':race.id}
                           ),
            'name': 'Submit Result'
            }
        ]

    buttons = []

    if not request.user.is_anonymous:
        if race_can_register(r,race):
            buttons += ['registerbutton']

        if race_can_adddiscipline(r,race):
            buttons += ['adddisciplinebutton']

        if race_can_submit(r,race):
            buttons += ['submitbutton']

        if race_can_resubmit(r,race):
            buttons += ['resubmitbutton']

        if race_can_withdraw(r,race):
            buttons += ['withdrawbutton']

        if race_can_edit(r,race):
            buttons += ['editbutton']


    return render(request,'race_submit.html',
                  {
                      'race':race,
                      'buttons':buttons,
                      'workouts':ws,
                      'breadcrumbs':breadcrumbs,
                      'active':'nav-racing',
                      'rower':r,
                      'w_form':w_form,
                      })

def addfollower_view(request,id=0):
    try:
        race = VirtualRace.objects.get(id=id)
    except VirtualRace.DoesNotExist:
        raise Http404("Virtual Challenge does not exist")

    if not request.user.is_anonymous:
        follower = VirtualRaceFollower(
            user=request.user,
            race=race,
            emailaddress = request.user.email
        )
        follower.save()
        messages.info(request,"You will receive challenge notifications per email")
        url = reverse(virtualevent_view,
                      kwargs={'id':id})

        return HttpResponseRedirect(url)

    # Anonymous
    if request.method == 'POST':
        form = FollowerForm(request.POST)
        if form.is_valid():
            email = form.cleaned_data['emailaddress']

            follower = VirtualRaceFollower(
                race=race,
                emailaddress = email
            )
            follower.save()

            messages.info(request,"You will receive challenge notifications per email")

            url = reverse(virtualevent_view,
                          kwargs={'id':id})

            return HttpResponseRedirect(url)

    else:
        form = FollowerForm()

    breadcrumbs = [
        {
            'url':reverse('virtualevents_view'),
            'name': 'Challenges'
            },
        {
            'url':reverse('virtualevent_view',
                          kwargs={'id':race.id}
                          ),
            'name': race.name
            },
        {
            'url': reverse(addfollower_view,
                           kwargs = {'id':race.id}
                           ),
            'name': 'Follow'
            }
        ]

    return render(request,'followerform.html',
                  {
                      'form':form,
                      'active':'nav-racing',
                      'breadcrumbs':breadcrumbs,
                  }
                  )
