import time
import colorsys
import timestring
import zipfile
import bleach
import operator
import warnings
import urllib
from numbers import Number
from django.views.generic.base import TemplateView
from django.db.models import Q
from django.db import IntegrityError, transaction
from django.shortcuts import render
from django.http import (
    HttpResponse, HttpResponseRedirect,
    HttpResponseForbidden, HttpResponseNotAllowed,
    HttpResponseNotFound,Http404
    )
from django.contrib.auth import authenticate, login, logout
from rowers.forms import (
    LoginForm,DocumentsForm,UploadOptionsForm,
    TeamUploadOptionsForm,
    )
from django.core.urlresolvers import reverse
from django.core.exceptions import PermissionDenied
from django.template import RequestContext
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.conf import settings
from django.utils.datastructures import MultiValueDictKeyError
from django.utils import timezone,translation
from django.core.mail import send_mail, BadHeaderError
from rowers.forms import (
    SummaryStringForm,IntervalUpdateForm,StrokeDataForm,
    StatsOptionsForm,PredictedPieceForm,DateRangeForm,DeltaDaysForm,
    EmailForm, RegistrationForm, RegistrationFormTermsOfService,
    RegistrationFormUniqueEmail,CNsummaryForm,UpdateWindForm,
    UpdateStreamForm,WorkoutMultipleCompareForm,ChartParamChoiceForm,
    FusionMetricChoiceForm,BoxPlotChoiceForm,MultiFlexChoiceForm,
    TrendFlexModalForm,WorkoutSplitForm,
    )
from rowers.models import Workout, User, Rower, WorkoutForm,FavoriteChart
from rowers.models import (
    RowerPowerForm,RowerForm,GraphImage,AdvancedWorkoutForm,
    RowerPowerZonesForm,AccountRowerForm,UserForm,StrokeData,
    Team,TeamForm,TeamInviteForm,TeamInvite,TeamRequest,
    WorkoutComment,WorkoutCommentForm
    )
from rowers.models import FavoriteForm,BaseFavoriteFormSet,SiteAnnouncement
from django.forms.formsets import formset_factory
import StringIO
from django.contrib.auth.decorators import login_required,user_passes_test
from time import strftime,strptime,mktime,time,daylight
import os,sys
import datetime
import iso8601
import c2stuff
from c2stuff import C2NoTokenError,c2_open
from runkeeperstuff import RunKeeperNoTokenError,runkeeper_open
from sporttracksstuff import SportTracksNoTokenError,sporttracks_open
from tpstuff import TPNoTokenError,tp_open
from iso8601 import ParseError
import stravastuff
from stravastuff import StravaNoTokenError
import sporttracksstuff
import underarmourstuff
from underarmourstuff import UnderArmourNoTokenError,underarmour_open
import tpstuff
import runkeeperstuff
import ownapistuff
from ownapistuff import TEST_CLIENT_ID, TEST_CLIENT_SECRET, TEST_REDIRECT_URI
from rowsandall_app.settings import (
    C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET,
    STRAVA_CLIENT_ID, STRAVA_REDIRECT_URI, STRAVA_CLIENT_SECRET,
    SPORTTRACKS_CLIENT_ID, SPORTTRACKS_REDIRECT_URI,
    SPORTTRACKS_CLIENT_SECRET,
    UNDERARMOUR_CLIENT_ID, UNDERARMOUR_REDIRECT_URI,
    UNDERARMOUR_CLIENT_SECRET,UNDERARMOUR_CLIENT_KEY,
    RUNKEEPER_CLIENT_ID,RUNKEEPER_REDIRECT_URI,RUNKEEPER_CLIENT_SECRET,
    TP_CLIENT_ID,TP_REDIRECT_URI,TP_CLIENT_KEY,TP_CLIENT_SECRET,
    )

from rowers.tasks_standalone import addcomment2
from django.contrib import messages
from async_messages import messages as a_messages

import requests
import json
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser
from rowers.rows import handle_uploaded_file
from rowers.tasks import handle_makeplot,handle_otwsetpower,handle_sendemailtcx,handle_sendemailcsv
from rowers.tasks import (
    handle_sendemail_unrecognized,handle_sendemailnewcomment,
    handle_sendemailnewresponse
    )

from scipy.signal import savgol_filter
from django.shortcuts import render_to_response
from Cookie import SimpleCookie
from shutil import copyfile
import types
from rowingdata import rower as rrower
from rowingdata import main as rmain
from rowingdata import rowingdata as rrdata
from rowingdata import make_cumvalues
from rowingdata import summarydata
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

from pytz import timezone as tz,utc
import dateutil
import mpld3
from mpld3 import plugins
import stravalib
from stravalib.exc import ActivityUploadFailed,TimeoutExceeded
from weather import get_wind_data,get_airport_code,get_metar_data

from oauth2_provider.models import Application,Grant,AccessToken

import django_rq
queue = django_rq.get_queue('default')
queuelow = django_rq.get_queue('low')
queuehigh = django_rq.get_queue('low')

from rest_framework_swagger.views import get_swagger_view
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser
from rest_framework.response import Response
from rowers.serializers import RowerSerializer,WorkoutSerializer
from rest_framework import status,permissions,generics
from rest_framework.decorators import api_view, renderer_classes

from permissions import IsOwnerOrNot

import plots
import mailprocessing

from io import BytesIO
from scipy.special import lambertw

from dataprep import timedeltaconv

from scipy.interpolate import griddata

LOCALTIMEZONE = tz('Etc/UTC')
USER_LANGUAGE = 'en-US'

from interactiveplots import *

# Define the API documentation
schema_view = get_swagger_view(title='Rowsandall API')

# Custom error pages with Rowsandall headers
def error500_view(request):
    response = render_to_response('500.html', {},
				  context_instance = RequestContext(request))

    response.status_code = 500
    return response

def error404_view(request):
    response = render_to_response('404.html', {},
				  context_instance = RequestContext(request))

    response.status_code = 404
    return response

def error400_view(request):
    response = render_to_response('400.html', {},
				  context_instance = RequestContext(request))

    response.status_code = 400
    return response

def error403_view(request):
    response = render_to_response('403.html', {},
				  context_instance = RequestContext(request))

    response.status_code = 403
    return response

# Wrapper around the rowingdata call to catch some exceptions
# Checks for CSV file, then for gzipped CSV file, and if all fails, returns 0
def rdata(file,rower=rrower()):
    try:
	res = rrdata(file,rower=rower)
    except IOError, IndexError:
        try:
            res = rrdata(file+'.gz',rower=rower)
        except IOError, IndexError:
            res = 0

    return res

# Query to get teams managed and member of
def get_my_teams(user):
    try:
        therower = Rower.objects.get(user=user)
        teams1 = therower.team.all()
        teams2 = Team.objects.filter(manager=user)
        teams = list(set(teams1).union(set(teams2)))
    except TypeError:
        teams = []

    return teams

# Used for the interval editor - translates seconds to a time object
def get_time(second):
    if (second<=0) or (second>1e9):
	hours = 0
	minutes=0
	sec=0
	microsecond = 0
    elif math.isnan(second):
	hours = 0
	minutes=0
	sec=0
	microsecond = 0
    else:
	days = int(second/(24.*3600.)) % (24*3600)
	hours = int((second-24.*3600.*days)/3600.) % 24
	minutes = int((second-3600.*(hours+24.*days))/60.) % 60
	sec = int(second-3600.*(hours+24.*days)-60.*minutes) % 60
	microsecond = int(1.0e6*(second-3600.*(hours+24.*days)-60.*minutes-sec)) 
    return datetime.time(hours,minutes,sec,microsecond)

	
# get the workout ID from the SportTracks URI
def getidfromsturi(uri,length=8):
    return uri[len(uri)-length:]

def splituadata(lijst):
    t = []
    y = []
    for d in lijst:
        t.append(d[0])
        y.append(d[1])

    return np.array(t),np.array(y)

def splitrunkeeperlatlongdata(lijst,tname,latname,lonname):
    t = []
    lat = []
    lon = []
    for d in lijst:
        t.append(d[tname])
        lat.append(d[latname])
        lon.append(d[lonname])

    return [np.array(t),np.array(lat),np.array(lon)]

def splitrunkeeperdata(lijst,xname,yname):
    x = []
    y = []
    for d in lijst:
        x.append(d[xname])
        y.append(d[yname])

    return [np.array(x),np.array(y)]

# Splits SportTracks data which is one long sequence of
# [t,[lat,lon],t2,[lat2,lon2] ...]
# to [t,t2,t3, ...], [[lat,long],[lat2,long2],...
def splitstdata(lijst):
    t = []
    latlong = []
    while len(lijst)>=2:
	t.append(lijst[0])
	latlong.append(lijst[1])
	lijst = lijst[2:]

    return [np.array(t),np.array(latlong)]
	
from utils import (
    geo_distance,serialize_list,deserialize_list,uniqify,
    str2bool,range_to_color_hex,absolute
    )

import datautils

from rowers.models import checkworkoutuser

# Check if a user is a Coach member
def iscoachmember(user):
    if not user.is_anonymous():
        try:
            r = Rower.objects.get(user=user)
        except Rower.DoesNotExist:
            r = Rower(user=user)
            r.save()
            
        result = user.is_authenticated() and (r.rowerplan=='coach')
    else:
        result = False
        
    return result

def getrower(user):
    try:
        r = Rower.objects.get(user=user)
    except Rower.DoesNotExist:
        r = Rower(user=user)
        r.save()

    return r

# Check if a user is a Pro member
def ispromember(user):
    if not user.is_anonymous():
        try:
            r = Rower.objects.get(user=user)
        except Rower.DoesNotExists:
            r = Rower(user=user)
            r.save()
            
        result = user.is_authenticated() and (r.rowerplan=='pro' or r.rowerplan=='coach')
    else:
        result = False
    return result

# User registration
def rower_register_view(request):
    if request.method == 'POST':
	form = RegistrationFormUniqueEmail(request.POST)
	if form.is_valid():
	    first_name = form.cleaned_data['first_name']
	    last_name = form.cleaned_data['last_name']
	    email = form.cleaned_data['email']
	    password = form.cleaned_data['password1']
	    username = form.cleaned_data['username']
	    theuser = User.objects.create_user(username,password=password)
	    theuser.first_name = first_name
	    theuser.last_name = last_name
	    theuser.email = email
	    theuser.save()

	    therower = Rower(user=theuser)

	    therower.save()

            # Create Sample workout
            f = 'media/testdata.csv.gz'
            timestr = strftime("%Y%m%d-%H%M%S")
            f2 = f[:-7]+timestr+'.csv.gz'
            copyfile(f,f2)
                        
            response = dataprep.new_workout_from_file(therower,f2,
                                                      title='New User Sample Data',
                                                      notes='This is an example workout to get you started')
            newworkoutid = response[0]
            w = Workout.objects.get(id=newworkoutid)
            w.startdatetime = timezone.now()
            w.save()
            
            # Create and send email
	    fullemail = first_name + " " + last_name + " " + "<" + email + ">"
	    subject = "Thank you for registering on rowsandall.com"
	    message = "Thank you for registering on rowsandall.com. You can now login using the credentials you provided.\n"
	    message += "The first thing you might want to do is check and edit the heart rate band values. After logging in, click the button with your first name.\n"
	    message += "You can also check our videos page at http://rowsandall.com/rowers/videos for some helpful instruction videos.\n\n"
	    message += "User name:"+username+"\n"
	    message += "For all your questions, just reply to this email.\n\n"
	    message += "Happy rowing!\n\n\n"
	    message += "Oh, one more thing. The site is currently in beta and is developing fast. Bear with us. Don't hesitate to contact me if anything is broken or doesn't seem to work as advertised."
	    send_mail(subject, message,
		      'Sander Roosendaal <info@rowsandall.com>',
		      [fullemail])

	    subject2 = "New User"
	    message2 = "New user registered.\n"
	    message2 += fullemail + "\n"
	    message2 += "User name: "+username

	    send_mail(subject2, message2,
		      'Rowsandall Server <info@rowsandall.com>',
		      ['roosendaalsander@gmail.com'])

	    return HttpResponseRedirect('/rowers/register/thankyou/')

	else:
	    return render(request,
			  "registration_form.html",
			  {'form':form})
    else:
	form =  RegistrationFormUniqueEmail()
	return render(request,
		      "registration_form.html",
		      {'form':form,})

# Shows email form and sends it if submitted
def sendmail(request):
    if request.method == 'POST':
        form = EmailForm(request.POST)
        if form.is_valid():
	    firstname = form.cleaned_data['firstname']
	    lastname = form.cleaned_data['lastname']
	    email = form.cleaned_data['email']
	    subject = form.cleaned_data['subject']
	    botcheck = form.cleaned_data['botcheck'].lower()
	    message = form.cleaned_data['message']
	    if botcheck == 'yes':
		try:
		    fullemail = firstname + " " + lastname + " " + "<" + email + ">"
		    send_mail(subject, message, fullemail, ['info@rowsandall.com'])
		    return HttpResponseRedirect('/rowers/email/thankyou/')
		except:
		    return HttpResponseRedirect('/rowers/email/')
	    else:
                messages.error(request,'You have to answer YES to the question')
		return HttpResponseRedirect('/rowers/email/')
	else:
	    return HttpResponseRedirect('/rowers/email/')  
    else:
        return HttpResponseRedirect('/rowers/email/')

# Create workout data from Strava or Concept2
# data and create the associated Workout object and save it
def add_workout_from_strokedata(user,importid,data,strokedata,
                                source='c2',splitdata=None,
                                workoutsource='concept2'):
    try:
        workouttype = data['type']
    except KeyError:
        workouttype = 'rower'
        
    if workouttype not in [x[0] for x in Workout.workouttypes]:
	workouttype = 'water'
    try:
	comments = data['comments']
    except:
	comments = ' '

#    comments = "Imported data \n %s" % comments
#    comments = "Imported data \n"+comments  # str(comments)
    try:
	thetimezone = tz(data['timezone'])
    except:
	thetimezone = 'UTC'

    r = getrower(user)
    try:
	rowdatetime = iso8601.parse_date(data['date_utc'])
    except KeyError:
	rowdatetime = iso8601.parse_date(data['start_date'])
    except ParseError:
	rowdatetime = iso8601.parse_date(data['date'])
    
	
    try:
        c2intervaltype = data['workout_type']
	
    except KeyError:
	c2intervaltype = ''
	
    try:
	title = data['name']
    except KeyError:
	title = ""
	try:
	    t = data['comments'].split('\n', 1)[0]
	    title += t[:20]
	except:
	    title = 'Imported'

    starttimeunix = mktime(rowdatetime.utctimetuple())

    res = make_cumvalues(0.1*strokedata['t'])
    cum_time = res[0]
    lapidx = res[1]

    unixtime = cum_time+starttimeunix
    # unixtime[0] = starttimeunix
    seconds = 0.1*strokedata.ix[:,'t']

    nr_rows = len(unixtime)

    try:
	latcoord = strokedata.ix[:,'lat']
	loncoord = strokedata.ix[:,'lon']
    except:
	latcoord = np.zeros(nr_rows)
	loncoord = np.zeros(nr_rows)


    try:
	strokelength = strokedata.ix[:,'strokelength']
    except:
	strokelength = np.zeros(nr_rows)

    dist2 = 0.1*strokedata.ix[:,'d']

    spm = strokedata.ix[:,'spm']
    try:
        hr = strokedata.ix[:,'hr']
    except KeyError:
        hr = 0*spm
    pace = strokedata.ix[:,'p']/10.
    pace = np.clip(pace,0,1e4)
    pace = pace.replace(0,300)

    velo = 500./pace

    power = 2.8*velo**3
    
    # save csv
    # Create data frame with all necessary data to write to csv
    df = pd.DataFrame({'TimeStamp (sec)':unixtime,
		       ' Horizontal (meters)': dist2,
		       ' Cadence (stokes/min)':spm,
		       ' HRCur (bpm)':hr,
		       ' longitude':loncoord,
		       ' latitude':latcoord,
		       ' Stroke500mPace (sec/500m)':pace,
		       ' Power (watts)':power,
		       ' DragFactor':np.zeros(nr_rows),
		       ' DriveLength (meters)':np.zeros(nr_rows),
		       ' StrokeDistance (meters)':strokelength,
		       ' DriveTime (ms)':np.zeros(nr_rows),
		       ' StrokeRecoveryTime (ms)':np.zeros(nr_rows),
		       ' AverageDriveForce (lbs)':np.zeros(nr_rows),
		       ' PeakDriveForce (lbs)':np.zeros(nr_rows),
		       ' lapIdx':lapidx,
		       ' ElapsedTime (sec)':seconds
		       })

    
    df.sort_values(by='TimeStamp (sec)',ascending=True)
	
    timestr = strftime("%Y%m%d-%H%M%S")

    # # auto smoothing
    # pace = df[' Stroke500mPace (sec/500m)'].values
    # velo = 500./pace

    # f = df['TimeStamp (sec)'].diff().mean()
    # windowsize = 2*(int(10./(f)))+1
    # if windowsize <= 3:
    #     windowsize = 5

    # df['originalvelo'] = velo

    # if windowsize > 3 and windowsize < len(velo):
    #     velo2 = savgol_filter(velo,windowsize,3)
    # else:
    #     velo2=velo

    # velo3 = pd.Series(velo2)
    # velo3 = velo3.replace([-np.inf,np.inf],np.nan)
    # velo3 = velo3.fillna(method='ffill')
    
    # pace2 = 500./abs(velo3)
    # df[' Stroke500mPace (sec/500m)'] = pace2

    # df = df.fillna(0)

    # end autosmoothing

    # Create CSV file name and save data to CSV file
    csvfilename ='media/Import_'+str(importid)+'.csv'

    res =  df.to_csv(csvfilename+'.gz',index_label='index',
                     compression='gzip')


    # with Concept2
    if source=='c2':
        try:
            totaldist = data['distance']
            totaltime = data['time']/10.
        except KeyError:
            totaldist = 0
            totaltime = 0
    else:
        totaldist = 0
        totaltime = 0

    id,message = dataprep.save_workout_database(csvfilename,r,
                                                workouttype=workouttype,
                                                title=title,notes=comments,
                                                totaldist=totaldist,
                                                totaltime=totaltime,
                                                workoutsource=workoutsource)

            

    return id,message

# Create workout from RunKeeper Data
def add_workout_from_runkeeperdata(user,importid,data):
    # To Do - add utcoffset to time
    workouttype = data['type']
    if workouttype not in [x[0] for x in Workout.workouttypes]:
	workouttype = 'water'
    try:
	comments = data['notes']
    except:
	comments = ''
    
    try:
	utcoffset = tz(data['utcoffset'])
    except:
	utcoffset = 0

    r = getrower(user)

    try:
	rowdatetime = iso8601.parse_date(data['start_time'])
    except iso8601.ParseError:
	try:
	    rowdatetime = datetime.datetime.strptime(data['start_time'],"%Y-%m-%d %H:%M:%S")
	    rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc)
	except:
	    try:
		rowdatetime = dateutil.parser.parse(data['start_time'])
		#rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc)
	    except:
		rowdatetime = datetime.datetime.strptime(data['date'],"%Y-%m-%d %H:%M:%S")
		rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc)
    starttimeunix = mktime(rowdatetime.utctimetuple())
    starttimeunix += utcoffset*3600
        
	
    try:
	title = data['name']
    except:
	title = "Imported data"



    res = splitrunkeeperdata(data['distance'],'timestamp','distance')

    distance = res[1]
    times_distance = res[0]

    try:
	l = data['path']
    
	res = splitrunkeeperlatlongdata(l,'timestamp','latitude','longitude')
	times_location = res[0]
	latcoord = res[1]
	loncoord = res[2]

    except:
	times_location = times_distance
	latcoord = np.zeros(len(times_distance))
	loncoord = np.zeros(len(times_distance))
        if workouttype in ('water','coastal'):
            workouttype = 'rower'
	
    try:
	res = splitrunkeeperdata(data['cadence'],'timestamp','cadence')
	times_spm = res[0]
	spm = res[1]
    except KeyError:
	times_spm = times_distance
	spm = 0*times_distance
    
    try:
	res = splitrunkeeperdata(data['heart_rate'],'timestamp','heart_rate')
	hr = res[1]
	times_hr = res[0]
    except KeyError:
	times_hr = times_distance
	hr = 0*times_distance


    # create data series and remove duplicates
    distseries = pd.Series(distance,index=times_distance)
    distseries = distseries.groupby(distseries.index).first()
    latseries = pd.Series(latcoord,index=times_location)
    latseries = latseries.groupby(latseries.index).first()
    lonseries = pd.Series(loncoord,index=times_location)
    lonseries = lonseries.groupby(lonseries.index).first()
    spmseries = pd.Series(spm,index=times_spm)
    spmseries = spmseries.groupby(spmseries.index).first()
    hrseries = pd.Series(hr,index=times_hr)
    try:
        hrseries = hrseries.groupby(hrseries.index).first()
    except TypeError:
        hrseries = 0*distseries


    # Create dicts and big dataframe
    d = {
	' Horizontal (meters)': distseries,
	' latitude': latseries,
	' longitude': lonseries,
	' Cadence (stokes/min)': spmseries,
	' HRCur (bpm)' : hrseries,
	}

    

    df = pd.DataFrame(d)

    df = df.groupby(level=0).last()

    cum_time = df.index.values
    df[' ElapsedTime (sec)'] = cum_time

    velo = df[' Horizontal (meters)'].diff()/df[' ElapsedTime (sec)'].diff()
    
    df[' Power (watts)'] = 0.0*velo

    nr_rows = len(velo.values)

    df[' DriveLength (meters)'] = np.zeros(nr_rows)
    df[' StrokeDistance (meters)'] = np.zeros(nr_rows)
    df[' DriveTime (ms)'] = np.zeros(nr_rows)
    df[' StrokeRecoveryTime (ms)'] = np.zeros(nr_rows)
    df[' AverageDriveForce (lbs)'] = np.zeros(nr_rows)
    df[' PeakDriveForce (lbs)'] = np.zeros(nr_rows)
    df[' lapIdx'] = np.zeros(nr_rows)



    unixtime = cum_time+starttimeunix
    unixtime[0] = starttimeunix
 
    df['TimeStamp (sec)'] = unixtime

 
    dt = np.diff(cum_time).mean()
    wsize = round(5./dt)

    # velo2 = stravastuff.ewmovingaverage(velo,wsize)

    # df[' Stroke500mPace (sec/500m)'] = 500./velo2


    df = df.fillna(0)

    df.sort_values(by='TimeStamp (sec)',ascending=True)
	
    timestr = strftime("%Y%m%d-%H%M%S")

    csvfilename ='media/Import_'+str(importid)+'.csv'

    res =  df.to_csv(csvfilename+'.gz',index_label='index',
                     compression='gzip')

    id,message = dataprep.save_workout_database(csvfilename,r,
                                                workouttype=workouttype,
                                                workoutsource='runkeeper',
                                                title=title,
                                                notes=comments)

    return (id,message)

    

# Create workout from SportTracks Data, which are slightly different
# than Strava or Concept2 data
def add_workout_from_stdata(user,importid,data):
    workouttype = data['type']
    if workouttype not in [x[0] for x in Workout.workouttypes]:
	workouttype = 'water'
    try:
	comments = data['comments']
    except:
	comments = ''
    
    try:
	thetimezone = tz(data['timezone'])
    except:
	thetimezone = 'UTC'

    r = getrower(user)
    try:
	rowdatetime = iso8601.parse_date(data['start_time'])
    except iso8601.ParseError:
	try:
	    rowdatetime = datetime.datetime.strptime(data['start_time'],"%Y-%m-%d %H:%M:%S")
	    rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc)
	except:
	    try:
		rowdatetime = dateutil.parser.parse(data['start_time'])
		rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc)
	    except:
		rowdatetime = datetime.datetime.strptime(data['date'],"%Y-%m-%d %H:%M:%S")
		rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc)
    starttimeunix = mktime(rowdatetime.utctimetuple())
        
	
    try:
	title = data['name']
    except:
	title = "Imported data"

    try:
        res = splitstdata(data['distance'])
    except KeyError:
        return (0,"No distance data in the workout")

    distance = res[1]
    times_distance = res[0]

    try:
	l = data['location']
    
	res = splitstdata(l)
	times_location = res[0]
	latlong = res[1]
	latcoord = []
	loncoord = []

	for coord in latlong:
	    lat = coord[0]
	    lon = coord[1]
	    latcoord.append(lat)
	    loncoord.append(lon)
    except:
	times_location = times_distance
	latcoord = np.zeros(len(times_distance))
	loncoord = np.zeros(len(times_distance))
        if workouttype in ('water','coastal'):
            workouttype = 'rower'
	
    try:
	res = splitstdata(data['cadence'])
	times_spm = res[0]
	spm = res[1]
    except KeyError:
	times_spm = times_distance
	spm = 0*times_distance
    
    try:
	res = splitstdata(data['heartrate'])
	hr = res[1]
	times_hr = res[0]
    except KeyError:
	times_hr = times_distance
	hr = 0*times_distance


    # create data series and remove duplicates
    distseries = pd.Series(distance,index=times_distance)
    distseries = distseries.groupby(distseries.index).first()
    latseries = pd.Series(latcoord,index=times_location)
    latseries = latseries.groupby(latseries.index).first()
    lonseries = pd.Series(loncoord,index=times_location)
    lonseries = lonseries.groupby(lonseries.index).first()
    spmseries = pd.Series(spm,index=times_spm)
    spmseries = spmseries.groupby(spmseries.index).first()
    hrseries = pd.Series(hr,index=times_hr)
    hrseries = hrseries.groupby(hrseries.index).first()


    # Create dicts and big dataframe
    d = {
	' Horizontal (meters)': distseries,
	' latitude': latseries,
	' longitude': lonseries,
	' Cadence (stokes/min)': spmseries,
	' HRCur (bpm)' : hrseries,
	}

    

    df = pd.DataFrame(d)

    df = df.groupby(level=0).last()

    cum_time = df.index.values
    df[' ElapsedTime (sec)'] = cum_time

    velo = df[' Horizontal (meters)'].diff()/df[' ElapsedTime (sec)'].diff()
    
    df[' Power (watts)'] = 0.0*velo

    nr_rows = len(velo.values)

    df[' DriveLength (meters)'] = np.zeros(nr_rows)
    df[' StrokeDistance (meters)'] = np.zeros(nr_rows)
    df[' DriveTime (ms)'] = np.zeros(nr_rows)
    df[' StrokeRecoveryTime (ms)'] = np.zeros(nr_rows)
    df[' AverageDriveForce (lbs)'] = np.zeros(nr_rows)
    df[' PeakDriveForce (lbs)'] = np.zeros(nr_rows)
    df[' lapIdx'] = np.zeros(nr_rows)



    unixtime = cum_time+starttimeunix
    unixtime[0] = starttimeunix
 
    df['TimeStamp (sec)'] = unixtime

 
    dt = np.diff(cum_time).mean()
    wsize = round(5./dt)

    velo2 = stravastuff.ewmovingaverage(velo,wsize)

    df[' Stroke500mPace (sec/500m)'] = 500./velo2


    df = df.fillna(0)

    df.sort_values(by='TimeStamp (sec)',ascending=True)
	
    timestr = strftime("%Y%m%d-%H%M%S")

    csvfilename ='media/Import_'+str(importid)+'.csv'

    res =  df.to_csv(csvfilename+'.gz',index_label='index',
                     compression='gzip')

    id,message = dataprep.save_workout_database(csvfilename,r,
                                                workouttype=workouttype,
                                                title=title,
                                                notes=comments,
                                                workoutsource='sporttracks')

    return (id,message)

# Create workout from SportTracks Data, which are slightly different
# than Strava or Concept2 data
def add_workout_from_underarmourdata(user,importid,data):
    workouttype = 'water'

    try:
	comments = data['notes']
    except:
	comments = ''
    
    try:
	thetimezone = tz(data['start_locale_timezone'])
    except:
	thetimezone = 'UTC'

    r = getrower(user)
    try:
	rowdatetime = iso8601.parse_date(data['start_datetime'])
    except iso8601.ParseError:
	try:
	    rowdatetime = datetime.datetime.strptime(data['start_datetime'],"%Y-%m-%d %H:%M:%S")
	    rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc)
	except:
	    try:
		rowdatetime = dateutil.parser.parse(data['start_datetime'])
		rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc)
	    except:
		rowdatetime = datetime.datetime.strptime(data['date'],"%Y-%m-%d %H:%M:%S")
		rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc)
    starttimeunix = mktime(rowdatetime.utctimetuple())
        
	
    try:
	title = data['name']
    except:
	title = "Imported data"

    timeseries = data['time_series']

    # position, distance, speed, cadence, power, 
    
    res = splituadata(timeseries['distance'])

    distance = res[1]

    times_distance = res[0]


    try:
	l = timeseries['position']
    
	res = splituadata(l)
	times_location = res[0]
	latlong = res[1]
	latcoord = []
	loncoord = []

	for coord in latlong:
	    lat = coord['lat']
	    lon = coord['lng']
	    latcoord.append(lat)
	    loncoord.append(lon)
    except:
	times_location = times_distance
	latcoord = np.zeros(len(times_distance))
	loncoord = np.zeros(len(times_distance))
        if workouttype in ('water','coastal'):
            workouttype = 'rower'
	
    try:
	res = splituadata(timeseries['cadence'])
	times_spm = res[0]
	spm = res[1]
    except KeyError:
	times_spm = times_distance
	spm = 0*times_distance
    
    try:
	res = splituadata(timeseries['heartrate'])
	hr = res[1]
	times_hr = res[0]
    except KeyError:
	times_hr = times_distance
	hr = 0*times_distance


    # create data series and remove duplicates
    distseries = pd.Series(distance,index=times_distance)
    distseries = distseries.groupby(distseries.index).first()
    latseries = pd.Series(latcoord,index=times_location)
    latseries = latseries.groupby(latseries.index).first()
    lonseries = pd.Series(loncoord,index=times_location)
    lonseries = lonseries.groupby(lonseries.index).first()
    spmseries = pd.Series(spm,index=times_spm)
    spmseries = spmseries.groupby(spmseries.index).first()
    hrseries = pd.Series(hr,index=times_hr)
    hrseries = hrseries.groupby(hrseries.index).first()


    # Create dicts and big dataframe
    d = {
	' Horizontal (meters)': distseries,
	' latitude': latseries,
	' longitude': lonseries,
	' Cadence (stokes/min)': spmseries,
	' HRCur (bpm)' : hrseries,
	}

    

    df = pd.DataFrame(d)

    df = df.groupby(level=0).last()

    cum_time = df.index.values
    df[' ElapsedTime (sec)'] = cum_time

    velo = df[' Horizontal (meters)'].diff()/df[' ElapsedTime (sec)'].diff()
    
    df[' Power (watts)'] = 0.0*velo

    nr_rows = len(velo.values)

    df[' DriveLength (meters)'] = np.zeros(nr_rows)
    df[' StrokeDistance (meters)'] = np.zeros(nr_rows)
    df[' DriveTime (ms)'] = np.zeros(nr_rows)
    df[' StrokeRecoveryTime (ms)'] = np.zeros(nr_rows)
    df[' AverageDriveForce (lbs)'] = np.zeros(nr_rows)
    df[' PeakDriveForce (lbs)'] = np.zeros(nr_rows)
    df[' lapIdx'] = np.zeros(nr_rows)



    unixtime = cum_time+starttimeunix
    unixtime[0] = starttimeunix
 
    df['TimeStamp (sec)'] = unixtime

 
    dt = np.diff(cum_time).mean()
    wsize = round(5./dt)

    # velo2 = stravastuff.ewmovingaverage(velo,wsize)

    # df[' Stroke500mPace (sec/500m)'] = 500./velo2


    df = df.fillna(0)

    df.sort_values(by='TimeStamp (sec)',ascending=True)
	
    timestr = strftime("%Y%m%d-%H%M%S")

    csvfilename ='media/Import_'+str(importid)+'.csv'

    res =  df.to_csv(csvfilename+'.gz',index_label='index',
                     compression='gzip')

    id,message = dataprep.save_workout_database(csvfilename,r,
                                                workouttype=workouttype,
                                                workoutsource='mapmyfitness',
                                                title=title,
                                                notes=comments)

    return (id,message)

    



# Export workout to TCX and send to user's email address
@login_required()
def workout_tcxemail_view(request,id=0):
    message = ""
    successmessage = ""
    r = getrower(request.user)
    try:
        w = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")
    if (checkworkoutuser(request.user,w)):
        try:
	    tcxfile,tcxmessg = stravastuff.createstravaworkoutdata(w,dozip=False)
            if tcxfile == 0:
                message = "Something went wrong (TCX export) "+tcxmessg
                messages.error(request,message)
                url = reverse(workout_export_view,
                              kwargs = {
                                  'id':str(w.id),
                                  })
                return HttpResponseRedirect(url)
	    if settings.DEBUG and tcxfile:	    
	        res = handle_sendemailtcx.delay(r.user.first_name,
					        r.user.last_name,
					        r.user.email,tcxfile)

	    elif tcxfile:
	        res = queuehigh.enqueue(handle_sendemailtcx,r.user.first_name,
				        r.user.last_name,
				        r.user.email,tcxfile)

	    successmessage = "The TCX file was sent to you per email"
            messages.info(request,successmessage)
	    url = reverse(workout_export_view,
		          kwargs = {
			      'id':str(w.id),
			  })
        except:
            successmessage = ""
            message = "Something went wrong (TCX export) "+str(sys.exc_info()[0])
            with open("media/c2errors.log","a") as errorlog:
                errorstring = str(sys.exc_info()[0])
                timestr = strftime("%Y%m%d-%H%M%S")
                errorlog.write(timestr+errorstring+"\r\n")

            messages.error(request,message)
            url = reverse(workout_export_view,
		          kwargs = {
			      'id':str(w.id),
			  })

	response = HttpResponseRedirect(url)

    else:
	message = "You are not allowed to export this workout"
        messages.error(request,message)
	url = reverse(workout_export_view,
		      kwargs = {
			  'id':str(w.id),
			  })
	response = HttpResponseRedirect(url)
		      
    return response

# Export workout to GPX and send to user's email address
@login_required()
def workout_gpxemail_view(request,id=0):
    message = ""
    successmessage = ""
    r = Rower.objects.get(user=request.user)
    try:
        w = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")
    if (checkworkoutuser(request.user,w)):
	filename = w.csvfilename
        row = rdata(filename)
        gpxfilename = filename[:-4]+'.gpx'
        row.exporttogpx(gpxfilename)
	if settings.DEBUG:	    
	    res = handle_sendemailtcx.delay(r.user.first_name,
					    r.user.last_name,
					    r.user.email,gpxfilename)

	else:
	    res = queuehigh.enqueue(handle_sendemailtcx,r.user.first_name,
				    r.user.last_name,
				    r.user.email,gpxfilename)

	successmessage = "The GPX file was sent to you per email"
        messages.info(request,successmessage)
	url = reverse(workout_export_view,
		      kwargs = {
			  'id':str(w.id),
		      })

	response = HttpResponseRedirect(url)

    else:
	message = "You are not allowed to export this workout"
        messages.error(request,message)
	url = reverse(workout_export_view,
		      kwargs = {
			  'id':str(w.id),
			  })
	response = HttpResponseRedirect(url)
		      
    return response

# Get Workout CSV file and send it to user's email address
@login_required()
def workout_csvemail_view(request,id=0):
    message = ""
    r = getrower(request.user)
    try:
        w = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")
    if (checkworkoutuser(request.user,w)):
	csvfile = w.csvfilename
	if settings.DEBUG:	    
	    res = handle_sendemailcsv.delay(r.user.first_name,
					    r.user.last_name,
					    r.user.email,csvfile)

	else:
	    res = queuehigh.enqueue(handle_sendemailcsv,r.user.first_name,
				r.user.last_name,
				r.user.email,csvfile)

	successmessage = "The CSV file was sent to you per email"
        messages.info(request,successmessage)
	url = reverse(workout_export_view,
		      kwargs = {
			  'id':str(w.id),
			  })
	response = HttpResponseRedirect(url)

    else:
	message = "You are not allowed to export this workout"
        messages.error(request,message)
	url = reverse(workout_export_view,
		      kwargs = {
			  'id':str(w.id),
			  })
	response = HttpResponseRedirect(url)
		      
    return response

# Get Workout CSV file and send it to user's email address
@login_required()
def workout_csvtoadmin_view(request,id=0):
    message = ""
    r = getrower(request.user)
    try:
        w = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

    csvfile = w.csvfilename
    if settings.DEBUG:	    
	res = handle_sendemailcsv.delay(
            'Sander',
	    'Roosendaal',
	    'roosendaalsander@gmail.com',csvfile)
        
    else:
	res = queuehigh.enqueue(
            handle_sendemailcsv,
            'Sander',
            'Roosendaal',
            'roosendaalsander@gmail.com',
            csvfile)

    successmessage = "The CSV file was sent to the site admin per email"
    messages.info(request,successmessage)
    url = reverse(workout_view,
		  kwargs = {
		      'id':str(w.id),
		  })
    response = HttpResponseRedirect(url)

    return response

# Send workout to TP
@login_required()
def workout_tp_upload_view(request,id=0):
    message = ""
    r = getrower(request.user)
    res = -1
    try:
        thetoken = tp_open(r.user)
    except TPNoTokenError:
        return HttpResponseRedirect("/rowers/me/tpauthorize/")

    # ready to upload. Hurray
    try:
        w = Workout.objects.get(id=id)
        r = w.user
    except Workout.DoesNotExist:
        raise Http404("Workout doesn't exist")
    if (checkworkoutuser(request.user,w)):
        tcxfile = tpstuff.createtpworkoutdata(w)
        if tcxfile:
            res,reason,status_code,headers = tpstuff.uploadactivity(
                r.tptoken,tcxfile,
                name=w.name
            )
            if res == 0:
                message = "Upload to TrainingPeaks failed with status code "+str(status_code)+": "+reason
                try:
                    os.remove(tcxfile)
                except WindowsError:
                    pass

                messages.error(request,message)

            else: # res != 0
                w.uploadedtotp = res
                w.save()
                os.remove(tcxfile)
                messages.info(request,'Uploaded to TrainingPeaks')

        else: # no tcxfile
            message = "Upload to TrainingPeaks failed"
            w.uploadedtotp = -1
            w.save()
            messages.error(request,message)

    else: # not allowed to upload
        message = "You are not allowed to export this workout to TP"
        messages.error(request,message)

    url = reverse(workout_export_view,
                  kwargs = {
                      'id':str(w.id),
                  })
                
    return HttpResponseRedirect(url)
                                      
                                
# Send workout to Strava
# abundance of error logging here because there were/are some bugs
@login_required()
def workout_strava_upload_view(request,id=0):
    message = ""
    r = getrower(request.user)
    res = -1
    if (r.stravatoken == '') or (r.stravatoken is None):
	s = "Token doesn't exist. Need to authorize"
	return HttpResponseRedirect("/rowers/me/stravaauthorize/")
    else:
	# ready to upload. Hurray
        try:
	    w = Workout.objects.get(id=id)
            r = w.user
        except Workout.DoesNotExist:
	    raise Http404("Workout doesn't exist")
	if (checkworkoutuser(request.user,w)):
            try:
	        tcxfile,tcxmessg = stravastuff.createstravaworkoutdata(w)
                if tcxfile:
		    with open(tcxfile,'rb') as f:
                        try:
                            newnotes = w.notes+'\n from '+w.workoutsource+' via rowsandall.com'
                        except TypeError:
                            newnotes = 'from '+w.workoutsource+' via rowsandall.com'
		        res,mes = stravastuff.handle_stravaexport(f,w.name,
							      r.stravatoken,
							          description=newnotes)
                        if res==0:
                            messages.error(request,mes)
		            w.uploadedtostrava = -1
		            w.save()
                            try:
		                os.remove(tcxfile)
                            except WindowsError:
                                pass
		            url = reverse(workout_export_view,
			                  kwargs = {
				              'id':str(w.id),
				          })
		            response = HttpResponseRedirect(url)
                            return response
                                
                        try:
        	            w.uploadedtostrava = res
		            w.save()
                            try:
		                os.remove(tcxfile)
                            except WindowsError:
                                print tcxfile
                                pass
		            url = "/rowers/workout/"+str(w.id)+"/edit"

                            messages.info(request,mes)
	                except:
                            with open("media/stravaerrors.log","a") as errorlog:
                                errorstring = str(sys.exc_info()[0])
                                timestr = strftime("%Y%m%d-%H%M%S")
                                errorlog.write(timestr+errorstring+"\r\n")
                                errorlog.write("views.py line 826\r\n")
                                message = 'Error: '+errorstring
                                messages.error(request,message)
                else: # No tcxfile
                    message = "Strava Data error "+tcxmessg
                    messages.error(request,message)
                    w.uploadedtostrava = -1
                    w.save()
		    url = reverse(workout_export_view,
			          kwargs = {
				      'id':str(w.id),
				  })
		    response = HttpResponseRedirect(url)


		url = reverse(workout_export_view,
			      kwargs = {
				  'id':str(w.id),
				  }
			      )
		response = HttpResponseRedirect(url)
	    except ActivityUploadFailed as e:
		message = "Strava Upload error: %s" % e
                messages.error(request,message)
		w.uploadedtostrava = -1
		w.save()
		os.remove(tcxfile)
		url = reverse(workout_export_view,
			      kwargs = {
				  'id':str(w.id),
				  })
		response = HttpResponseRedirect(url)

	return response
	  
# Upload workout to Concept2 logbook
@login_required()
def workout_c2_upload_view(request,id=0):
    message = ""
    # ready to upload. Hurray
    try:
        w = Workout.objects.get(id=id)
        r = w.user
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

    try:
        message,c2id = c2stuff.workout_c2_upload(request.user,w)
    except C2NoTokenError:
        return HttpResponseRedirect("/rowers/me/c2authorize/")

    if message and c2id <=0:
        messages.error(request,message)
    elif message:
        messages.info(request,message)


    url = reverse(workout_export_view,
		  kwargs = {
		      'id':str(w.id),
		  })

    return HttpResponseRedirect(url)

# Upload workout to RunKeeper
@login_required()
def workout_runkeeper_upload_view(request,id=0):
    message = ""
    try:
        w = Workout.objects.get(id=id)
        r = w.user
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

    try:
	thetoken = runkeeper_open(r.user)
    except RunKeeperNoTokenError:
	return HttpResponseRedirect("/rowers/me/runkeeperauthorize/")

    # ready to upload. Hurray

    if (checkworkoutuser(request.user,w)):
	data = runkeeperstuff.createrunkeeperworkoutdata(w)
        if not data:
            message = "Data error"
            messages.error(request,message)
            url = reverse(workout_export_view,
		          kwargs = {
		              'id':str(w.id),
		          })
            return HttpResponseRedirect(url)
        
	authorizationstring = str('Bearer ' + thetoken)
	headers = {'Authorization': authorizationstring,
		   'user-agent': 'sanderroosendaal',
		   'Content-Type': 'application/vnd.com.runkeeper.NewFitnessActivity+json',
                   'Content-Length':'nnn'}

	url = "https://api.runkeeper.com/fitnessActivities"
	response = requests.post(url,headers=headers,data=json.dumps(data))

	# check for duplicate error first
	if (response.status_code == 409 ):
	    message = "Duplicate error"
            messages.error(request,message)
	    w.uploadedtorunkeeper = -1
	    w.save()
	elif (response.status_code == 201 or response.status_code==200):
	    runkeeperid = runkeeperstuff.getidfromresponse(response)
	    w.uploadedtorunkeeper = runkeeperid
	    w.save()
	    url = "/rowers/workout/"+str(w.id)+"/export"
	    return HttpResponseRedirect(url)
	else:
	    s = response
	    message = "Something went wrong in workout_runkeeper_upload_view: %s - %s" % (s.reason,s.text)
            messages.error(request,message)
		
    else:
	message = "You are not authorized to upload this workout"
        messages.error(request,message)

    url = reverse(workout_export_view,
		  kwargs = {
		      'id':str(w.id),
	      })

    return HttpResponseRedirect(url)

# Upload workout to Underarmour
@login_required()
def workout_underarmour_upload_view(request,id=0):
    message = ""
    try:
        w = Workout.objects.get(id=id)
        r = w.user
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

    try:
	thetoken = underarmour_open(r.user)
    except UnderArmourNoTokenError:
	return HttpResponseRedirect("/rowers/me/underarmourauthorize/")

    # ready to upload. Hurray

    if (checkworkoutuser(request.user,w)):
	data = underarmourstuff.createunderarmourworkoutdata(w)
#        return HttpResponse(json.dumps(data))
        if not data:
            message = "Data error"
            messages.error(request,message)
            url = reverse(workout_export_view,
		          kwargs = {
		              'id':str(w.id),
		          })
            return HttpResponseRedirect(url)
        
	authorizationstring = str('Bearer ' + thetoken)
	headers = {'Authorization': authorizationstring,
                   'Api-Key': UNDERARMOUR_CLIENT_KEY,
		   'user-agent': 'sanderroosendaal',
		   'Content-Type': 'application/json',
                   }

	url = "https://api.ua.com/v7.1/workout/"
	response = requests.post(url,headers=headers,data=json.dumps(data))

	# check for duplicate error first
	if (response.status_code == 409 ):
	    message = "Duplicate error"
            messages.error(request,message)
	    w.uploadedtounderarmour = -1
	    w.save()
	elif (response.status_code == 201 or response.status_code==200):
	    underarmourid = underarmourstuff.getidfromresponse(response)
	    w.uploadedtounderarmour = underarmourid
	    w.save()
	    url = "/rowers/workout/"+str(w.id)+"/export"
	    return HttpResponseRedirect(url)
	else:
	    s = response
	    message = "Something went wrong in workout_underarmour_upload_view: %s - %s" % (s.reason,s.text)
	    messages.error(request,message)
    else:
	message = "You are not authorized to upload this workout"
        messages.error(request,message)
        
    url = reverse(workout_export_view,
		  kwargs = {
		      'id':str(w.id),
	      })

    return HttpResponseRedirect(url)

# Upload workout to SportTracks
@login_required()
def workout_sporttracks_upload_view(request,id=0):
    message = ""
    # ready to upload. Hurray
    try:
        w = Workout.objects.get(id=id)
        r = w.user
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

    try:
	thetoken = sporttracks_open(r.user)
    except SportTracksNoTokenError:
	return HttpResponseRedirect("/rowers/me/sporttracksauthorize/")


    if (checkworkoutuser(request.user,w)):
	data = sporttracksstuff.createsporttracksworkoutdata(w)
        if not data:
            message = "Data error"
            messages.error(request,message)
            url = reverse(workout_export_view,
		          kwargs = {
		              'id':str(w.id),
		          })
            return HttpResponseRedirect(url)
        
	authorizationstring = str('Bearer ' + thetoken)
	headers = {'Authorization': authorizationstring,
		   'user-agent': 'sanderroosendaal',
		   'Content-Type': 'application/json'}

	url = "https://api.sporttracks.mobi/api/v2/fitnessActivities.json"
	response = requests.post(url,headers=headers,data=json.dumps(data))

	# check for duplicate error first
	if (response.status_code == 409 ):
	    message = "Duplicate error"
            messages.error(request,message)
	    w.uploadedtosporttracks = -1
	    w.save()
	elif (response.status_code == 201 or response.status_code==200):
	    s= json.loads(response.text)
	    sporttracksid = sporttracksstuff.getidfromresponse(response)
	    w.uploadedtosporttracks = sporttracksid
	    w.save()
            message = "Upload to SportTracks was successful"
            messages.info(request,message)
	    url = "/rowers/workout/"+str(w.id)+"/export"
	    return HttpResponseRedirect(url)
	else:
	    s = response
	    message = "Something went wrong in workout_sporttracks_upload_view: %s" % s.reason
	    messages.error(request,message)
    else:
	message = "You are not authorized to upload this workout"
        messages.error(request,message)
        
    url = reverse(workout_export_view,
		  kwargs = {
		      'id':str(w.id),
		      })

    return HttpResponseRedirect(url)

# Concept2 authorization 	  
@login_required()
def rower_c2_authorize(request):
    # Generate a random string for the state parameter
    # Save it for use later to prevent xsrf attacks
    from uuid import uuid4
    state = str(uuid4())
    scope = "user:read,results:write"
    params = {"client_id": C2_CLIENT_ID,
              "response_type": "code",
              "redirect_uri": C2_REDIRECT_URI}
    url = "http://log.concept2.com/oauth/authorize?"+ urllib.urlencode(params)
    url += "&scope="+scope
    return HttpResponseRedirect(url)

# Strava Authorization
@login_required()
def rower_strava_authorize(request):
    # Generate a random string for the state parameter
    # Save it for use later to prevent xsrf attacks
    from uuid import uuid4
    state = str(uuid4())

    params = {"client_id": STRAVA_CLIENT_ID,
              "response_type": "code",
              "redirect_uri": STRAVA_REDIRECT_URI,
	      "scope": "write"}

    url = "https://www.strava.com/oauth/authorize?"+ urllib.urlencode(params)

    return HttpResponseRedirect(url)

# Runkeeper authorization
@login_required()
def rower_runkeeper_authorize(request):
    # Generate a random string for the state parameter
    # Save it for use later to prevent xsrf attacks
    from uuid import uuid4
    state = str(uuid4())

    params = {"client_id": RUNKEEPER_CLIENT_ID,
              "response_type": "code",
	      "state": state,
              "redirect_uri": RUNKEEPER_REDIRECT_URI}

    url = "https://runkeeper.com/apps/authorize?"+ urllib.urlencode(params)


    return HttpResponseRedirect(url)

# SportTracks Authorization
@login_required()
def rower_sporttracks_authorize(request):
    # Generate a random string for the state parameter
    # Save it for use later to prevent xsrf attacks
    from uuid import uuid4
    state = str(uuid4())

    params = {"client_id": SPORTTRACKS_CLIENT_ID,
              "response_type": "code",
	      "state": state,
              "redirect_uri": SPORTTRACKS_REDIRECT_URI}

    url = "https://api.sporttracks.mobi/oauth2/authorize?"+ urllib.urlencode(params)


    return HttpResponseRedirect(url)

# Underarmour Authorization
@login_required()
def rower_underarmour_authorize(request):
    # Generate a random string for the state parameter
    # Save it for use later to prevent xsrf attacks
    from uuid import uuid4
    state = str(uuid4())

    redirect_uri = UNDERARMOUR_REDIRECT_URI
    
    url = 'https://www.mapmyfitness.com/v7.1/oauth2/authorize/?' \
                'client_id={0}&response_type=code&redirect_uri={1}'.format(
                    UNDERARMOUR_CLIENT_KEY, redirect_uri
                )

    return HttpResponseRedirect(url)

# Underarmour Authorization
@login_required()
def rower_tp_authorize(request):
    # Generate a random string for the state parameter
    # Save it for use later to prevent xsrf attacks
    from uuid import uuid4
    state = str(uuid4())
    params = {"client_id": TP_CLIENT_KEY,
              "response_type": "code",
              "redirect_uri": TP_REDIRECT_URI,
              "scope": "file:write",
	      }
    url = "https://oauth.trainingpeaks.com/oauth/authorize/?" +urllib.urlencode(params)

    return HttpResponseRedirect(url)


# Concept2 token refresh. URL for manual refresh. Not visible to users
@login_required()
def rower_c2_token_refresh(request):
    r = getrower(request.user)
    res = c2stuff.do_refresh_token(r.c2refreshtoken)
    if res[0] != None:
        access_token = res[0]
        expires_in = res[1]
        refresh_token = res[2]
        expirydatetime = timezone.now()+datetime.timedelta(seconds=expires_in)
        r = getrower(request.user)
        r.c2token = access_token
        r.tokenexpirydate = expirydatetime
        r.c2refreshtoken = refresh_token

        r.save()

        successmessage = "Tokens refreshed. Good to go"
        messages.info(request,successmessage)
    else:
        message = "Something went wrong (refreshing tokens). Please reauthorize:"
        messages.error(request,successmessage)
        
    return imports_view(request)

# Underarmour token refresh. URL for manual refresh. Not visible to users
@login_required()
def rower_underarmour_token_refresh(request):
    r = getrower(request.user)
    res = underarmourstuff.do_refresh_token(
        r.underarmourrefreshtoken,
        r.underarmourtoken
    )
    access_token = res[0]
    expires_in = res[1]
    refresh_token = res[2]
    expirydatetime = timezone.now()+datetime.timedelta(seconds=expires_in)

    r = getrower(request.user)
    r.underarmourtoken = access_token
    r.underarmourtokenexpirydate = expirydatetime
    r.underarmourrefreshtoken = refresh_token

    r.save()

    successmessage = "Tokens refreshed. Good to go"
    messages.info(request,successmessage)
    return imports_view(request)


# TrainingPeaks token refresh. URL for manual refresh. Not visible to users
@login_required()
def rower_tp_token_refresh(request):
    r = getrower(request.user)
    res = tpstuff.do_refresh_token(
        r.tprefreshtoken,
    )
    access_token = res[0]
    expires_in = res[1]
    refresh_token = res[2]
    expirydatetime = timezone.now()+datetime.timedelta(seconds=expires_in)

    r = getrower(request.user)
    r.tptoken = access_token
    r.tptokenexpirydate = expirydatetime
    r.tprefreshtoken = refresh_token

    r.save()

    successmessage = "Tokens refreshed. Good to go"
    messages.info(request,successmessage)
    return imports_view(request)


# SportTracks token refresh. URL for manual refresh. Not visible to users
@login_required()
def rower_sporttracks_token_refresh(request):
    r = getrower(request.user)
    res = sporttracksstuff.do_refresh_token(
        r.sporttracksrefreshtoken,
        )
    access_token = res[0]
    expires_in = res[1]
    refresh_token = res[2]
    expirydatetime = timezone.now()+datetime.timedelta(seconds=expires_in)

    r = getrower(request.user)
    r.sporttrackstoken = access_token
    r.sporttrackstokenexpirydate = expirydatetime
    r.sporttracksrefreshtoken = refresh_token

    r.save()

    successmessage = "Tokens refreshed. Good to go"
    messages.info(request,successmessage)
    return imports_view(request)


# Concept2 Callback
@login_required()
def rower_process_callback(request):
    try:
	code = request.GET['code']
	res = c2stuff.get_token(code)
    except MultiValueDictKeyError:
	message = "The resource owner or authorization server denied the request"
        messages.error(request,message)
	return imports_view(request)
	
    access_token = res[0]
    if access_token == 0:
        message = res[1]
        message += ' Contact info@rowsandall.com if this behavior persists.'
        messages.error(request,message)
        return imports_view(request)
        
    expires_in = res[1]
    refresh_token = res[2]
    expirydatetime = timezone.now()+datetime.timedelta(seconds=expires_in)

    r = getrower(request.user)
    r.c2token = access_token
    r.tokenexpirydate = expirydatetime
    r.c2refreshtoken = refresh_token

    r.save()

    successmessage = "Tokens stored. Good to go"
    messages.info(request,successmessage)
    return imports_view(request)

# The imports page
@login_required()
def imports_view(request,successmessage="",message=""):
    messages.info(request,successmessage)
    messages.error(request,message)
    return render(request,"imports.html",
		  {
                      'teams':get_my_teams(request.user),
		   })

# Just for testing purposes
@login_required()
def test_reverse_view(request):
    successmessage = "Tokens stored. Good to go"
    messages.info(request,successmessage)
    return imports_view(request)

# dummy 
@login_required()
def rower_process_twittercallback(request):
    return "dummy"

# Process Strava Callback
@login_required()
def rower_process_stravacallback(request):
    try:
        code = request.GET['code']
    except MultiValueDictKeyError:
        try:
            message = request.GET['error']
        except MultiValueDictKeyError:
            message = "access error"

        messages.error(request,message)
        return imports_view(request)
            
    res = stravastuff.get_token(code)

    if res[0]:
        access_token = res[0]
	      
        r = getrower(request.user)
        r.stravatoken = access_token

        r.save()

        successmessage = "Tokens stored. Good to go"
        messages.info(request,successmessage)
        return imports_view(request)
    else:
        message = "Something went wrong with the Strava authorization"
        messages.error(request,message)
        return imports_view(request)

# Process Runkeeper callback
@login_required()
def rower_process_runkeepercallback(request):
    code = request.GET['code']
    access_token = runkeeperstuff.get_token(code)

    r = getrower(request.user)
    r.runkeepertoken = access_token

    r.save()

    successmessage = "Tokens stored. Good to go"
    messages.info(request,successmessage)
    return imports_view(request)

# Process SportTracks callback
@login_required()
def rower_process_sporttrackscallback(request):
    code = request.GET['code']
    res = sporttracksstuff.get_token(code)


    access_token = res[0]
    expires_in = res[1]
    refresh_token = res[2]
    expirydatetime = timezone.now()+datetime.timedelta(seconds=expires_in)
    
    r = getrower(request.user)
    r.sporttrackstoken = access_token
    r.sporttrackstokenexpirydate = expirydatetime
    r.sporttracksrefreshtoken = refresh_token

    r.save()

    successmessage = "Tokens stored. Good to go"
    messages.info(request,successmessage)
    return imports_view(request)

# Process Underarmour callback
@login_required()
def rower_process_underarmourcallback(request):
    code = request.GET['code']
    res = underarmourstuff.get_token(code)


    access_token = res[0]
    expires_in = res[1]
    refresh_token = res[2]
    expirydatetime = timezone.now()+datetime.timedelta(seconds=expires_in)
    
    r = getrower(request.user)
    r.underarmourtoken = access_token
    r.underarmourtokenexpirydate = expirydatetime
    r.underarmourrefreshtoken = refresh_token

    r.save()

    successmessage = "Tokens stored. Good to go"
    messages.info(request,successmessage)
    return imports_view(request)

# Process TrainingPeaks callback
@login_required()
def rower_process_tpcallback(request):
    code = request.GET['code']
    res = tpstuff.get_token(code)


    access_token = res[0]
    expires_in = res[1]
    refresh_token = res[2]
    expirydatetime = timezone.now()+datetime.timedelta(seconds=expires_in)
    
    r = getrower(request.user)
    r.tptoken = access_token
    r.tptokenexpirydate = expirydatetime
    r.tprefreshtoken = refresh_token

    r.save()

    successmessage = "Tokens stored. Good to go"
    messages.info(request,successmessage)
    return imports_view(request)

# Process Own API callback - for API testing purposes
@login_required()
def rower_process_testcallback(request):
    code = request.GET['code']
    res = ownapistuff.get_token(code)


    access_token = res[0]
    expires_in = res[1]
    refresh_token = res[2]
    expirydatetime = timezone.now()+datetime.timedelta(seconds=expires_in)

    text = "Access Token:\n"
    text += access_token

    text += "\n\nRefresh Token:\n"
    text += refresh_token
    
    return HttpResponse(text)

# View around the Histogram of all strokes. Not implemented in UI
@login_required()
def histo_all(request,theuser=0):
    promember=0
    if theuser == 0:
	theuser = request.user.id

    if not request.user.is_anonymous():
	r = getrower(request.user)
	result = request.user.is_authenticated() and ispromember(request.user)
	if result:
	    promember=1

    if not promember:
	return HttpResponseRedirect("/rowers/about/")
	
    # get all indoor rows of past 12 months
    ayearago = timezone.now()-datetime.timedelta(days=365)
    try:
	r2 = getrower(theuser)
	allergworkouts = Workout.objects.filter(user=r2,
						workouttype__in=['rower','dynamic','slides'],
						startdatetime__gte=ayearago)
    except Rower.DoesNotExist:
	allergworkouts = []
	r2=0

    try:
	u = User.objects.get(id=theuser)
    except User.DoesNotExist:
	u = ''

    if allergworkouts:
	res = interactive_histoall(allergworkouts)
	script = res[0]
	div = res[1]
    else:
	script = ''
	div = '<p>No erg pieces uploaded yet.</p>'

    return render(request, 'histoall.html',
		  {'interactiveplot':script,
		   'the_div':div,
		   'id':theuser,
		   'theuser':u,
                   'teams':get_my_teams(request.user),
		   })

# The Flex plot for a large selection of workouts
@login_required()
def cum_flex(request,theuser=0,
	     xparam='spm',
	     yparam1='power',
	     yparam2='None',
	     startdate=timezone.now()-datetime.timedelta(days=10),
	     enddate=timezone.now()+datetime.timedelta(days=1),
	     deltadays=-1,
	     startdatestring="",
	     enddatestring="",
             options={
                 'includereststrokes':False,
                 'workouttypes':['rower','dynamic','slides'],
                 'waterboattype':['1x','2x','2-','4x','4-','8+']
             }):

    if 'options' in request.session:
        options = request.session['options']

    workouttypes = options['workouttypes']
    includereststrokes = options['includereststrokes']
    waterboattype = options['waterboattype']
    workstrokesonly = not includereststrokes


    checktypes = ['water','rower','dynamic','slides','skierg',
                  'paddle','snow','coastal','other']

    
    if deltadays>0:
	startdate = enddate-datetime.timedelta(days=int(deltadays))

    if startdatestring != "":
	startdate = iso8601.parse_date(startdatestring)

    if enddatestring != "":
	enddate = iso8601.parse_date(enddatestring)

    if enddate < startdate:
	s = enddate
	enddate = startdate
	startdate = s

    promember=0
    if theuser == 0:
	theuser = request.user.id

    if not request.user.is_anonymous():
	r = getrower(request.user)
	result = request.user.is_authenticated() and ispromember(request.user)
	if result:
	    promember=1

    #if not promember:
	#return HttpResponseRedirect("/rowers/about/")
	
    # get all indoor rows of in date range
    
    # process form
    if request.method == 'POST' and "daterange" in request.POST:
	form = DateRangeForm(request.POST)
	deltaform = DeltaDaysForm(request.POST)
        optionsform = StatsOptionsForm()
	if form.is_valid():
	    startdate = form.cleaned_data['startdate']
	    enddate = form.cleaned_data['enddate']
	    if startdate > enddate:
		s = enddate
		enddate = startdate
		startdate = s
    elif request.method == 'POST' and "datedelta" in request.POST:
	deltaform = DeltaDaysForm(request.POST)
        optionsform = StatsOptionsForm()
	if deltaform.is_valid():
	    deltadays = deltaform.cleaned_data['deltadays']
	    if deltadays != 0 and isinstance(deltadays, Number):
		enddate = timezone.now()
		startdate = enddate-datetime.timedelta(days=deltadays)
		if startdate > enddate:
		    s = enddate
		    enddate = startdate
		    startdate = s
		form = DateRangeForm(initial={
		    'startdate': startdate,
		    'enddate': enddate,
		    })
            else:
                form = DateRangeForm()
                optionsform = StatsOptionsForm()
    elif request.method == 'POST' and 'options' in request.POST:
        optionsform = StatsOptionsForm(request.POST)
        if optionsform.is_valid():
            includereststrokes = optionsform.cleaned_data['includereststrokes']
            workstrokesonly = not includereststrokes
            waterboattype = optionsform.cleaned_data['waterboattype']
            workouttypes = []
            for type in checktypes:
                if optionsform.cleaned_data[type]:
                    workouttypes.append(type)
                    
                    
            options = {
                'includereststrokes':includereststrokes,
                'workouttypes':workouttypes,
                'waterboattype':waterboattype,
                }
            form = DateRangeForm(initial={
	    'startdate': startdate,
	    'enddate': enddate,
	    })
            deltaform = DeltaDaysForm()
        else:
            form = DateRangeForm(initial={
	    'startdate': startdate,
	    'enddate': enddate,
	    })
            deltaform = DeltaDaysForm()
    else:
	form = DateRangeForm(initial={
	    'startdate': startdate,
	    'enddate': enddate,
	    })
	deltaform = DeltaDaysForm()
        optionsform = StatsOptionsForm()
    try:
	r2 = getrower(theuser)
	allworkouts = Workout.objects.filter(user=r2,
					     workouttype__in=workouttypes,
                                             boattype__in=waterboattype,
					     startdatetime__gte=startdate,
					     startdatetime__lte=enddate)
	
    except Rower.DoesNotExist:
	allworkouts = []
	r2=0

    try:
	u = User.objects.get(id=theuser)
    except User.DoesNotExist:
	u = ''

    if allworkouts:
	res = interactive_cum_flex_chart2(allworkouts,xparam=xparam,
					  yparam1=yparam1,
					  yparam2=yparam2,
					  promember=promember,
                                          workstrokesonly=workstrokesonly)
	script = res[0]
	div = res[1]
	js_resources = res[2]
	css_resources = res[3]
    else:
	script = ''
	div = '<p>No erg pieces uploaded for this date range.</p>'
	js_resources = ''
	css_resources = ''

    axchoicesbasic = {ax[0]:ax[1] for ax in axes if ax[4]=='basic'}
    axchoicespro = {ax[0]:ax[1] for ax in axes if ax[4]=='pro'}
    noylist = ["time","distance"]
    axchoicesbasic.pop("cumdist")

    # set options form correctly
    initial = {}
    initial['includereststrokes'] = includereststrokes

    initial['waterboattype'] = waterboattype

    for wtype in checktypes:
        if wtype in workouttypes:
            initial[wtype] = True
        else:
            initial[wtype] = False


    optionsform = StatsOptionsForm(initial=initial)
        
    request.session['options'] = options

    return render(request, 'cum_flex.html',
		  {'interactiveplot':script,
		   'the_div':div,
		   'js_res': js_resources,
		   'css_res':css_resources,
		   'id':theuser,
		   'theuser':u,
		   'startdate':startdate,
		   'enddate':enddate,
		   'form':form,
                   'optionsform':optionsform,
		   'deltaform':deltaform,
		   'xparam':xparam,
		   'yparam1':yparam1,
		   'yparam2':yparam2,
		   'promember':promember,
                   'teams':get_my_teams(request.user),
                   'axchoicesbasic':axchoicesbasic,
                   'axchoicespro':axchoicespro,
                   'noylist':noylist,
		   })

# Show the EMpower Oarlock generated Stroke Profile
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def workout_forcecurve_view(request,id=0,workstrokesonly=False):
    try:
        row = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

    promember=0
    mayedit=0
    if not request.user.is_anonymous():
	r = getrower(request.user)
	result = request.user.is_authenticated() and ispromember(request.user)
	if result:
	    promember=1
	if request.user == row.user.user:
	    mayedit=1

    if not promember:
	return HttpResponseRedirect("/rowers/about/")

    if request.method == 'POST' and 'workstrokesonly' in request.POST:
        workstrokesonly = request.POST['workstrokesonly']
	if workstrokesonly == 'True':
	    workstrokesonly = True
	else:
	    workstrokesonly = False
            
    script,div,js_resources,css_resources = interactive_forcecurve([row],
                                                                   workstrokesonly=workstrokesonly)

    return render(request,
                  'forcecurve_single.html',
                  {
                      'the_script':script,
                      'the_div':div,
		      'js_res': js_resources,
		      'css_res':css_resources,
                      'id':int(id),
                      'mayedit':mayedit,
                      'workstrokesonly': not workstrokesonly,
                      'teams':get_my_teams(request.user),
                  })

# Test asynchronous tasking and messaging
@login_required()
def workout_test_task_view(request,id=0):
    row = Workout.objects.get(id=id)
    if settings.DEBUG:	    
        res = addcomment2.delay(request.user.id,row.id)
    else:
        #res = queuehigh.enqueue(addcomment2,request.user.id,row.id)
        res = queuehigh.enqueue(addcomment2,request.user.id,row.id)


    url = reverse(workout_edit_view,
                  kwargs = {
                      'id':int(id),
                  })
    return HttpResponseRedirect(url)

# Show Stroke power histogram for a workout
@login_required()
def workout_histo_view(request,id=0):
    try:
        row = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

    promember=0
    mayedit=0
    if not request.user.is_anonymous():
	r = getrower(request.user)
	result = request.user.is_authenticated() and ispromember(request.user)
	if result:
	    promember=1
	    if request.user == row.user.user:
		mayedit=1

    if not promember:
	return HttpResponseRedirect("/rowers/about/")
        
    res = interactive_histoall([row])
    script = res[0]
    div = res[1]

    return render(request,
                  'histo_single.html',
		  {'interactiveplot':script,
		   'the_div':div,
                   'id':int(id),
                   'mayedit':mayedit,
                   'teams':get_my_teams(request.user),
		   })



# Histogram for a date/time range
@login_required()
def histo(request,theuser=0,
	  startdate=timezone.now()-datetime.timedelta(days=365),
	  enddate=timezone.now(),
	  deltadays=-1,
	  startdatestring="",
	  enddatestring=""):

    if deltadays>0:
	startdate = enddate-datetime.timedelta(days=int(deltadays))

    if startdatestring != "":
	startdate = iso8601.parse_date(startdatestring)

    if enddatestring != "":
	enddate = iso8601.parse_date(enddatestring)

    if enddate < startdate:
	s = enddate
	enddate = startdate
	startdate = s

    promember=0
    if theuser == 0:
	theuser = request.user.id

    if not request.user.is_anonymous():
	r = getrower(request.user)
	result = request.user.is_authenticated() and ispromember(request.user)
	if result:
	    promember=1

    if not promember:
	return HttpResponseRedirect("/rowers/promembership/")
	
    # get all indoor rows of in date range
    
    # process form
    if request.method == 'POST' and "daterange" in request.POST:
	form = DateRangeForm(request.POST)
	deltaform = DeltaDaysForm(request.POST)
	if form.is_valid():
	    startdate = form.cleaned_data['startdate']
	    enddate = form.cleaned_data['enddate']
	    if startdate > enddate:
		s = enddate
		enddate = startdate
		startdate = s
    elif request.method == 'POST' and "datedelta" in request.POST:
	deltaform = DeltaDaysForm(request.POST)
	if deltaform.is_valid():
	    deltadays = deltaform.cleaned_data['deltadays']
	    if deltadays != 0:
		enddate = timezone.now()
		startdate = enddate-datetime.timedelta(days=deltadays)
		if startdate > enddate:
		    s = enddate
		    enddate = startdate
		    startdate = s
		form = DateRangeForm(initial={
		    'startdate': startdate,
		    'enddate': enddate,
		    })
            else:
                form = DateRangeForm()

    else:
	form = DateRangeForm(initial={
	    'startdate': startdate,
	    'enddate': enddate,
	    })
	deltaform = DeltaDaysForm()

    try:
	r2 = getrower(theuser)
	allergworkouts = Workout.objects.filter(user=r2,
						workouttype__in=['rower','dynamic','slides'],
						startdatetime__gte=startdate,
						startdatetime__lte=enddate)
	
    except Rower.DoesNotExist:
	allergworkouts = []
	r2=0

    try:
	u = User.objects.get(id=theuser)
    except User.DoesNotExist:
	u = ''

    if allergworkouts:
	res = interactive_histoall(allergworkouts)
	script = res[0]
	div = res[1]
    else:
	script = ''
	div = '<p>No erg pieces uploaded for this date range.</p>'


    return render(request, 'histo.html',
		  {'interactiveplot':script,
		   'the_div':div,
		   'id':theuser,
		   'theuser':u,
		   'startdate':startdate,
		   'enddate':enddate,
		   'form':form,
		   'deltaform':deltaform,
                   'teams':get_my_teams(request.user),
		   })

# Show ranking distances including predicted paces
@login_required()
def rankings_view(request,theuser=0,
	  startdate=timezone.now()-datetime.timedelta(days=365),
	  enddate=timezone.now(),
	  deltadays=-1,
	  startdatestring="",
	  enddatestring=""):

    if deltadays>0:
	startdate = enddate-datetime.timedelta(days=int(deltadays))

    if startdatestring != "":
	startdate = iso8601.parse_date(startdatestring)

    if enddatestring != "":
	enddate = iso8601.parse_date(enddatestring)

    if enddate < startdate:
	s = enddate
	enddate = startdate
	startdate = s

    if theuser == 0:
	theuser = request.user.id

    promember=0
    if not request.user.is_anonymous():
	r = getrower(request.user)
	result = request.user.is_authenticated() and ispromember(request.user)
	if result:
	    promember=1

    # get all indoor rows in date range
    
    # process form
    if request.method == 'POST' and "daterange" in request.POST:
	dateform = DateRangeForm(request.POST)
	deltaform = DeltaDaysForm(request.POST)
	if dateform.is_valid():
	    startdate = dateform.cleaned_data['startdate']
	    enddate = dateform.cleaned_data['enddate']
	    if startdate > enddate:
		s = enddate
		enddate = startdate
		startdate = s
    elif request.method == 'POST' and "datedelta" in request.POST:
	deltaform = DeltaDaysForm(request.POST)
	if deltaform.is_valid():
	    deltadays = deltaform.cleaned_data['deltadays']
	    if deltadays:
		enddate = timezone.now()
		startdate = enddate-datetime.timedelta(days=deltadays)
		if startdate > enddate:
		    s = enddate
		    enddate = startdate
		    startdate = s
		dateform = DateRangeForm(initial={
		    'startdate': startdate,
		    'enddate': enddate,
		    })
            else:
                dateform = DateRangeForm()
                deltaform = DeltaDaysForm()

    else:
	dateform = DateRangeForm(initial={
	    'startdate': startdate,
	    'enddate': enddate,
	    })
	deltaform = DeltaDaysForm()

    # get all 2k (if any) - this rower, in date range
    try:
	r = getrower(theuser)
    except Rower.DoesNotExist:
	allergworkouts = []
	r=0

	
    try:
	uu = User.objects.get(id=theuser)
    except User.DoesNotExist:
	uu = ''


    # test to fix bug
    startdate = datetime.datetime.combine(startdate,datetime.time())
    enddate = datetime.datetime.combine(enddate,datetime.time(23,59,59))
    enddate = enddate+datetime.timedelta(days=1)

    rankingdistances = [100,500,1000,2000,5000,6000,10000,21097,42195,100000]
    rankingdurations = []
    rankingdurations.append(datetime.time(minute=1))
    rankingdurations.append(datetime.time(minute=4))
    rankingdurations.append(datetime.time(minute=30))
    rankingdurations.append(datetime.time(hour=1))

    thedistances = []
    theworkouts = []
    thesecs = []



    rankingdistances.sort()
    rankingdurations.sort()

    for rankingdistance in rankingdistances:
    
	workouts = Workout.objects.filter(user=r,distance=rankingdistance,
				      workouttype__in=['rower','dynamic','slides'],
					  startdatetime__gte=startdate,
					  startdatetime__lte=enddate).order_by('duration')
	if workouts:
	    thedistances.append(rankingdistance)
	    theworkouts.append(workouts[0])

	    timesecs = 3600*workouts[0].duration.hour
	    timesecs += 60*workouts[0].duration.minute
	    timesecs += workouts[0].duration.second
	    timesecs += 1.e-6*workouts[0].duration.microsecond
	
	    thesecs.append(timesecs)

    for rankingduration in rankingdurations:
    
	workouts = Workout.objects.filter(user=r,duration=rankingduration,
				          workouttype='rower',
				          startdatetime__gte=startdate,
					  startdatetime__lte=enddate).order_by('-distance')
	if workouts:
	    thedistances.append(workouts[0].distance)
	    theworkouts.append(workouts[0])

	    timesecs = 3600*workouts[0].duration.hour
	    timesecs += 60*workouts[0].duration.minute
	    timesecs += workouts[0].duration.second
	    timesecs += 1.e-5*workouts[0].duration.microsecond
	
	    thesecs.append(timesecs)

    thedistances = np.array(thedistances)
    thesecs = np.array(thesecs)

    thevelos = thedistances/thesecs
    theavpower = 2.8*(thevelos**3)


    # create interactive plot
    if len(thedistances) !=0 :
	res = interactive_cpchart(thedistances,thesecs,theavpower,
				  theworkouts,promember=promember)
	script = res[0]
	div = res[1]
	paulslope = res[2]
	paulintercept = res[3]
	p1 = res[4]
	message = res[5]
    else:
	script = ''
	div = '<p>No ranking pieces found.</p>'
	paulslope = 1
	paulintercept = 1
	p1 = [1,1,1,1]
	message = ""


    if request.method == 'POST' and "piece" in request.POST:
	form = PredictedPieceForm(request.POST)
	if form.is_valid():
	    value = form.cleaned_data['value']
            hourvalue,value = divmod(value,60)
            if hourvalue >= 24:
                hourvalue = 23
	    pieceunit = form.cleaned_data['pieceunit']
	    if pieceunit == 'd':
		rankingdistances.append(value)
	    else:
		rankingdurations.append(datetime.time(minute=int(value),hour=int(hourvalue)))
    else:
	form = PredictedPieceForm()

    rankingdistances.sort()
    rankingdurations.sort()


    predictions = []
    cpredictions = []


    for rankingdistance in rankingdistances:
	# Paul's model
	p = paulslope*np.log10(rankingdistance)+paulintercept
	velo = 500./p
	t = rankingdistance/velo
	pwr = 2.8*(velo**3)
	a = {'distance':rankingdistance,
	     'duration':timedeltaconv(t),
	     'pace':timedeltaconv(p),
	     'power':int(pwr)}
	predictions.append(a)

	# CP model -
	pwr2 = p1[0]/(1+t/p1[2])
	pwr2 += p1[1]/(1+t/p1[3])

	if pwr2 <= 0:
	    pwr2 = 50.
	
	velo2 = (pwr2/2.8)**(1./3.)

	if np.isnan(velo2) or velo2 <= 0:
	    velo2 = 1.0
	    
	t2 = rankingdistance/velo2
	
	pwr3 = p1[0]/(1+t2/p1[2])
	pwr3 += p1[1]/(1+t2/p1[3])

	if pwr3 <= 0:
	    pwr3 = 50.
	
	velo3 = (pwr3/2.8)**(1./3.)
	if np.isnan(velo3) or velo3 <= 0:
	    velo3 = 1.0
	    
	t3 = rankingdistance/velo3
	p3 = 500./velo3

	a = {'distance':rankingdistance,
	     'duration':timedeltaconv(t3),
	     'pace':timedeltaconv(p3),
	     'power':int(pwr3)}
	cpredictions.append(a)




    for rankingduration in rankingdurations:
	t = 3600.*rankingduration.hour
	t += 60.*rankingduration.minute
	t += rankingduration.second
	t += rankingduration.microsecond/1.e6

	# Paul's model
	ratio = paulintercept/paulslope

	u = ((2**(2+ratio))*(5.**(3+ratio))*t*np.log(10))/paulslope

	d = 500*t*np.log(10.)
	d = d/(paulslope*lambertw(u))
	d = d.real

	velo = d/t
	p = 500./velo
	pwr = 2.8*(velo**3)
	a = {'distance':int(d),
	     'duration':timedeltaconv(t),
	     'pace':timedeltaconv(p),
	     'power':int(pwr)}
	predictions.append(a)

	# CP model
	pwr = p1[0]/(1+t/p1[2])
	pwr += p1[1]/(1+t/p1[3])

	if pwr <= 0:
	    pwr = 50.

	velo = (pwr/2.8)**(1./3.)

	if np.isnan(velo) or velo <=0:
	    velo = 1.0
	
	d = t*velo
	p = 500./velo
	a = {'distance':int(d),
	     'duration':timedeltaconv(t),
	     'pace':timedeltaconv(p),
	     'power':int(pwr)}
	cpredictions.append(a)


    messages.error(request,message)
    return render(request, 'rankings.html',
		  {'rankingworkouts':theworkouts,
		   'interactiveplot':script,
		   'the_div':div,
		   'predictions':predictions,
		   'cpredictions':cpredictions,
		   'nrdata':len(thedistances),
		   'form':form,
		   'dateform':dateform,
		   'deltaform':deltaform,
		   'id': theuser,
		   'theuser':uu,
		   'startdate':startdate,
		   'enddate':enddate,
                   'teams':get_my_teams(request.user),
		   })

@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def workout_update_cp_view(request,id=0):
    try:
        row = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

    if (checkworkoutuser(request.user,row)==False):
	message = "You are not allowed to edit this workout"
        messages.error(request,message)
	url = reverse(workouts_view)

	return HttpResponseRedirect(url)

    row.rankingpiece = True
    row.save()

    url = reverse(otwrankings_view)

    return HttpResponseRedirect(url)

# Show ranking distances including predicted paces
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def otwrankings_view(request,theuser=0,
	             startdate=timezone.now()-datetime.timedelta(days=365),
	             enddate=timezone.now(),
	             deltadays=-1,
	             startdatestring="",
	             enddatestring=""):

    if deltadays>0:
	startdate = enddate-datetime.timedelta(days=int(deltadays))

    if startdatestring != "":
	startdate = iso8601.parse_date(startdatestring)

    if enddatestring != "":
	enddate = iso8601.parse_date(enddatestring)

    if enddate < startdate:
	s = enddate
	enddate = startdate
	startdate = s

    if theuser == 0:
	theuser = request.user.id

    promember=0
    if not request.user.is_anonymous():
	r = Rower.objects.get(user=request.user)
	result = request.user.is_authenticated() and ispromember(request.user)
	if result:
	    promember=1

    # get all OTW rows in date range
    
    # process form
    if request.method == 'POST' and "daterange" in request.POST:
	dateform = DateRangeForm(request.POST)
	deltaform = DeltaDaysForm(request.POST)
	if dateform.is_valid():
	    startdate = dateform.cleaned_data['startdate']
	    enddate = dateform.cleaned_data['enddate']
	    if startdate > enddate:
		s = enddate
		enddate = startdate
		startdate = s
    elif request.method == 'POST' and "datedelta" in request.POST:
	deltaform = DeltaDaysForm(request.POST)
	if deltaform.is_valid():
	    deltadays = deltaform.cleaned_data['deltadays']
	    if deltadays:
		enddate = timezone.now()
		startdate = enddate-datetime.timedelta(days=deltadays)
		if startdate > enddate:
		    s = enddate
		    enddate = startdate
		    startdate = s
		dateform = DateRangeForm(initial={
		    'startdate': startdate,
		    'enddate': enddate,
		    })
            else:
                dateform = DateRangeForm()
                deltaform = DeltaDaysForm()

    else:
	dateform = DateRangeForm(initial={
	    'startdate': startdate,
	    'enddate': enddate,
	    })
	deltaform = DeltaDaysForm()

    # get all 2k (if any) - this rower, in date range
    try:
	r = Rower.objects.get(user=theuser)
    except Rower.DoesNotExist:
	allergworkouts = []
	r=0

	
    try:
	uu = User.objects.get(id=theuser)
    except User.DoesNotExist:
	uu = ''


    # test to fix bug
    startdate = datetime.datetime.combine(startdate,datetime.time())
    enddate = datetime.datetime.combine(enddate,datetime.time(23,59,59))
    enddate = enddate+datetime.timedelta(days=1)

 
    rankingdurations = []
    rankingdurations.append(datetime.time(minute=1))
    rankingdurations.append(datetime.time(minute=4))
    rankingdurations.append(datetime.time(minute=30))
    rankingdurations.append(datetime.time(hour=1))

    thedistances = []
    theworkouts = []
    thesecs = []
    
    theworkouts = Workout.objects.filter(user=r,rankingpiece=True,
				          workouttype='water',
				          startdatetime__gte=startdate,
					  startdatetime__lte=enddate)


    # get all power data from database (plus workoutid)
    theids = [int(w.id) for w in theworkouts]
    columns = ['power','workoutid','time']
    df = dataprep.getsmallrowdata_db(columns,ids=theids)

    thesecs = []
    
    for w in theworkouts:
        timesecs = 3600*w.duration.hour
	timesecs += 60*w.duration.minute
	timesecs += w.duration.second
	timesecs += 1.e-5*w.duration.microsecond
	
	thesecs.append(timesecs)


    if len(thesecs) != 0:
        maxt = 1.05*pd.Series(thesecs).max()
    else:
        maxt = 1000.

        
    logarr = datautils.getlogarr(maxt)

    dfgrouped = df.groupby(['workoutid'])
    delta,cpvalue,avgpower = datautils.getcp(dfgrouped,logarr)
    
    powerdf = pd.DataFrame({
        'Delta':delta,
        'CP':cpvalue,
        })


    
    powerdf = powerdf[powerdf['CP']>0]
    powerdf.dropna(axis=0,inplace=True)
    powerdf.sort_values(['Delta','CP'],ascending=[1,0],inplace=True)
    powerdf.drop_duplicates(subset='Delta',keep='first',inplace=True)


    # create interactive plot
    if len(powerdf) !=0 :
	res = interactive_otwcpchart(powerdf,promember=promember)
	script = res[0]
	div = res[1]
	p1 = res[2]
        ratio = res[3]
        r.p0 = p1[0]
        r.p1 = p1[1]
        r.p2 = p1[2]
        r.p3 = p1[3]
        r.cpratio = ratio
        r.save()
        paulslope = 1
        paulintercept = 1
	message = res[4]
    else:
	script = ''
	div = '<p>No ranking pieces found.</p>'
	paulslope = 1
	paulintercept = 1
	p1 = [1,1,1,1]
	message = ""


    if request.method == 'POST' and "piece" in request.POST:
	form = PredictedPieceForm(request.POST)
        clean = form.is_valid()
	value = form.cleaned_data['value']
        hourvalue,value = divmod(value,60)
        hourvalue = int(hourvalue)
        minutevalue = int(value)
        value = int(60*(value-minutevalue))
        if hourvalue >= 24:
            hourvalue = 23
	rankingdurations.append(datetime.time(minute=minutevalue,
                                              hour=hourvalue,
                                              second=value))
    else:
	form = PredictedPieceForm()


    cpredictions = []

    for rankingduration in rankingdurations:
	t = 3600.*rankingduration.hour
	t += 60.*rankingduration.minute
	t += rankingduration.second
	t += rankingduration.microsecond/1.e6


	# CP model
	pwr = p1[0]/(1+t/p1[2])
	pwr += p1[1]/(1+t/p1[3])

        
	if pwr <= 0:
	    pwr = 50.


        if  not np.isnan(pwr):
            try:
                pwr2 = pwr*ratio
            except:
                pwr2 = pwr

            a = {
	        'duration':timedeltaconv(t),
	        'power':int(pwr),
                'upper':int(pwr2)}
	    cpredictions.append(a)


    del form.fields["pieceunit"]
            
    messages.error(request,message)
    return render(request, 'otwrankings.html',
		  {'rankingworkouts':theworkouts,
		   'interactiveplot':script,
		   'the_div':div,
		   'cpredictions':cpredictions,
                   'avgpower':avgpower,
		   'form':form,
		   'dateform':dateform,
		   'deltaform':deltaform,
		   'id': theuser,
		   'theuser':uu,
		   'startdate':startdate,
		   'enddate':enddate,
                   'teams':get_my_teams(request.user),
		   })

# Reload the workout and calculate the summary from the stroke data (lapIDx)
@login_required()
def workout_recalcsummary_view(request,id=0):
    try:
        row = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

    if (checkworkoutuser(request.user,row)==False):
	message = "You are not allowed to edit this workout"
        messages.error(request,message)
	url = reverse(workouts_view)

	return HttpResponseRedirect(url)

    filename = row.csvfilename
    rowdata = rdata(filename)
    if rowdata:
        row.summary = rowdata.allstats()
        row.save()
        successmessage = "Summary Updated"
        messages.info(request,successmessage)
        url = reverse(workout_edit_view,
		  kwargs = {
		      'id':int(id),
		  })
    else:
        message = "Something went wrong. Could not update summary"
        messages.error(request,message)
        url = reverse(workout_edit_view,
                      kwargs = {
                          'id':int(id),
                          })
        
    return HttpResponseRedirect(url)

@login_required()
def workout_makepublic_view(request,id,
                            message='',
                            successmessage=''):
    try:    
        row = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
        raise Http404("Workout doesn't exist")
    
    if (checkworkoutuser(request.user,row)==False):
        message = "You are not allowed to edit this workout"
        messages.error(request,message)
        url = reverse(workouts_view)

        return HttpResponseRedirect(url)

    row.privacy = 'visible'
    row.save()
    rr = getrower(request.user)
    
    teams = rr.team.all()
    for team in teams:
        row.team.add(team)
        

    message = "Workout set to public. Your followers and team members will see it"
    messages.info(request,message)
    
    url = reverse(workout_edit_view,
		  kwargs = {
		      'id':int(id),
		  })
    return HttpResponseRedirect(url)

@login_required()
def workout_setprivate_view(request,id,
                            message='',
                            successmessage=''):
    try:    
        row = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
        raise Http404("Workout doesn't exist")
    
    if (checkworkoutuser(request.user,row)==False):
        message = "You are not allowed to edit this workout"
        messages.error(request,message)
        url = reverse(workouts_view)

        return HttpResponseRedirect(url)

    row.privacy = 'private'
    row.save()

    for team in row.team.all():
        row.team.remove(team)

    message = "Workout set to private. Only you will see it"
    messages.info(request,message)
    
    url = reverse(workout_edit_view,
		  kwargs = {
		      'id':int(id),
		  })
    return HttpResponseRedirect(url)

# Team comparison
@login_required()
def team_comparison_select(request,
                           startdatestring="",
                           enddatestring="",
                           message='',
                           successmessage='',
                           startdate=timezone.now()-datetime.timedelta(days=30),
                           enddate=timezone.now()+datetime.timedelta(days=1),
                           teamid=0):

    try:
	r = getrower(request.user)
    except Rower.DoesNotExist:
        raise Http404("Rower doesn't exist")

    if 'startdate' in request.session:
        startdate = iso8601.parse_date(request.session['startdate'])


    if 'enddate' in request.session:
        enddate = iso8601.parse_date(request.session['enddate'])


    if 'waterboattype' in request.session:
        waterboattype = request.session['waterboattype']
    else:
        waterboattype = ['1x','2x','2-','4x','4-','8+']

        
    if 'modalities' in request.session:
        modalities = request.session['modalities']
        if len(modalities) > 1:
            modality = 'all'
        else:
            modality = modalities[0]
    else:
        modalities = [m[0] for m in types.workouttypes]
        modality = 'all'
            
    if request.method == 'POST' and 'daterange' in request.POST:
        dateform = DateRangeForm(request.POST)
        if dateform.is_valid():
            startdate = dateform.cleaned_data['startdate']
            enddate = dateform.cleaned_data['enddate']
            startdatestring = startdate.strftime('%Y-%m-%d')
            enddatestring = enddate.strftime('%Y-%m-%d')
            request.session['startdate'] = startdatestring
            request.session['enddate'] = enddatestring
    else:
        dateform = DateRangeForm(initial={
            'startdate':startdate,
            'enddate':enddate,
            })

    
    if request.method == 'POST' and 'modality' in request.POST:
        modalityform = TrendFlexModalForm(request.POST)
        if modalityform.is_valid():
            modality = modalityform.cleaned_data['modality']
            waterboattype = modalityform.cleaned_data['waterboattype']
            if modality == 'all':
                modalities = [m[0] for m in types.workouttypes]
            else:
                modalities = [modality]

            if modality != 'water':
                waterboattype = [b[0] for b in types.boattypes]

                
            request.session['modalities'] = modalities
            request.session['waterboattype'] = waterboattype

    negtypes = []
    for b in types.boattypes:
        if b[0] not in waterboattype:
            negtypes.append(b[0])
            
    startdate = datetime.datetime.combine(startdate,datetime.time())
    enddate = datetime.datetime.combine(enddate,datetime.time(23,59,59))
    enddate = enddate+datetime.timedelta(days=1)

    if startdatestring:
        startdate = iso8601.parse_date(startdatestring)
    if enddatestring:
        enddate = iso8601.parse_date(enddatestring)

    if enddate < startdate:
        s = enddate
        enddate = startdate
        startdate = s

    try:
        theteam = Team.objects.get(id=teamid)
    except Team.DoesNotExist:
        theteam = 0
        
    if r.rowerplan == 'basic' and theteam==0:
        raise Http404("Not allowed")

    if theteam and (theteam.viewing == 'allmembers' or theteam.manager == request.user):
        workouts = Workout.objects.filter(team=theteam,
                                          startdatetime__gte=startdate,
                                          startdatetime__lte=enddate,
                                          workouttype__in=modalities).order_by("-date", "-starttime").exclude(boattype__in=negtypes)
    elif theteam and theteam.viewing == 'coachonly':
        workouts = Workout.objects.filter(team=theteam,user=r,
                                          startdatetime__gte=startdate,
                                          startdatetime__lte=enddate,
                                          workouttype__in=modalities).order_by("-date","-starttime").exclude(boattype__in=negtypes)

            
    else:
        theteam = None
        workouts = Workout.objects.filter(user=r,
                                      startdatetime__gte=startdate,
                                          startdatetime__lte=enddate,
                                          workouttype__in=modalities).order_by("-date", "-starttime").exclude(boattype__in=negtypes)

    query = request.GET.get('q')
    if query:
        query_list = query.split()
        workouts = workouts.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))
            )

    form = WorkoutMultipleCompareForm()
    form.fields["workouts"].queryset = workouts

    if theteam:
        theid = theteam.id
    else:
        theid = 0
        
    chartform = ChartParamChoiceForm(initial={'teamid':0})
    modalityform = TrendFlexModalForm(initial={
        'modality':modality,
        'waterboattype':waterboattype
    })


    messages.info(request,successmessage)
    messages.error(request,message)
    
    return render(request, 'team_compare_select.html',
                  {'workouts': workouts,
                   'dateform':dateform,
                   'startdate':startdate,
                   'enddate':enddate,
                   'team':theteam,
                   'form':form,
                   'chartform':chartform,
                   'modalityform':modalityform,
                   'teams':get_my_teams(request.user),
                   })


# Team comparison
@login_required()
def multi_compare_view(request):
    promember=0
    if not request.user.is_anonymous():
	r = getrower(request.user)
	result = request.user.is_authenticated() and ispromember(request.user)
	if result:
            promember=1

            
    if request.method == 'POST' and 'workouts' in request.POST:
        form = WorkoutMultipleCompareForm(request.POST)
        chartform = ChartParamChoiceForm(request.POST)
        if form.is_valid() and chartform.is_valid():
            cd = form.cleaned_data
            workouts = cd['workouts']
            xparam = chartform.cleaned_data['xparam']
            yparam = chartform.cleaned_data['yparam']
            plottype = chartform.cleaned_data['plottype']
            teamid = chartform.cleaned_data['teamid']
            ids = [int(w.id) for w in workouts]
            request.session['ids'] = ids

            labeldict = {
                int(w.id): w.__unicode__() for w in workouts
                }
            
            res = interactive_multiple_compare_chart(ids,xparam,yparam,
                                                     promember=promember,
                                                     plottype=plottype,
                                                     labeldict=labeldict)
            script = res[0]
            div = res[1]

            return render(request,'multicompare.html',
                          {'interactiveplot':script,
                           'the_div':div,
                           'promember':promember,
                           'teamid':teamid,
                           'chartform':chartform,
                           'teams':get_my_teams(request.user),
                           })
        else:
            return HttpResponse("Form is not valid")
    if request.method == 'POST' and 'ids' in request.session:
        chartform = ChartParamChoiceForm(request.POST)
        if chartform.is_valid():
            xparam = chartform.cleaned_data['xparam']
            yparam = chartform.cleaned_data['yparam']
            plottype = chartform.cleaned_data['plottype']
            teamid = chartform.cleaned_data['teamid']
            ids = request.session['ids']
            request.session['ids'] = ids
            workouts = [Workout.objects.get(id=id) for id in ids]

            labeldict = {
                int(w.id): w.__unicode__() for w in workouts
                }
            
            res = interactive_multiple_compare_chart(ids,xparam,yparam,
                                                     promember=promember,
                                                     plottype=plottype,
                                                     labeldict=labeldict)
            script = res[0]
            div = res[1]

            return render(request,'multicompare.html',
                          {'interactiveplot':script,
                           'the_div':div,
                           'promember':promember,
                           'teamid':teamid,
                           'chartform':chartform,
                           'teams':get_my_teams(request.user),
                           })
        
    else:
        url = reverse(workouts_view)
        return HttpResponseRedirect(url)

# Multi Flex Chart with Grouping
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def user_multiflex_select(request,
                        startdatestring="",
                        enddatestring="",
                        message='',
                        successmessage='',
                        startdate=timezone.now()-datetime.timedelta(days=30),
                        enddate=timezone.now()+datetime.timedelta(days=1),
                        userid=0):

    if userid == 0:
        user = request.user
    else:
        user = User.objects.get(id=userid)
        

    r = getrower(user)
    
    if 'options' in request.session:
        options = request.session['options']
    else:
        options = {}

    try:
        palette = request.session['palette']
    except KeyError:
        palette = 'monochrome_blue'
    
    try:
        includereststrokes = request.session['includereststrokes']
    except KeyError:
        includereststrokes = False

    try:
        ploterrorbars = request.session['ploterrorbars']
    except:
        ploterrorbars = False
        

        
    if 'startdate' in request.session:
        startdate = iso8601.parse_date(request.session['startdate'])


    if 'enddate' in request.session:
        enddate = iso8601.parse_date(request.session['enddate'])


    if 'waterboattype' in request.session:
        waterboattype = request.session['waterboattype']
    else:
        waterboattype = ['1x','2x','2-','4x','4-','8+']

        
    if 'modalities' in request.session:
        modalities = request.session['modalities']
        if len(modalities) > 1:
            modality = 'all'
        else:
            modality = modalities[0]
    else:
        modalities = [m[0] for m in types.workouttypes]
        modality = 'all'
            
    if request.method == 'POST' and 'daterange' in request.POST:
        dateform = DateRangeForm(request.POST)
        if dateform.is_valid():
            startdate = dateform.cleaned_data['startdate']
            enddate = dateform.cleaned_data['enddate']
            startdatestring = startdate.strftime('%Y-%m-%d')
            enddatestring = enddate.strftime('%Y-%m-%d')
            request.session['startdate'] = startdatestring
            request.session['enddate'] = enddatestring
    else:
        dateform = DateRangeForm(initial={
            'startdate':startdate,
            'enddate':enddate,
            })

    if request.method == 'POST' and 'modality' in request.POST:
        modalityform = TrendFlexModalForm(request.POST)
        if modalityform.is_valid():
            modality = modalityform.cleaned_data['modality']
            waterboattype = modalityform.cleaned_data['waterboattype']
            if modality == 'all':
                modalities = [m[0] for m in types.workouttypes]
            else:
                modalities = [modality]

            if modality != 'water':
                waterboattype = [b[0] for b in types.boattypes]

                
            request.session['modalities'] = modalities
            request.session['waterboattype'] = waterboattype

            
    startdate = datetime.datetime.combine(startdate,datetime.time())
    enddate = datetime.datetime.combine(enddate,datetime.time(23,59,59))
    enddate = enddate+datetime.timedelta(days=1)

    if startdatestring:
        startdate = iso8601.parse_date(startdatestring)
    if enddatestring:
        enddate = iso8601.parse_date(enddatestring)

    if enddate < startdate:
        s = enddate
        enddate = startdate
        startdate = s


    negtypes = []
    for b in types.boattypes:
        if b[0] not in waterboattype:
            negtypes.append(b[0])
            
    workouts = Workout.objects.filter(user=r,
                                      startdatetime__gte=startdate,
                                      startdatetime__lte=enddate,
                                      workouttype__in=modalities).order_by("-date", "-starttime").exclude(boattype__in=negtypes)

    query = request.GET.get('q')
    if query:
        query_list = query.split()
        workouts = workouts.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))
            )

    form = WorkoutMultipleCompareForm()
    form.fields["workouts"].queryset = workouts

    chartform = MultiFlexChoiceForm(initial={
        'palette':palette,
        'ploterrorbars':ploterrorbars,
        'includereststrokes':includereststrokes,
    })

    modalityform = TrendFlexModalForm(initial={
        'modality':modality,
        'waterboattype':waterboattype
    })

    messages.info(request,successmessage)
    messages.error(request,message)

    startdatestring = startdate.strftime('%Y-%m-%d')
    enddatestring = enddate.strftime('%Y-%m-%d')
    request.session['startdate'] = startdatestring
    request.session['enddate'] = enddatestring

    return render(request, 'user_multiflex_select.html',
                  {'workouts': workouts,
                   'dateform':dateform,
                   'startdate':startdate,
                   'enddate':enddate,
                   'theuser':user,
                   'form':form,
                   'chartform':chartform,
                   'modalityform':modalityform,
                   'teams':get_my_teams(request.user),
                   })

@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def multiflex_view(request,userid=0,
                 options={
                     'includereststrokes':False,
                     'ploterrorbars':False,
                     }):

    if 'options' in request.session:
        options = request.session['options']

    try:
        includereststrokes = options['includereststrokes']
    except KeyError:
        includereststrokes = False

    try:
        ploterrorbars = options['ploterrorbars']
    except KeyError:
        ploterrorbars = False

    try:
        palette = request.session['palette']
    except KeyError:
        palette = 'monochrome_blue'
        
    workstrokesonly = not includereststrokes

    if userid==0:
        userid = request.user.id
    
    if request.method == 'POST' and 'workouts' in request.POST:
        form = WorkoutMultipleCompareForm(request.POST)
        chartform = MultiFlexChoiceForm(request.POST)
        if form.is_valid() and chartform.is_valid():
            cd = form.cleaned_data
            workouts = cd['workouts']
            xparam = chartform.cleaned_data['xparam']
            yparam = chartform.cleaned_data['yparam']
            includereststrokes = chartform.cleaned_data['includereststrokes']
            ploterrorbars = chartform.cleaned_data['ploterrorbars']
            request.session['ploterrorbars'] = ploterrorbars
            request.session['includereststrokes'] = includereststrokes
            workstrokesonly = not includereststrokes
            palette = chartform.cleaned_data['palette']
            request.session['palette'] = palette
            
            groupby = chartform.cleaned_data['groupby']
            binsize = chartform.cleaned_data['binsize']
            if binsize <= 0:
                binsize = 1
            if groupby == 'pace':
                binsize *= 1000
            
            spmmin = chartform.cleaned_data['spmmin']
            spmmax = chartform.cleaned_data['spmmax']
            workmin = chartform.cleaned_data['workmin']
            workmax = chartform.cleaned_data['workmax']

            ids = [int(w.id) for w in workouts]
            request.session['ids'] = ids

        else:
            return HttpResponse("Form is not valid")
    elif request.method == 'POST' and 'ids' in request.session:
        chartform = MultiFlexChoiceForm(request.POST)
        if chartform.is_valid():
            xparam = chartform.cleaned_data['xparam']
            yparam = chartform.cleaned_data['yparam']
            includereststrokes = chartform.cleaned_data['includereststrokes']
            ploterrorbars = chartform.cleaned_data['ploterrorbars']
            request.session['ploterrorbars'] = ploterrorbars
            request.session['includereststrokes'] = includereststrokes
            workstrokesonly = not includereststrokes
            palette = chartform.cleaned_data['palette']
            request.session['palette'] = palette

            groupby = chartform.cleaned_data['groupby']
            binsize = chartform.cleaned_data['binsize']
            if binsize <= 0:
                binsize = 1
            if groupby == 'pace':
                binsize *= 1000.
            
            spmmin = chartform.cleaned_data['spmmin']
            spmmax = chartform.cleaned_data['spmmax']
            workmin = chartform.cleaned_data['workmin']
            workmax = chartform.cleaned_data['workmax']

            ids = request.session['ids']
            request.session['ids'] = ids
            workouts = dataprep.get_workouts(ids,userid)
            if not workouts:
                message = 'Error: Workouts in session storage do not belong to this user.'
                messages.error(request,message)
                url = reverse(user_multiflex_select,
                              kwargs={
                                  'userid':userid,
                                  }
                              )
                return HttpResponseRedirect(url)
                              
            # workouts = [Workout.objects.get(id=id) for id in ids]

            labeldict = {
                int(w.id): w.__unicode__() for w in workouts
                }

        else:
            return HttpResponse("invalid form")
    else:
        url = reverse(user_multiflex_select)
        return HttpResponseRedirect(url)

    fieldlist,fielddict = dataprep.getstatsfields()
    fieldlist = [xparam,yparam,groupby,
                 'workoutid','spm','driveenergy',
                 'workoutstate']
    
    # prepare data frame
    datadf = dataprep.read_cols_df_sql(ids,fieldlist)


    datadf = dataprep.clean_df_stats(datadf,workstrokesonly=workstrokesonly)


    datadf = dataprep.filter_df(datadf,'spm',spmmin,
                                largerthan=True)
    datadf = dataprep.filter_df(datadf,'spm',spmmax,
                                largerthan=False)

    datadf = dataprep.filter_df(datadf,'driveenergy',workmin,
                                largerthan=True)
    datadf = dataprep.filter_df(datadf,'driveneergy',workmax,
                                largerthan=False)


    datadf.dropna(axis=0,how='any',inplace=True)


    datemapping = {
        w.id:w.date for w in workouts
    }

    datadf['date'] = datadf['workoutid']
    datadf['date'].replace(datemapping,inplace=True)

    today = datetime.date.today()
    datadf['days ago'] = map(lambda x : x.days, datadf.date - today)

    if groupby != 'date':
        bins = np.arange(datadf[groupby].min()-binsize,
                         datadf[groupby].max()+binsize,
                         binsize)
        groups = datadf.groupby(pd.cut(datadf[groupby],bins,labels=False))
    else:
        bins = np.arange(datadf['days ago'].min()-binsize,
                         datadf['days ago'].max()+binsize,
                         binsize,
        )
        groups = datadf.groupby(pd.cut(datadf['days ago'], bins,
                                           labels=False))
            

    xvalues = groups.mean()[xparam]
    yvalues = groups.mean()[yparam]
    xerror = groups.std()[xparam]
    yerror = groups.std()[yparam]
    groupsize = groups.count()[xparam]

    mask = groupsize <= min([0.01*groupsize.sum(),0.2*groupsize.mean()])
    xvalues.loc[mask] = np.nan
    yvalues.loc[mask] = np.nan
    xerror.loc[mask] = np.nan
    yerror.loc[mask] = np.nan
    groupsize.loc[mask] = np.nan

    xvalues.dropna(inplace=True)
    yvalues.dropna(inplace=True)
    xerror.dropna(inplace=True)
    yerror.dropna(inplace=True)
    groupsize.dropna(inplace=True)

    
    if len(groupsize) == 0:
        messages.error(request,'No data in selection')
        url = reverse(user_multiflex_select)
        return HttpResponseRedirect(url)
    else:
        groupsize = 30.*np.sqrt(groupsize/float(groupsize.max()))
    
    df = pd.DataFrame({
        xparam:xvalues,
        yparam:yvalues,
        'x':xvalues,
        'y':yvalues,
        'xerror':xerror,
        'yerror':yerror,
        'groupsize':groupsize,
    })

    if yparam == 'pace':
        df['y'] = dataprep.paceformatsecs(df['y']/1.0e3)
    
    aantal = len(df)
    
    if groupby != 'date':
        try:
            df['groupval'] = groups.mean()[groupby]
            df['groupval'].loc[mask] = np.nan
                    
            groupcols = df['groupval']
        except ValueError:
            df['groupval'] =  groups.mean()[groupby].fillna(value=0)
            df['groupval'].loc[mask] = np.nan
            groupcols = df['groupval']
        except KeyError:
            messages.error(request,'Data selection error')
            url = reverse(user_multiflex_select)
            return HttpResponseRedirect(url)            
    else:
        try:
            dates = groups.min()[groupby]
            dates.loc[mask] = np.nan
            dates.dropna(inplace=True)
            df['groupval'] = [x.strftime("%Y-%m-%d") for x in dates]
            df['groupval'].loc[mask] = np.nan
            groupcols = 100.*np.arange(aantal)/float(aantal)
        except AttributeError:
            df['groupval'] = groups.mean()['days ago'].fillna(value=0)
            groupcols = 100.*np.arange(aantal)/float(aantal)
                    

    groupcols = (groupcols-groupcols.min())/(groupcols.max()-groupcols.min())
    if aantal == 1:
        groupcols = np.array([1.])
        

    colors = range_to_color_hex(groupcols,palette=palette)
    
    df['color'] = colors

    clegendx = np.arange(0,1.2,.2)
    legcolors = range_to_color_hex(clegendx,palette=palette)
    if groupby != 'date':
        clegendy = df['groupval'].min()+clegendx*(df['groupval'].max()-df['groupval'].min())
    else:
        clegendy = df.index.min()+clegendx*(df.index.max()-df.index.min())


    
    colorlegend =  zip(range(6),clegendy,legcolors)


    if userid == 0:
        extratitle = ''
    else:
        u = User.objects.get(id=userid)
        extratitle = ' '+u.first_name+' '+u.last_name
                

            
    script,div = interactive_multiflex(df,xparam,yparam,
                                       groupby,
                                       extratitle=extratitle,
                                       ploterrorbars=ploterrorbars,
                                       binsize=binsize,
                                       colorlegend=colorlegend)
                
            

    return render(request,'multiflex.html',
                  {'interactiveplot':script,
                   'the_div':div,
                   'chartform':chartform,
                   'userid':userid,
                   'teams':get_my_teams(request.user),
                  })


# Box plots
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def user_boxplot_select(request,
                        startdatestring="",
                        enddatestring="",
                        message='',
                        successmessage='',
                        startdate=timezone.now()-datetime.timedelta(days=30),
                        enddate=timezone.now()+datetime.timedelta(days=1),
                        userid=0):

    if userid == 0:
        user = request.user
    else:
        user = User.objects.get(id=userid)
        

    r = getrower(user)
    
    if 'startdate' in request.session:
        startdate = iso8601.parse_date(request.session['startdate'])


    if 'enddate' in request.session:
        enddate = iso8601.parse_date(request.session['enddate'])


    if 'waterboattype' in request.session:
        waterboattype = request.session['waterboattype']
    else:
        waterboattype = ['1x','2x','2-','4x','4-','8+']

        
    if 'modalities' in request.session:
        modalities = request.session['modalities']
        if len(modalities) > 1:
            modality = 'all'
        else:
            modality = modalities[0]
    else:
        modalities = [m[0] for m in types.workouttypes]
        modality = 'all'

    if request.method == 'POST' and 'daterange' in request.POST:
        dateform = DateRangeForm(request.POST)
        if dateform.is_valid():
            startdate = dateform.cleaned_data['startdate']
            enddate = dateform.cleaned_data['enddate']
            startdatestring = startdate.strftime('%Y-%m-%d')
            enddatestring = enddate.strftime('%Y-%m-%d')
            request.session['startdate'] = startdatestring
            request.session['enddate'] = enddatestring
    else:
        dateform = DateRangeForm(initial={
            'startdate':startdate,
            'enddate':enddate,
            })

    if request.method == 'POST' and 'modality' in request.POST:
        modalityform = TrendFlexModalForm(request.POST)
        if modalityform.is_valid():
            modality = modalityform.cleaned_data['modality']
            waterboattype = modalityform.cleaned_data['waterboattype']
            if modality == 'all':
                modalities = [m[0] for m in types.workouttypes]
            else:
                modalities = [modality]

            if modality != 'water':
                waterboattype = [b[0] for b in types.boattypes]

                
            request.session['modalities'] = modalities
            request.session['waterboattype'] = waterboattype

    startdate = datetime.datetime.combine(startdate,datetime.time())
    enddate = datetime.datetime.combine(enddate,datetime.time(23,59,59))
    enddate = enddate+datetime.timedelta(days=1)

    if startdatestring:
        startdate = iso8601.parse_date(startdatestring)
    if enddatestring:
        enddate = iso8601.parse_date(enddatestring)

    if enddate < startdate:
        s = enddate
        enddate = startdate
        startdate = s

    negtypes = []
    for b in types.boattypes:
        if b[0] not in waterboattype:
            negtypes.append(b[0])

    workouts = Workout.objects.filter(user=r,
                                      startdatetime__gte=startdate,
                                      startdatetime__lte=enddate,
                                      workouttype__in=modalities).order_by("-date", "-starttime").exclude(boattype__in=negtypes)

    query = request.GET.get('q')
    if query:
        query_list = query.split()
        workouts = workouts.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))
            )

    form = WorkoutMultipleCompareForm()
    form.fields["workouts"].queryset = workouts

    chartform = BoxPlotChoiceForm()
    modalityform = TrendFlexModalForm(initial={
        'modality':modality,
        'waterboattype':waterboattype
    })

    messages.info(request,successmessage)
    messages.error(request,message)

    startdatestring = startdate.strftime('%Y-%m-%d')
    enddatestring = enddate.strftime('%Y-%m-%d')
    request.session['startdate'] = startdatestring
    request.session['enddate'] = enddatestring

    return render(request, 'user_boxplot_select.html',
                  {'workouts': workouts,
                   'dateform':dateform,
                   'startdate':startdate,
                   'enddate':enddate,
                   'theuser':user,
                   'form':form,
                   'chartform':chartform,
                   'modalityform':modalityform,
                   'teams':get_my_teams(request.user),
                   })

@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def boxplot_view(request,userid=0,
                 options={
                     'includereststrokes':False,
                     }):

    if 'options' in request.session:
        options = request.session['options']
        
    includereststrokes = options['includereststrokes']
    workstrokesonly = not includereststrokes

    if userid==0:
        userid = request.user.id
    
    if request.method == 'POST' and 'workouts' in request.POST:
        form = WorkoutMultipleCompareForm(request.POST)
        chartform = BoxPlotChoiceForm(request.POST)
        if form.is_valid() and chartform.is_valid():
            cd = form.cleaned_data
            workouts = cd['workouts']
            plotfield = chartform.cleaned_data['yparam']
            includereststrokes = chartform.cleaned_data['includereststrokes']
            request.session['includereststrokes'] = includereststrokes
            workstrokesonly = not includereststrokes

            spmmin = chartform.cleaned_data['spmmin']
            spmmax = chartform.cleaned_data['spmmax']
            workmin = chartform.cleaned_data['workmin']
            workmax = chartform.cleaned_data['workmax']

            ids = [int(w.id) for w in workouts]
            request.session['ids'] = ids

            labeldict = {
                int(w.id): w.__unicode__() for w in workouts
                }
            
            
            datemapping = {
                w.id:w.date for w in workouts
            }

    
    
            fieldlist,fielddict = dataprep.getstatsfields()
            fieldlist = [plotfield,'workoutid','spm','driveenergy',
                         'workoutstate']
    
            # prepare data frame
            datadf = dataprep.read_cols_df_sql(ids,fieldlist)
            
            datadf = dataprep.clean_df_stats(datadf,workstrokesonly=workstrokesonly)

            datadf = dataprep.filter_df(datadf,'spm',spmmin,
                                        largerthan=True)
            datadf = dataprep.filter_df(datadf,'spm',spmmax,
                                        largerthan=False)
            datadf = dataprep.filter_df(datadf,'driveenergy',workmin,
                                        largerthan=True)
            datadf = dataprep.filter_df(datadf,'driveneergy',workmax,
                                        largerthan=False)

            datadf.dropna(axis=0,how='any',inplace=True)

            datadf['workoutid'].replace(datemapping,inplace=True)
            datadf.rename(columns={"workoutid":"date"},inplace=True)
            datadf = datadf.sort_values(['date'])

            if userid == 0:
                extratitle = ''
            else:
                u = User.objects.get(id=userid)
                extratitle = ' '+u.first_name+' '+u.last_name
                

            
            script,div = interactive_boxchart(datadf,plotfield,
                                              extratitle=extratitle)
            

            return render(request,'boxplot.html',
                          {'interactiveplot':script,
                           'the_div':div,
                           'chartform':chartform,
                           'userid':userid,
                           'teams':get_my_teams(request.user),
                           })
        else:
            return HttpResponse("Form is not valid")
    elif request.method == 'POST' and 'ids' in request.session:
        chartform = BoxPlotChoiceForm(request.POST)
        if chartform.is_valid():
            plotfield = chartform.cleaned_data['yparam']
            includereststrokes = chartform.cleaned_data['includereststrokes']
            spmmin = chartform.cleaned_data['spmmin']
            spmmax = chartform.cleaned_data['spmmax']
            workmin = chartform.cleaned_data['workmin']
            workmax = chartform.cleaned_data['workmax']
            request.session['includereststrokes'] = includereststrokes
            workstrokesonly = not includereststrokes
            ids = request.session['ids']
            request.session['ids'] = ids
            workouts = dataprep.get_workouts(ids,userid)
            if not workouts:
                message = 'Error: Workouts in session storage do not belong to this user.'
                messages.error(request,message)
                url = reverse(user_boxplot_select,
                              kwargs={
                                  'userid':userid,
                                  }
                              )
                return HttpResponseRedirect(url)
                              
            # workouts = [Workout.objects.get(id=id) for id in ids]

            labeldict = {
                int(w.id): w.__unicode__() for w in workouts
                }
            
            datemapping = {
                w.id:w.date for w in workouts
            }

            fieldlist,fielddict = dataprep.getstatsfields()
            fieldlist = [plotfield,'workoutid','spm','driveenergy',
                         'workoutstate']
    
            # prepare data frame
            datadf = dataprep.read_cols_df_sql(ids,fieldlist)

            # dummy values for drive energy
            mask = datadf['driveenergy'] == 0
            datadf.loc[mask,'driveenergy'] = 450
            
            datadf = dataprep.clean_df_stats(datadf,
                                             workstrokesonly=workstrokesonly)


            datadf = dataprep.filter_df(datadf,'spm',spmmin,
                                        largerthan=True)
            datadf = dataprep.filter_df(datadf,'spm',spmmax,
                                        largerthan=False)
            datadf = dataprep.filter_df(datadf,'driveenergy',workmin,
                                        largerthan=True)
            datadf = dataprep.filter_df(datadf,'driveneergy',workmax,
                                        largerthan=False)

            datadf.dropna(axis=0,how='any',inplace=True)
            
            datadf['workoutid'].replace(datemapping,inplace=True)
            datadf.rename(columns={"workoutid":"date"},inplace=True)
            datadf = datadf.sort_values(['date'])

            if userid == 0:
                extratitle = ''
            else:
                u = User.objects.get(id=userid)
                extratitle = ' '+u.first_name+' '+u.last_name
                
            script,div = interactive_boxchart(datadf,plotfield,
                                              extratitle=extratitle)


            return render(request,'boxplot.html',
                          {'interactiveplot':script,
                           'the_div':div,
                           'chartform':chartform,
                           'userid':userid,
                           'teams':get_my_teams(request.user),
                           })
        else:
            return HttpResponse("invalid form")
    else:
        url = reverse(user_boxplot_select)
        return HttpResponseRedirect(url)

# List Workouts    
@login_required()
def workouts_view(request,message='',successmessage='',
                  startdatestring="",enddatestring="",
                  startdate=timezone.now()-datetime.timedelta(days=365),
                  enddate=timezone.now()+datetime.timedelta(days=1),
                  teamid=0):
    request.session['referer'] = absolute(request)['PATH']
    try:
	r = getrower(request.user)
    except Rower.DoesNotExist:
        raise Http404("Rower doesn't exist")

    if request.method == 'POST':
        dateform = DateRangeForm(request.POST)
        if dateform.is_valid():
            startdate = dateform.cleaned_data['startdate']
            enddate = dateform.cleaned_data['enddate']
    else:
        dateform = DateRangeForm(initial={
            'startdate':startdate,
            'enddate':enddate,
            })

    startdate = datetime.datetime.combine(startdate,datetime.time())
    enddate = datetime.datetime.combine(enddate,datetime.time(23,59,59))
    enddate = enddate+datetime.timedelta(days=1)

    if startdatestring:
        startdate = iso8601.parse_date(startdatestring)
    if enddatestring:
        enddate = iso8601.parse_date(enddatestring)

    if enddate < startdate:
        s = enddate
        enddate = startdate
        startdate = s

    # start date for the small graph
    activity_startdate = enddate-datetime.timedelta(days=15)

    try:
        if utc.localize(enddate) > timezone.now():
            activity_enddate = timezone.now()
            activity_startdate = activity_enddate-datetime.timedelta(days=15)
        else:
            activity_enddate = enddate
    except ValueError:
        activity_enddate = enddate

        
    if teamid:
        try:
            theteam = Team.objects.get(id=teamid)
        except Team.DoesNotExist:
            raise Http404("Team doesn't exist")

        if theteam.viewing == 'allmembers' or theteam.manager == request.user:
            workouts = Workout.objects.filter(team=theteam,
                                          startdatetime__gte=startdate,
                                          startdatetime__lte=enddate).order_by("-date", "-starttime")
            g_workouts = Workout.objects.filter(team=theteam,
                                                startdatetime__gte=activity_startdate,
                                                startdatetime__lte=activity_enddate).order_by("-date", "-starttime")
        elif theteam.viewing == 'coachonly':
            workouts = Workout.objects.filter(team=theteam,user=r,
                                              startdatetime__gte=startdate,
                                              startdatetime__lte=enddate).order_by("-date","-starttime")
            g_workouts = Workout.objects.filter(team=theteam,user=r,
                                                startdatetime__gte=activity_startdate,
                                                enddatetime__lte=activity_enddate).order_by("-date","-starttime")


    else:
        theteam = None
        workouts = Workout.objects.filter(user=r,
                                      startdatetime__gte=startdate,
                                      startdatetime__lte=enddate).order_by("-date", "-starttime")
        g_workouts = Workout.objects.filter(user=r,
                                            startdatetime__gte=activity_startdate,
                                            startdatetime__lte=activity_enddate).order_by("-date","-starttime")

    query = request.GET.get('q')
    if query:
        query_list = query.split()
        workouts = workouts.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))
            )

    paginator = Paginator(workouts,20) # show 25 workouts per page
    page = request.GET.get('page')

    try:
        workouts = paginator.page(page)
    except PageNotAnInteger:
        workouts = paginator.page(1)
    except EmptyPage:
        workouts = paginator.page(paginator.num_pages)

    today = timezone.now()
    announcements = SiteAnnouncement.objects.filter(
        expires__gte=today
    ).order_by(
        "-created",
        "-id"
    )

    script,div = interactive_activitychart(g_workouts,
                                           activity_startdate,
                                           activity_enddate)
    
    messages.info(request,successmessage)
    messages.error(request,message)
    
    return render(request, 'list_workouts.html',
                  {'workouts': workouts,
                   'dateform':dateform,
                   'startdate':startdate,
                   'enddate':enddate,
                   'announcements':announcements[0:4],
                   'team':theteam,
                   'teams':get_my_teams(request.user),
                   'interactiveplot':script,
                   'the_div':div,
                   })


# List of workouts to compare a selected workout to
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def workout_comparison_list(request,id=0,message='',successmessage='',
                            startdatestring="",enddatestring="",
                            startdate=timezone.now()-datetime.timedelta(days=365),
                            enddate=timezone.now()):

    try:
	r = getrower(request.user)
	u = User.objects.get(id=r.user.id)
        if request.method == 'POST':
            dateform = DateRangeForm(request.POST)
            if dateform.is_valid():
	        startdate = dateform.cleaned_data['startdate']
	        enddate = dateform.cleaned_data['enddate']
        else:
            dateform = DateRangeForm(initial={
                'startdate':startdate,
                'enddate':enddate,
                })

        if startdatestring:
            startdate = iso8601.parse_date(startdatestring)
        if enddatestring:
            enddate = iso8601.parse_date(enddatestring)

        startdate = datetime.datetime.combine(startdate,datetime.time())
        enddate = datetime.datetime.combine(enddate,datetime.time(23,59,59))
        enddate = enddate+datetime.timedelta(days=1)
                
        if enddate < startdate:
	    s = enddate
	    enddate = startdate
	    startdate = s
        
	workouts = Workout.objects.filter(user=r,
                                          startdatetime__gte=startdate,
                                          startdatetime__lte=enddate).order_by("-date", "-starttime").exclude(id=id)

        query = request.GET.get('q')
        if query:
            query_list = query.split()
            workouts = workouts.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))
                )

        paginator = Paginator(workouts,15) # show 25 workouts per page
        page = request.GET.get('page')

        try:
            workouts = paginator.page(page)
        except PageNotAnInteger:
            workouts = paginator.page(1)
        except EmptyPage:
            workouts = paginator.page(paginator.num_pages)
        try:
	    row = Workout.objects.get(id=id)
        except Workout.DoesNotExist:
	    raise Http404("Workout doesn't exist")

        messages.error(request,message)
        messages.info(request,successmessage)
	
	return render(request, 'comparison_list.html',
		      {'id':int(id),
		       'workout':row,
		       'workouts': workouts,
		       'last_name':u.last_name,
		       'first_name':u.first_name,
                       'dateform':dateform,
                       'startdate':startdate,
                       'enddate':enddate,
	               'teams':get_my_teams(request.user),
	       })
    except Rower.DoesNotExist:
	raise Http404("User has no rower instance")

# List of workouts to compare a selected workout to
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def workout_fusion_list(request,id=0,message='',successmessage='',
                            startdatestring="",enddatestring="",
                            startdate=timezone.now()-datetime.timedelta(days=365),
                            enddate=timezone.now()):

    try:
	r = getrower(request.user)
	u = User.objects.get(id=r.user.id)
        if request.method == 'POST':
            dateform = DateRangeForm(request.POST)
            if dateform.is_valid():
	        startdate = dateform.cleaned_data['startdate']
	        enddate = dateform.cleaned_data['enddate']
        else:
            dateform = DateRangeForm(initial={
                'startdate':startdate,
                'enddate':enddate,
                })

        if startdatestring:
            startdate = iso8601.parse_date(startdatestring)
        if enddatestring:
            enddate = iso8601.parse_date(enddatestring)

        startdate = datetime.datetime.combine(startdate,datetime.time())
        enddate = datetime.datetime.combine(enddate,datetime.time(23,59,59))
        enddate = enddate+datetime.timedelta(days=1)
                
        if enddate < startdate:
	    s = enddate
	    enddate = startdate
	    startdate = s
        
	workouts = Workout.objects.filter(user=r,
                                          startdatetime__gte=startdate,
                                          startdatetime__lte=enddate).order_by("-date", "-starttime").exclude(id=id)

        query = request.GET.get('q')
        if query:
            query_list = query.split()
            workouts = workouts.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))
                )

        paginator = Paginator(workouts,15) # show 25 workouts per page
        page = request.GET.get('page')

        try:
            workouts = paginator.page(page)
        except PageNotAnInteger:
            workouts = paginator.page(1)
        except EmptyPage:
            workouts = paginator.page(paginator.num_pages)
        try:
	    row = Workout.objects.get(id=id)
        except Workout.DoesNotExist:
	    raise Http404("Workout doesn't exist")


	messages.info(request,successmessage)
        messages.error(request,message)
        
	return render(request, 'fusion_list.html',
		      {'id':int(id),
		       'workout':row,
		       'workouts': workouts,
		       'last_name':u.last_name,
		       'first_name':u.first_name,
                       'dateform':dateform,
                       'startdate':startdate,
                       'enddate':enddate,
	               'teams':get_my_teams(request.user),
	       })
    except Rower.DoesNotExist:
	raise Http404("User has no rower instance")

# Basic 'EDIT' view of workout
def workout_view(request,id=0):
    request.session['referer'] = absolute(request)['PATH']

    try:
	# check if valid ID exists (workout exists)
	row = Workout.objects.get(id=id)
        comments = WorkoutComment.objects.filter(workout=row)

        aantalcomments = len(comments)


        if row.privacy == 'private':
            raise Http404("Not allowed to view this workout")
        
	g = GraphImage.objects.filter(workout=row).order_by("-creationdatetime")
	r = Rower.objects.get(id=row.user.id)
	u = User.objects.get(id=r.user.id)

	
	# create interactive plot
	res = interactive_chart(id)
	script = res[0]
	div = res[1]
	
		
	# render page
	if (len(g)<=3):
	    return render(request, 'workout_view.html',
			  {'workout':row,
			   'graphs1':g[0:3],
			   'last_name':u.last_name,
			   'first_name':u.first_name,
			   'interactiveplot':script,
                           'aantalcomments':aantalcomments,
		           'teams':get_my_teams(request.user),
	                   'the_div':div})
	else:
	    return render(request, 'workout_view.html',
			  {'workout':row,
			   'graphs1':g[0:3],
			   'graphs2':g[3:6],
			   'last_name':u.last_name,
			   'first_name':u.first_name,
                           'teams':get_my_teams(request.user),
                           'aantalcomments':aantalcomments,
			   'interactiveplot':script,
			   'the_div':div})


    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

# Resets stroke data to raw data (pace)
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def workout_undo_smoothenpace_view(request,id=0,message="",successmessage=""):
    try:
        row = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

    if (checkworkoutuser(request.user,row)==False):
	message = "You are not allowed to edit this workout"
        messages.error(request,message)
	url = reverse(workouts_view)

	return HttpResponseRedirect(url)

    filename = row.csvfilename
    row = rdata(filename)
    if row == 0:
	return HttpResponse("Error: CSV Data File Not Found")

    if 'originalvelo' in row.df:
	velo = row.df['originalvelo'].values
	row.df[' Stroke500mPace (sec/500m)'] = 500./velo

    row.write_csv(filename,gzip=True)
    dataprep.update_strokedata(id,row.df)

    url = "/rowers/workout/"+str(id)+"/advanced"

    return HttpResponseRedirect(url)

	
# Data smoothing of pace data
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def workout_smoothenpace_view(request,id=0,message="",successmessage=""):
    try:
        row = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

    if (checkworkoutuser(request.user,row)==False):
	message = "You are not allowed to edit this workout"
        messages.error(request,message)
	url = reverse(workouts_view)

	return HttpResponseRedirect(url)

    filename = row.csvfilename
    row = rdata(filename)
    if row == 0:
	return HttpResponse("Error: CSV Data File Not Found")

    pace = row.df[' Stroke500mPace (sec/500m)'].values
    velo = 500./pace

    if not 'originalvelo' in row.df:
	row.df['originalvelo'] = velo

    velo2 = stravastuff.ewmovingaverage(velo,5)

    pace2 = 500./abs(velo2)

    row.df[' Stroke500mPace (sec/500m)'] = pace2

    row.df = row.df.fillna(0)

    row.write_csv(filename,gzip=True)
    dataprep.update_strokedata(id,row.df)

    url = "/rowers/workout/"+str(id)+"/advanced"

    return HttpResponseRedirect(url)

# Process CrewNerd Summary CSV and update summary
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def workout_crewnerd_summary_view(request,id=0,message="",successmessage=""):
    try:
        row = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

    if request.method == 'POST':
	form = CNsummaryForm(request.POST,request.FILES)
	if form.is_valid():
	    f = request.FILES['file']
	    res = handle_uploaded_file(f)
	    fname = res[1]
	    try:
		sumd = summarydata(fname)
		row.summary = sumd.allstats()
		row.save()
		os.remove(fname)
		successmessage = "CrewNerd summary added"
                messages.info(request,successmessage)
		url = reverse(workout_edit_view,
			      kwargs = {
				  'id':int(id),
				  })

		return HttpResponseRedirect(url)
	    except:
                try:
		    os.remove(fname)
                except:
                    pass
                message = "Something went wrong (workout_crewnerd_summary_view)"
                messages.error(request,message)
		url = reverse(workout_edit_view,
			      kwargs = {
				  'id':int(id),
				  })
		return HttpResponseRedirect(url)
	else:
	    return render(request,
			  "cn_form.html",
			  {'form':form,
                           'teams':get_my_teams(request.user),
			   'id':row.id})
    else:
	form = CNsummaryForm()
	
	return render(request,
		      "cn_form.html",
		      {'form':form,
                       'teams':get_my_teams(request.user),
		       'id':row.id})
    
# Get weather for given location and date/time
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def workout_downloadwind_view(request,id=0,
                              airportcode=None,
                              message="",successmessage=""):
    try:
        row = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

    f1 = row.csvfilename
    if (checkworkoutuser(request.user,row)==False):
	message = "You are not allowed to edit this workout"
        messages.error(request,message)
	url = reverse(workouts_view)

	return HttpResponseRedirect(url)

    # create bearing
    rowdata = rdata(f1)
    if rowdata == 0:
	return HttpResponse("Error: CSV Data File Not Found")

    try:
	bearing = rowdata.df.ix[:,'bearing'].values
    except KeyError:
	rowdata.add_bearing()
	rowdata.write_csv(f1,gzip=True)

    # get wind
    try:
	avglat = rowdata.df[' latitude'].mean()
	avglon = rowdata.df[' longitude'].mean()
	avgtime = int(rowdata.df['TimeStamp (sec)'].mean()-rowdata.df.ix[0,'TimeStamp (sec)'])
	startdatetime = dateutil.parser.parse("{}, {}".format(row.date,
							      row.starttime))
	
	starttimeunix = int(mktime(startdatetime.utctimetuple()))
	avgtime = starttimeunix+avgtime
	winddata = get_wind_data(avglat,avglon,avgtime)
	windspeed = winddata[0]
	windbearing = winddata[1]
	message = winddata[2]
	row.notes += "\n"+message
	row.save()
	rowdata.add_wind(windspeed,windbearing)
	rowdata.write_csv(f1,gzip=True)

        messages.info(request,message)
        
	kwargs = {
	    'id':int(id)}

	url = reverse(workout_wind_view,kwargs=kwargs)
	response = HttpResponseRedirect(url)
    except KeyError:
	message = "No latitude/longitude data"
        messages.error(request,message)
	kwargs = {
	    'id':int(id)
        }
	url = reverse(workout_wind_view,kwargs=kwargs)
	response = HttpResponseRedirect(url)



    return response

# Get weather for given location and date/time
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def workout_downloadmetar_view(request,id=0,
                              airportcode=None,
                              message="",successmessage=""):
    try:
        row = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

    f1 = row.csvfilename
    if (checkworkoutuser(request.user,row)==False):
	message = "You are not allowed to edit this workout"
        messages.error(request,message)
	url = reverse(workouts_view)

	return HttpResponseRedirect(url)

    # create bearing
    rowdata = rdata(f1)
    if rowdata == 0:
	return HttpResponse("Error: CSV Data File Not Found")

    try:
	bearing = rowdata.df.ix[:,'bearing'].values
    except KeyError:
	rowdata.add_bearing()
	rowdata.write_csv(f1,gzip=True)

    # get wind
    try:
	avglat = rowdata.df[' latitude'].mean()
	avglon = rowdata.df[' longitude'].mean()
        airportcode = get_airport_code(avglat,avglon)[0]
	avgtime = int(rowdata.df['TimeStamp (sec)'].mean()-rowdata.df.ix[0,'TimeStamp (sec)'])
	startdatetime = dateutil.parser.parse("{}, {}".format(row.date,
							      row.starttime))
	
	starttimeunix = int(mktime(startdatetime.utctimetuple()))
	avgtime = starttimeunix+avgtime
	winddata = get_metar_data(airportcode,avgtime)
	windspeed = winddata[0]
	windbearing = winddata[1]
	message = winddata[2]
	row.notes += "\n"+message
	row.save()
	rowdata.add_wind(windspeed,windbearing)
	rowdata.write_csv(f1,gzip=True)
        messages.info(request,message)
        
	kwargs = {
		  'id':int(id)}

	url = reverse(workout_wind_view,kwargs=kwargs)
	response = HttpResponseRedirect(url)
    except KeyError:
	message = "No latitude/longitude data"
        messages.error(request,message)
	kwargs = {
	    'id':int(id)
        }
	url = reverse(workout_wind_view,kwargs=kwargs)
	response = HttpResponseRedirect(url)



    return response


# Show form to update wind data
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def workout_wind_view(request,id=0,message="",successmessage=""):
    try:
        row = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

    if (checkworkoutuser(request.user,row)==False):
	message = "You are not allowed to edit this workout"
        messages.error(request,message)
	url = reverse(workouts_view)

	return HttpResponseRedirect(url)


    # get data
    f1 = row.csvfilename
    u = row.user.user
    r = getrower(u)

    # create bearing
    rowdata = rdata(f1)
    if row == 0:
	return HttpResponse("Error: CSV Data File Not Found")


    hascoordinates = 1
    try:
	latitude = rowdata.df.ix[:,' latitude']
    except KeyError:
	hascoordinates = 0

    if hascoordinates and not latitude.std():
        hascoordinates = 0
        
    try:
	bearing = rowdata.df.ix[:,'bearing'].values
    except KeyError:
	rowdata.add_bearing()
	rowdata.write_csv(f1,gzip=True)
	

    if hascoordinates:
        avglat = rowdata.df[' latitude'].mean()
        avglon = rowdata.df[' longitude'].mean()
        airportcode,newlat,newlon,airportdistance = get_airport_code(avglat,avglon)
        airportcode = airportcode.upper()
        airportdistance = airportdistance[0]
    else:
        airportcode = 'UNKNOWN'
        airportdistance = 0
        

    if request.method == 'POST':
	# process form
	form = UpdateWindForm(request.POST)

	if form.is_valid():
	    
	    vwind1 = form.cleaned_data['vwind1']
	    vwind2 = form.cleaned_data['vwind2']
	    dist1 = form.cleaned_data['dist1']
	    dist2 = form.cleaned_data['dist2']
	    winddirection1 = form.cleaned_data['winddirection1']
	    winddirection2 = form.cleaned_data['winddirection2']
	    windunit = form.cleaned_data['windunit']

	    rowdata.update_wind(vwind1,vwind2,
				winddirection1,
				winddirection2,
				dist1,dist2,
				units=windunit)

	    rowdata.write_csv(f1,gzip=True)

	    
	else:
	    message = "Invalid Form"
            messages.error(request,message)
	    kwargs = {
		'id':int(id)
            }
	    url = reverse(workout_wind_view,kwargs=kwargs)
	    response = HttpResponseRedirect(url)
	    
    else:
	form = UpdateWindForm()

    # create interactive plot
    res = interactive_windchart(id,promember=1)
    script = res[0]
    div = res[1]

    if hascoordinates:
        gmscript,gmdiv = leaflet_chart(
            rowdata.df[' latitude'],
	    rowdata.df[' longitude'],
	    row.name)
    else:
	gmscript = ""
	gmdiv = "No GPS data available"


    messages.info(request,successmessage)
    messages.error(request,message)
    
    return render(request,
		  'windedit.html',
		  {'workout':row,
                   'teams':get_my_teams(request.user),
		   'interactiveplot':script,
		   'form':form,
                   'airport':airportcode,
                   'airportdistance':airportdistance,
		   'the_div':div,
		   'gmap':gmscript,
		   'gmapdiv':gmdiv})
    

# Show form to update River stream data (for river dwellers)
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def workout_stream_view(request,id=0,message="",successmessage=""):
    try:
        row = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

    if (checkworkoutuser(request.user,row)==False):
	message = "You are not allowed to edit this workout"
        messages.error(request,message)
	url = reverse(workouts_view)

	return HttpResponseRedirect(url)


    # create interactive plot
    f1 = row.csvfilename
    u = row.user.user
    r = getrower(u)

    rowdata = rdata(f1)
    if rowdata == 0:
	return HttpResponse("Error: CSV Data File Not Found")

    if request.method == 'POST':
	# process form
	form = UpdateStreamForm(request.POST)

	if form.is_valid():
	    
	    dist1 = form.cleaned_data['dist1']
	    dist2 = form.cleaned_data['dist2']
	    stream1 = form.cleaned_data['stream1']
	    stream2 = form.cleaned_data['stream2']
	    streamunit = form.cleaned_data['streamunit']

	    rowdata.update_stream(stream1,stream2,dist1,dist2,
				units=streamunit)

	    rowdata.write_csv(f1,gzip=True)

	    
	else:
	    message = "Invalid Form"
            messages.error(request,message)
	    kwargs = {
		'id':int(id)}
	    url = reverse(workout_wind_view,kwargs=kwargs)
	    response = HttpResponseRedirect(url)
	    
    else:
	form = UpdateStreamForm()

    # create interactive plot
    res = interactive_streamchart(id,promember=1)
    script = res[0]
    div = res[1]

    messages.info(request,successmessage)
    messages.error(request,message)
    return render(request,
		  'streamedit.html',
		  {'workout':row,
                   'teams':get_my_teams(request.user),
		   'interactiveplot':script,
		   'form':form,
		   'the_div':div})
    
# Form to set average crew weight and boat type, then run power calcs
@user_passes_test(ispromember, login_url="/",redirect_field_name=None)
def workout_otwsetpower_view(request,id=0,message="",successmessage=""):
    try:
        row = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

    if (checkworkoutuser(request.user,row)==False):
	message = "You are not allowed to edit this workout"
        messages.error(request,message)
	url = reverse(workouts_view)

	return HttpResponseRedirect(url)


    if request.method == 'POST':
	# process form
	form = AdvancedWorkoutForm(request.POST)

	if form.is_valid():
	    boattype = form.cleaned_data['boattype']
	    weightvalue = form.cleaned_data['weightvalue']
	    row.boattype = boattype
	    row.weightvalue = weightvalue
	    row.save()

	    # load row data & create power/wind/bearing columns if not set
	    f1 = row.csvfilename
	    rowdata = rdata(f1)
	    if rowdata == 0:
		return HttpResponse("Error: CSV Data File Not Found")
	    try:
		vstream = rowdata.df['vstream']
	    except KeyError:
		rowdata.add_stream(0)
		rowdata.write_csv(f1,gzip=True)

	    try:
		bearing = rowdata.df['bearing']
	    except KeyError:
		rowdata.add_bearing()
		rowdata.write_csv(f1,gzip=True)

	    try:
		vwind = rowdata.df['vwind']
	    except KeyError:
		rowdata.add_wind(0,0)
		rowdata.write_csv(f1,gzip=True)

	    # do power calculation (asynchronous)
            r = row.user
            u = r.user

	    first_name = u.first_name
	    last_name = u.last_name
	    emailaddress = u.email
	    
	    if settings.DEBUG:	    
		res = handle_otwsetpower.delay(f1,boattype,weightvalue,
					       first_name,last_name,
                                               emailaddress,id,debug=True,
                                               ps=[r.p0,r.p1,r.p2,r.p3],
                                               ratio=r.cpratio)
	    else:
		res = queuelow.enqueue(handle_otwsetpower,f1,boattype,
				    weightvalue,
				       first_name,last_name,emailaddress,id,
                                       ps=[r.p0,r.p1,r.p2,r.p3],
                                       ratio=r.cpratio)

	    
	    successmessage = "Your calculations have been submitted. You will receive an email when they are done."
            messages.info(request,successmessage)
	    kwargs = {
		'id':int(id)}

	    url = reverse(workout_advanced_view,kwargs=kwargs)
	    response = HttpResponseRedirect(url)
	    return response
	    
	else:
	    message = "Invalid Form"
            messages.error(request,message)
	    kwargs = {
		'id':int(id)}
	    url = reverse(workout_otwsetpower_view,kwargs=kwargs)
	    response = HttpResponseRedirect(url)
	    
    else:
	form = AdvancedWorkoutForm(instance=row)

    messages.error(request,message)
    messages.info(request,successmessage)
    return render(request,
		  'otwsetpower.html',
		  {'workout':row,
                   'teams':get_my_teams(request.user),
		   'form':form,
		   })

# A special Edit page with all the Geeky functionality for the workout
@login_required()
def workout_geeky_view(request,id=0,message="",successmessage=""):
    try:
        row = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

    form = WorkoutForm(instance=row)
    g = GraphImage.objects.filter(workout=row).order_by("-creationdatetime")
    # check if user is owner of this workout

    if (checkworkoutuser(request.user,row)==False):
	message = "You are not allowed to edit this workout"
        messages.error(request,message)
	url = reverse(workouts_view)

	return HttpResponseRedirect(url)


    # create interactive plot
    f1 = row.csvfilename
    u = row.user.user
    r = getrower(u)

    # create interactive plot
    try:
	res = interactive_chart(id,promember=1)
	script = res[0]
	div = res[1]
    except ValueError:
	pass

    messages.error(request,message)
    messages.info(request,successmessage)

    if row.workouttype in ('water','coastal'):
	return render(request,
		  'otwgeeky.html',
		  {'workout':row,
                   'teams':get_my_teams(request.user),
		   'interactiveplot':script,
		   'the_div':div})
    else:
	return render(request,
		  'advancededit.html',
		  {'workout':row,
                   'teams':get_my_teams(request.user),
		   'interactiveplot':script,
		   'the_div':div})

# Cumulative stats page
@login_required()
def cumstats(request,theuser=0,
	     startdate=timezone.now()-datetime.timedelta(days=30),
	     enddate=timezone.now(),
	     deltadays=-1,
	     startdatestring="",
	     enddatestring="",
             plotfield='spm',
             options={
                 'includereststrokes':False,
                 'workouttypes':['rower','dynamic','slides'],
                 'waterboattype':['1x','2x','2-','4x','4-','8+']
             }):

    if 'options' in request.session:
        options = request.session['options']
        
    workouttypes = options['workouttypes']
    includereststrokes = options['includereststrokes']
    workstrokesonly = not includereststrokes
    checktypes = ['water','rower','dynamic','slides','skierg',
                  'paddle','snow','other','coastal']
    waterboattype = ['1x','2x','2-','4x','4-','8+']
    
    if deltadays>0:
	startdate = enddate-datetime.timedelta(days=int(deltadays))

    if startdatestring != "":
	startdate = iso8601.parse_date(startdatestring)

    if enddatestring != "":
	enddate = iso8601.parse_date(enddatestring)

    if enddate < startdate:
	s = enddate
	enddate = startdate
	startdate = s

    promember=0
    if theuser == 0:
	theuser = request.user.id

    if not request.user.is_anonymous():
	r = getrower(request.user)
	result = request.user.is_authenticated() and ispromember(request.user)
	if result:
	    promember=1

    if not promember:
	return HttpResponseRedirect("/rowers/promembership/")
	
    # get all indoor rows of in date range
    # process form
    if request.method == 'POST' and "daterange" in request.POST:
	form = DateRangeForm(request.POST)
	deltaform = DeltaDaysForm(request.POST)
        optionsform = StatsOptionsForm()
	if form.is_valid():
	    startdate = form.cleaned_data['startdate']
	    enddate = form.cleaned_data['enddate']
	    if startdate > enddate:
		s = enddate
		enddate = startdate
		startdate = s
    elif request.method == 'POST' and "datedelta" in request.POST:
	deltaform = DeltaDaysForm(request.POST)
	if deltaform.is_valid():
	    deltadays = deltaform.cleaned_data['deltadays']
	    if deltadays != 0 and isinstance(deltadays, Number):
		enddate = timezone.now()
		startdate = enddate-datetime.timedelta(days=deltadays)
		if startdate > enddate:
		    s = enddate
		    enddate = startdate
		    startdate = s
		form = DateRangeForm(initial={
		    'startdate': startdate,
		    'enddate': enddate,
		    })
                optionsform = StatsOptionsForm()
            else:
                form = DateRangeForm()
                optionsform = StatsOptionsForm()
    elif request.method == 'POST' and 'options' in request.POST:
        optionsform = StatsOptionsForm(request.POST)
        if optionsform.is_valid():
            includereststrokes = optionsform.cleaned_data['includereststrokes']
            workstrokesonly = not includereststrokes
            workouttypes = []
            waterboattype = optionsform.cleaned_data['waterboattype']
            for type in checktypes:
                if optionsform.cleaned_data[type]:
                    workouttypes.append(type)

            options = {
                'includereststrokes':includereststrokes,
                'workouttypes':workouttypes,
                'waterboattype':waterboattype,
                }
            form = DateRangeForm()
            deltaform = DeltaDaysForm()
        else:
            form = DateRangeForm()
            deltaform = DeltaDaysForm()
    else:
	form = DateRangeForm(initial={
	    'startdate': startdate,
	    'enddate': enddate,
	    })
	deltaform = DeltaDaysForm()
        optionsform = StatsOptionsForm()

    try:
	r2 = getrower(theuser)
	allergworkouts = Workout.objects.filter(user=r2,
						workouttype__in=workouttypes,
                                                boattype__in=waterboattype,
						startdatetime__gte=startdate,
						startdatetime__lte=enddate)
	
    except Rower.DoesNotExist:
	allergworkouts = []
	r2=0

    try:
	u = User.objects.get(id=theuser)
    except User.DoesNotExist:
	u = ''

    ids = [int(workout.id) for workout in allergworkouts]

    datemapping = {
        w.id:w.date for w in allergworkouts
        }

    
    
    fieldlist,fielddict = dataprep.getstatsfields()
    
    # prepare data frame
    datadf = dataprep.read_cols_df_sql(ids,fieldlist)

    datadf = dataprep.clean_df_stats(datadf,workstrokesonly=workstrokesonly)
    
    
    if datadf.empty:
        stats = {}
        plotfield = 'spm'
        cordict = {}
        div = "No Data found"
        script = ''
        
        response = render(request,
		          'cumstats.html',
		          {
                              'stats':stats,
                              'teams':get_my_teams(request.user),
                              'options':options,
		              'id':theuser,
		              'theuser':u,
		              'startdate':startdate,
		              'enddate':enddate,
		              'form':form,
		              'deltaform':deltaform,
                              'optionsform':optionsform,
                              'cordict':cordict,
                              'plotscript':script,
                              'plotdiv':div,
                              'plotfield':plotfield,
                          })

        request.session['options'] = options
        
        return response



    # Create stats
    stats = {}
    fielddict.pop('workoutstate')
    fielddict.pop('workoutid')

    for field,verbosename in fielddict.iteritems():
        thedict = {
            'mean':datadf[field].mean(),
            'min': datadf[field].min(),
            'std': datadf[field].std(),
            'max': datadf[field].max(),
            'median': datadf[field].median(),
            'firstq':datadf[field].quantile(q=0.25),
            'thirdq':datadf[field].quantile(q=0.75),
            'verbosename':verbosename,
        }
        stats[field] = thedict

    # Create a dict with correlation values
    cor = datadf.corr(method='spearman')
    cor.fillna(value=0,inplace=True)
    cordict = {}
    for field1,verbosename in fielddict.iteritems():
        thedict = {}
        for field2,verbosename in fielddict.iteritems():
            try:
                thedict[field2] = cor.ix[field1,field2]
            except KeyError:
                thedict[field2] = 0

        cordict[field1] = thedict

    # interactive box plot
    datadf['workoutid'].replace(datemapping,inplace=True)
    datadf.rename(columns={"workoutid":"date"},inplace=True)
    datadf = datadf.sort_values(['date'])
    script,div = interactive_boxchart(datadf,plotfield)
    
    # set options form correctly
    initial = {}
    initial['includereststrokes'] = includereststrokes
    initial['waterboattype'] = waterboattype

    for wtype in checktypes:
        if wtype in workouttypes:
            initial[wtype] = True
        else:
            initial[wtype] = False


    optionsform = StatsOptionsForm(initial=initial)
            
    response = render(request,
		  'cumstats.html',
		  {
                      'stats':stats,
                      'teams':get_my_teams(request.user),
                      'options':options,
		      'id':theuser,
		      'theuser':u,
		      'startdate':startdate,
		      'enddate':enddate,
		      'form':form,
		      'deltaform':deltaform,
                      'optionsform':optionsform,
                      'cordict':cordict,
                      'plotscript':script,
                      'plotdiv':div,
                      'plotfield':plotfield,
                  })

    request.session['options'] = options

    return response

# Stats page
@login_required()
def workout_stats_view(request,id=0,message="",successmessage=""):

    r = getrower(request.user)
    try:
        w = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
        raise Http404("Workout doesn't exist")

    workstrokesonly = True
    if request.method == 'POST' and 'workstrokesonly' in request.POST:
        workstrokesonly = str2bool(request.POST['workstrokesonly'])


    # prepare data frame
    datadf,row = dataprep.getrowdata_db(id=id)
    if (checkworkoutuser(request.user,row)==False):
        message = "You are not allowed to see the stats of this workout"
        messages.error(request,message)
        url = reverse(workouts_view)
        return HttpResponseRedirect(url)

    datadf = dataprep.clean_df_stats(datadf,workstrokesonly=workstrokesonly)

        
    if datadf.empty:
        return HttpResponse("CSV data file not found")

    workoutstateswork = [1,4,5,8,9,6,7]
    workoutstatesrest = [3]
    workoutstatetransition = [0,2,10,11,12,13]


    # Create stats
    stats = {}

    fieldlist,fielddict = dataprep.getstatsfields()
    fielddict.pop('workoutstate')
    fielddict.pop('workoutid')
    
    for field,verbosename in fielddict.iteritems():
        thedict = {
            'mean':datadf[field].mean(),
            'min': datadf[field].min(),
            'std': datadf[field].std(),
            'max': datadf[field].max(),
            'median': datadf[field].median(),
            'firstq':datadf[field].quantile(q=0.25),
            'thirdq':datadf[field].quantile(q=0.75),
            'verbosename':verbosename,
        }
        stats[field] = thedict

    # Create a dict with correlation values
    cor = datadf.corr(method='spearman')
    cor.fillna(value=0,inplace=True)
    cordict = {}
    for field1,verbosename in fielddict.iteritems():
        thedict = {}
        for field2,verbosename in fielddict.iteritems():
            try:
                thedict[field2] = cor.ix[field1,field2]
            except KeyError:
                thedict[field2] = 0

            cordict[field1] = thedict

    # additional non-automated stats
    otherstats = {}

    # Normalized power & TSS
    duration = datadf['time'].max()-datadf['time'].min()
    duration /= 1.0e3
    pwr4 = datadf['power']**(4)
    normp = (pwr4.mean())**(0.25)
    if not np.isnan(normp):
        ftp = float(r.ftp)
        if w.workouttype in ('water','coastal'):
            ftp = ftp*(100.-r.otwslack)/100.
            
        intensityfactor = datadf['power'].mean()/float(ftp)
        intensityfactor = normp/float(ftp)
        tss = 100.*((duration*normp*intensityfactor)/(3600.*ftp))

        if not np.isnan(tss):
            otherstats['tss'] = {
                'verbose_name':'rScore',
                'value':int(tss),
                'unit':''
            }
    
    if not np.isnan(normp):
        otherstats['np'] = {
            'verbose_name':'rPower',
            'value':int(10*normp)/10.,
            'unit':'Watt'
        }
        
    # HR Drift
    tmax = datadf['time'].max()
    tmin = datadf['time'].min()
    thalf = tmin+0.5*(tmax-tmin)
    mask1 = datadf['time'] < thalf
    mask2 = datadf['time'] > thalf

    hr1 = datadf.loc[mask1,'hr'].mean()
    hr2 = datadf.loc[mask2,'hr'].mean()
            
    pwr1 = datadf.loc[mask1,'power'].mean()
    pwr2 = datadf.loc[mask2,'power'].mean()

    try:
        hrdrift = ((pwr1/hr1)-(pwr2/hr2))/(pwr1/hr1)
        hrdrift *= 100.
        if not np.isnan(hrdrift):
            hrdrift = int(100*hrdrift)/100.
            otherstats['hrdrift'] = {
                'verbose_name': 'Heart Rate Drift',
                'value': hrdrift,
                'unit': '%',
            }
    except ZeroDivisionError,ValueError:
        pass


    return render(request,
		  'workoutstats.html',
		  {
                      'stats':stats,
                      'teams':get_my_teams(request.user),
                      'workout':row,
                      'workstrokesonly':workstrokesonly,
                      'cordict':cordict,
                      'otherstats':otherstats,
                  })
    
# The Advanced edit page
@login_required()
def workout_advanced_view(request,id=0,message="",successmessage=""):
    try:
        row = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")
    form = WorkoutForm(instance=row)
    g = GraphImage.objects.filter(workout=row).order_by("-creationdatetime")
    # check if user is owner of this workout

    if (checkworkoutuser(request.user,row)==False):
	message = "You are not allowed to edit this workout"
        messages.error(request,message)
	url = reverse(workouts_view)

	return HttpResponseRedirect(url)


    # create interactive plot
    f1 = row.csvfilename
    u = row.user.user
    r = getrower(u)

    # create interactive plot
    try:
	res = interactive_chart(id,promember=1)
	script = res[0]
	div = res[1]
    except ValueError:
	pass

    messages.error(request,message)
    messages.info(request,successmessage)


    if row.workouttype in ('water','coastal'):
	return render(request,
		  'advancedotw.html',
		  {'workout':row,
                   'teams':get_my_teams(request.user),
		   'interactiveplot':script,
		   'the_div':div})
    else:
	return render(request,
		  'advancededit.html',
		  {'workout':row,
                   'teams':get_my_teams(request.user),
		   'interactiveplot':script,
		   'the_div':div})

# The interactive plot comparing two workouts (obsolete version)
def workout_comparison_view(request,id1=0,id2=0,xparam='distance',yparam='spm'):
    promember=0
    if not request.user.is_anonymous():
	r = getrower(request.user)
	result = request.user.is_authenticated() and ispromember(request.user)
	if result:
	    promember=1

    # create interactive plot
    res = interactive_comparison_chart(id1,id2,xparam=xparam,yparam=yparam,
				       promember=promember)
    script = res[0]
    div = res[1]

    axchoicesbasic = {ax[0]:ax[1] for ax in axes if ax[4]=='basic'}
    axchoicespro = {ax[0]:ax[1] for ax in axes if ax[4]=='pro'}
    noylist = ["time","distance"]
    axchoicesbasic.pop("cumdist")

    return render(request,
		  'comparisonchart.html',
		  {'interactiveplot':script,
		   'the_div':div,
                   'teams':get_my_teams(request.user),
		   'id1':id1,
		   'id2':id2,
                   'axchoicesbasic':axchoicesbasic,
                   'axchoicespro':axchoicespro,
                   'noylist':noylist,
		   'xparam':xparam,
		   'yparam':yparam,
		   })

# Updated version of comparison plot	
def workout_comparison_view2(request,id1=0,id2=0,xparam='distance',
			    yparam='spm',plottype='line'):
    promember=0
    if not request.user.is_anonymous():
	r = getrower(request.user)
	result = request.user.is_authenticated() and ispromember(request.user)
	if result:
	    promember=1

    if not Workout.objects.filter(id=id1).exists() or not Workout.objects.filter(id=id2).exists():
        raise Http404("Workout doesn't exist")
        
    # create interactive plot
    res = interactive_comparison_chart(id1,id2,xparam=xparam,yparam=yparam,
				       promember=promember,plottype=plottype)
    script = res[0]
    div = res[1]

    axchoicesbasic = {ax[0]:ax[1] for ax in axes if ax[4]=='basic'}
    axchoicespro = {ax[0]:ax[1] for ax in axes if ax[4]=='pro'}
    noylist = ["time","distance"]
    axchoicesbasic.pop("cumdist")

    row1 = Workout.objects.get(id=id1)
    row2 = Workout.objects.get(id=id2)

    if row1.workouttype != 'water' or row2.workouttype != 'water':
        axchoicespro.pop('slip')
        axchoicespro.pop('wash')
        axchoicespro.pop('catch')
        axchoicespro.pop('finish')
        axchoicespro.pop('totalangle')
        axchoicespro.pop('effectiveangle')
        axchoicespro.pop('peakforceangle')
        
    
    return render(request,
		  'comparisonchart2.html',
		  {'interactiveplot':script,
		   'the_div':div,
                   'teams':get_my_teams(request.user),
		   'id1':id1,
		   'id2':id2,
                   'axchoicesbasic':axchoicesbasic,
                   'axchoicespro':axchoicespro,
                   'noylist':noylist,
		   'xparam':xparam,
		   'yparam':yparam,
		   'plottype':plottype,
		   'promember':promember,
		   })
	
	
# The famous flex chart
def workout_flexchart3_view(request,*args,**kwargs):
    
    try:
        id = kwargs['id']
    except KeyError:
        return HttpResponse("Invalid workout number")
    
    if 'promember' in kwargs:
        promember = kwargs['promember']
    else:
        promember = 0

    try:
        favoritenr = int(request.GET['favoritechart'])
    except:
        favoritenr = 0
        

    try:
        row = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

    promember=0
    mayedit=0
    if not request.user.is_anonymous():
	r = getrower(request.user)
	result = request.user.is_authenticated() and ispromember(request.user)
	if result:
	    promember=1
	if request.user == row.user.user:
	    mayedit=1


    workouttype = 'ote'
    if row.workouttype in ('water','coastal'):
        workouttype = 'otw'

    try:
        favorites = FavoriteChart.objects.filter(user=r,
                                                 workouttype__in=[workouttype,'both']).order_by("id")
        maxfav = len(favorites)-1
    except:
        favorites = None
        maxfav = 0

    # check if favoritenr is not out of range
    if favorites:
        try:
            t = favorites[favoritenr].xparam
        except IndexError:
            favoritenr=0
        
    if 'xparam' in kwargs:
        xparam = kwargs['xparam']
    else:
        if favorites:
            xparam = favorites[favoritenr].xparam
        else:
            xparam = 'distance'

    if 'yparam1' in kwargs:
        yparam1 = kwargs['yparam1']
    else:
        if favorites:
            yparam1 = favorites[favoritenr].yparam1
        else:
            yparam1 = 'pace'
            
    if 'yparam2' in kwargs:
        yparam2 = kwargs['yparam2']
        if yparam2 == '':
            yparam2 = 'None'
    else:
        if favorites:
            yparam2 = favorites[favoritenr].yparam2
            if yparam2 == '':
                yparam2 = 'None'
        else:
            yparam2 = 'hr'

    if 'plottype' in kwargs:
        plottype = kwargs['plottype']
    else:
        if favorites:
            plottype = favorites[favoritenr].plottype
        else:
            plottype = 'line'

    if 'workstrokesonly' in kwargs:
        workstrokesonly = kwargs['workstrokesonly']
    else:
        if favorites:
            workstrokesonly = not favorites[favoritenr].reststrokes
        else:
            workstrokesonly = False
            
    if request.method == 'POST' and 'savefavorite' in request.POST:
        if not request.user.is_anonymous():
            workstrokesonly = request.POST['workstrokesonlysave']
            reststrokes = not workstrokesonly
	    r = getrower(request.user)
            f = FavoriteChart(user=r,xparam=xparam,
                              yparam1=yparam1,yparam2=yparam2,
                              plottype=plottype,workouttype=workouttype,
                              reststrokes=reststrokes)
            f.save()

    if request.method == 'POST' and 'workstrokesonly' in request.POST:
	workstrokesonly = request.POST['workstrokesonly']
	if workstrokesonly == 'True':
	    workstrokesonly = True
	else:
	    workstrokesonly = False

    # create interactive plot
    try:
        script,div,js_resources,css_resources,workstrokesonly = interactive_flex_chart2(id,xparam=xparam,yparam1=yparam1,
				 yparam2=yparam2,
				 promember=promember,plottype=plottype,
				 workstrokesonly=workstrokesonly)
    except ValueError:
        script,div = interactive_flex_chart2(id,xparam=xparam,yparam1=yparam1,
				             yparam2=yparam2,
				             promember=promember,plottype=plottype,
				             workstrokesonly=workstrokesonly)
        js_resources = ""
        css_resources = ""

        
    # script = res[0]
    # div = res[1]
    # js_resources = res[2]
    # css_resources = res[3]

    
    axchoicesbasic = {ax[0]:ax[1] for ax in axes if ax[4]=='basic'}
    axchoicespro = {ax[0]:ax[1] for ax in axes if ax[4]=='pro'}
    noylist = ["time","distance"]
    axchoicesbasic.pop("cumdist")
    
    if row.workouttype in ('water','coastal'):
        return render(request,
		      'flexchart3otw.html',
		      {'the_script':script,
		       'the_div':div,
		       'js_res': js_resources,
		       'css_res':css_resources,
		       'id':int(id),
                       'teams':get_my_teams(request.user),
		       'xparam':xparam,
		       'yparam1':yparam1,
		       'yparam2':yparam2,
		       'plottype':plottype,
		       'mayedit':mayedit,
		       'promember':promember,
                       'axchoicesbasic':axchoicesbasic,
                       'axchoicespro':axchoicespro,
                       'noylist':noylist,
		       'workstrokesonly': not workstrokesonly,
                       'favoritenr':favoritenr,
                       'maxfav':maxfav,
		      })
    else:
        axchoicespro.pop('slip')
        axchoicespro.pop('wash')
        axchoicespro.pop('catch')
        axchoicespro.pop('finish')
        axchoicespro.pop('totalangle')
        axchoicespro.pop('effectiveangle')
        axchoicespro.pop('peakforceangle')
        axchoicespro.pop('efficiency')
        
        return render(request,
		      'flexchart3otw.html',
		      {'the_script':script,
		       'the_div':div,
		       'js_res': js_resources,
		       'css_res':css_resources,
		       'teams':get_my_teams(request.user),
                       'id':int(id),
		       'xparam':xparam,
		       'yparam1':yparam1,
		       'yparam2':yparam2,
		       'plottype':plottype,
                       'axchoicesbasic':axchoicesbasic,
                       'axchoicespro':axchoicespro,
                       'noylist':noylist,
		       'mayedit':mayedit,
		       'promember':promember,
		       'workstrokesonly': not workstrokesonly,
                       'favoritenr':favoritenr,
                       'maxfav':maxfav,
		      })
	

# The interactive plot with the colored Heart rate zones
def workout_biginteractive_view(request,id=0,message="",successmessage=""):
    try:
        row = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

    # check if user is owner of this workout


    # create interactive plot
    f1 = row.csvfilename
    u = row.user.user
    # r = getrower(u)

    promember=0
    mayedit=0
    if not request.user.is_anonymous():
	r = getrower(request.user)
	result = request.user.is_authenticated() and ispromember(request.user)
	if result:
	    promember=1
	if request.user == row.user.user:
	    mayedit=1


    # create interactive plot
    res = interactive_bar_chart(id,promember=promember)
    script = res[0]
    div = res[1]

    messages.error(request,message)
    messages.info(request,successmessage)


    return render(request,
		  'biginteractive1.html',
		  {'workout':row,
                   'teams':get_my_teams(request.user),
		   'interactiveplot':script,
		   'the_div':div,
		   'promember':promember,
		   'mayedit':mayedit})

# The interactive plot with wind corrected pace for OTW outings
def workout_otwpowerplot_view(request,id=0,message="",successmessage=""):
    try:
        row = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

    # check if user is owner of this workout


    # create interactive plot
    f1 = row.csvfilename
    u = row.user.user
    # r = getrower(u)

    promember=0
    mayedit=0
    if not request.user.is_anonymous():
	r = getrower(request.user)
	result = request.user.is_authenticated() and ispromember(request.user)
	if result:
	    promember=1
	if request.user == row.user.user:
	    mayedit=1

    # create interactive plot
    res = interactive_otw_advanced_pace_chart(id,promember=promember)
    script = res[0]
    div = res[1]

    messages.error(request,message)
    messages.info(request,successmessage)

    return render(request,
		  'otwinteractive.html',
		  {'workout':row,
                   'teams':get_my_teams(request.user),
		   'interactiveplot':script,
		   'the_div':div,
		   'mayedit':mayedit})

# the page where you can choose where to export this workout
@login_required()
def workout_export_view(request,id=0, message="", successmessage=""):
    request.session[translation.LANGUAGE_SESSION_KEY] = USER_LANGUAGE
    try:
        row = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

    try:
	thetoken = c2_open(request.user)
    except C2NoTokenError:
        thetoken = 0

    if (checkworkoutuser(request.user,row)) and thetoken:
        c2userid = c2stuff.get_userid(thetoken)
    else:
        c2userid = 0

    try:
        rktoken = runkeeper_open(request.user)
    except RunKeeperNoTokenError:
        rktoken = 0
        
    if (checkworkoutuser(request.user,row)) and rktoken:
        rkuserid = runkeeperstuff.get_userid(rktoken)
    else:
        rkuserid = 0
        
        
    form = WorkoutForm(instance=row)
    g = GraphImage.objects.filter(workout=row).order_by("-creationdatetime")
    # check if user is owner of this workout

    if (checkworkoutuser(request.user,row)==False):
	message = "You are not allowed to edit this workout"
        messages.error(request,message)
	url = reverse(workouts_view)

	return HttpResponseRedirect(url)

    messages.error(request,message)
    messages.info(request,successmessage)

    return render(request,
		  'export.html',
		  {'workout':row,
                   'teams':get_my_teams(request.user),
                   'c2userid':c2userid,
                   'rkuserid':rkuserid,
		  })

#
@login_required()
def workout_unsubscribe_view(request,id=0):
    try:
        w = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
        raise Http404("Workout doesn't exist")

    if w.privacy == 'private' and w.user.user != request.user:
	return HttpResponseForbidden("Permission error")

    comments = WorkoutComment.objects.filter(workout=w,
                                             user=request.user).order_by("created")

    for c in comments:
        c.notification = False
        c.save()

    form = WorkoutCommentForm()

    successmessage = 'You have been unsubscribed from new comment notifications for this workout'
    
    messages.info(request,successmessage)

    return render(request,
                  'workout_comments.html',
                  {'workout':w,
                   'teams':get_my_teams(request.user),
                   'comments':comments,
                   'form':form,
                   })

        
# list of comments to a workout
@login_required()
def workout_comment_view(request,id=0):
    try:
        w = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
        raise Http404("Workout doesn't exist")

    if w.privacy == 'private' and w.user.user != request.user:
	return HttpResponseForbidden("Permission error")

    comments = WorkoutComment.objects.filter(workout=w).order_by("created")

    # ok we're permitted
    if request.method == 'POST':
        r = w.user
        form = WorkoutCommentForm(request.POST)
        if form.is_valid():
            cd = form.cleaned_data
            comment = cd['comment']
            comment = bleach.clean(comment)
            notification = cd['notification']
            c = WorkoutComment(workout=w,user=request.user,comment=comment,
                               notification=notification)
            c.save()
            url = reverse(workout_comment_view,
                          kwargs={
                              'id':id
                              })
            message = '{name} says: <a href="{url}">{comment}</a>'.format(
                name = request.user.first_name,
                comment = comment,
                url = url,
            )
            if request.user != r.user:    
                a_messages.info(r.user,message)
                
            if settings.DEBUG and request.user != r.user:
	        res = handle_sendemailnewcomment.delay(r.user.first_name,
					               r.user.last_name,
					               r.user.email,
                                                       request.user.first_name,
                                                       request.user.last_name,
                                                       comment,w.name,
                                                       w.id)

                
	    elif request.user != r.user:
	        res = queuehigh.enqueue(handle_sendemailnewcomment,r.user.first_name,
				    r.user.last_name,
				    r.user.email,
                                    request.user.first_name,
                                    request.user.last_name,
                                    comment,w.name,w.id)
                
            commenters = {oc.user for oc in comments if oc.notification}
            for u in commenters:
                a_messages.info(u,message)
                if settings.DEBUG and u != request.user and u != r.user:
                    res = handle_sendemailnewresponse.delay(u.first_name,
                                                      u.last_name,
                                                      u.email,
                                                      request.user.first_name,
                                                      request.user.last_name,
                                                      comment,
                                                      w.name,
                                                      w.id,
                                                      c.id)
                elif u != request.user and u != r.user:
                    res = queuelow.enqueue(handle_sendemailnewresponse,
                                           u.first_name,
                                           u.last_name,
                                           u.email,
                                           request.user.first_name,
                                           request.user.last_name,
                                           comment,
                                           w.name,
                                           w.id,
                                           c.id)

        url = reverse(workout_comment_view,kwargs = {
        'id':id})
        return HttpResponseRedirect(url)
                
    form = WorkoutCommentForm()

    g = GraphImage.objects.filter(workout=w).order_by("-creationdatetime")

    if (len(g)<=3):
        return render(request,
                      'workout_comments.html',
                      {'workout':w,
                       'teams':get_my_teams(request.user),
		       'graphs1':g[0:3],
                       'comments':comments,
                       'form':form,
                      })
    else:
        return render(request,
                      'workout_comments.html',
                      {'workout':w,
                       'teams':get_my_teams(request.user),
		       'graphs1':g[0:3],
		       'graphs1':g[3:6],
                       'comments':comments,
                       'form':form,
                      })
        
        
# The basic edit page
@login_required()
def workout_edit_view(request,id=0,message="",successmessage=""):
    request.session[translation.LANGUAGE_SESSION_KEY] = USER_LANGUAGE
    request.session['referer'] = absolute(request)['PATH']


    try:
	# check if valid ID exists (workout exists)
	row = Workout.objects.get(id=id)
        form = WorkoutForm(instance=row)
    except Workout.DoesNotExist:
        raise Http404("Workout doesn't exist")

    if request.method == 'POST':
	# Form was submitted
	form = WorkoutForm(request.POST)
	if form.is_valid():
	    # Get values from form
	    name = form.cleaned_data['name']
	    date = form.cleaned_data['date']
	    starttime = form.cleaned_data['starttime']
	    workouttype = form.cleaned_data['workouttype']
	    duration = form.cleaned_data['duration']
	    distance = form.cleaned_data['distance']
	    notes = form.cleaned_data['notes']
            try:
                boattype  = request.POST['boattype']
            except KeyError:
                boattype = Workout.objects.get(id=id).boattype
            try:
                privacy = request.POST['privacy']
            except KeyError:
                privacy = Workout.objects.get(id=id).privacy
            try:
                rankingpiece = form.cleaned_data['rankingpiece']
            except KeyError:
                rankingpiece =- Workout.objects.get(id=id).rankingpiece
                
	    startdatetime = (str(date) + ' ' + str(starttime))
	    startdatetime = datetime.datetime.strptime(startdatetime,
						       "%Y-%m-%d %H:%M:%S")
	    startdatetime = timezone.make_aware(startdatetime)
            # check if user is owner of this workout
            if checkworkoutuser(request.user,row):
                row.name  = name
                row.date = date
                row.starttime = starttime
                row.startdatetime = startdatetime
                row.workouttype = workouttype
                row.notes = notes
                row.duration = duration
                row.distance = distance
                row.boattype = boattype
                row.privacy = privacy
                row.rankingpiece = rankingpiece
                try:
                    row.save()
                except IntegrityError:
                    pass
                # change data in csv file

                r = rdata(row.csvfilename)
                if r == 0:
                    return HttpResponse("Error: CSV Data File Not Found")
                r.rowdatetime = startdatetime
                r.write_csv(row.csvfilename,gzip=True)
                dataprep.update_strokedata(id,r.df)
                successmessage = "Changes saved"
                messages.info(request,successmessage)
                url = reverse(workout_edit_view,
                              kwargs = {
                                  'id':str(row.id),
                              })
                response = HttpResponseRedirect(url)
            else:
                message = "You are not allowed to change this workout"
                messages.error(request,message)
                url = reverse(workouts_view)

                response = HttpResponseRedirect(url)
                
    #else: # form not POSTed
    form = WorkoutForm(instance=row)


    try:
	row = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
        raise Http404("Workout doesn't exist")

    g = GraphImage.objects.filter(workout=row).order_by("-creationdatetime")
    # check if user is owner of this workout

    comments = WorkoutComment.objects.filter(workout=row)

    aantalcomments = len(comments)

    if (checkworkoutuser(request.user,row)==False):
        raise Http404("You are not allowed to edit this workout")

    # create interactive plot
    f1 = row.csvfilename
    u = row.user.user
    r = getrower(u)
    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'],
                                         row.name)
                                        
        #res = googlemap_chart(rowdata.df[' latitude'],
        #                      rowdata.df[' longitude'],
        #                      row.name)
        #gmscript = res[0]
        #gmdiv = res[1]

    else:
        mapscript = ""
        mapdiv = ""


    # render page
    if (len(g)<=3):
        return render(request, 'workout_form.html',
                      {'form':form,
                       'workout':row,
                       'teams':get_my_teams(request.user),
                       'graphs1':g[0:3],
                       'mapscript':mapscript,
                       'aantalcomments':aantalcomments,
                       'mapdiv':mapdiv,
                       })

    else:
        return render(request, 'workout_form.html',
                      {'form':form,
                       'teams':get_my_teams(request.user),
                       'workout':row,
                       'graphs1':g[0:3],
                       'graphs2':g[3:6],
                       'mapscript':mapscript,
                       'aantalcomments':aantalcomments,
                       'mapdiv':mapdiv,
                       })


    return HttpResponseRedirect(url)

# Create the chart image with wind corrected pace (OTW)
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def workout_add_otw_powerplot_view(request,id):
    try:
        w = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

    if (checkworkoutuser(request.user,w)==False):
	raise PermissionDenied("You are not allowed add plots to this workout")
    else:
	f1 = w.csvfilename[6:-4] 
	timestr = strftime("%Y%m%d-%H%M%S")
	imagename = f1+timestr+'.png'
	fullpathimagename = 'static/plots/'+imagename
	u = w.user.user
	r = getrower(u)
        powerperc = 100*np.array([r.pw_ut2,
                                  r.pw_ut1,
                                  r.pw_at,
                                  r.pw_tr,r.pw_an])/r.ftp


        ftp = r.ftp
        if w.workouttype in ('water','coastal'):
            ftp = ftp*(100.-r.otwslack)/100.

	hrpwrdata = {
	    'hrmax':r.max,
	    'hrut2':r.ut2,
	    'hrut1':r.ut1,
	    'hrat':r.at,
	    'hrtr':r.tr,
	    'hran':r.an,
	    'ftp':ftp,
            'powerperc':serialize_list(powerperc),
            'powerzones':serialize_list(r.powerzones),
	    }

	# make plot - asynchronous task
	plotnr = 9

	if w.workouttype in ('water','coastal'):
	    plotnr = plotnr+3

	if settings.DEBUG:	    
	    res = handle_makeplot.delay(f1,w.csvfilename,
					w.name,hrpwrdata,plotnr,imagename)
	else:
	    res = queue.enqueue(handle_makeplot,f1,w.csvfilename,
						w.name,hrpwrdata,plotnr,imagename)
	    
#	i = GraphImage(workout=w,creationdatetime=datetime.datetime.now(),
#			   filename=fullpathimagename)
	i = GraphImage(workout=w,creationdatetime=timezone.now(),
			   filename=fullpathimagename)
	i.save()

    url = "/rowers/workout/"+str(w.id)+"/edit"
    return HttpResponseRedirect(url)

# Create the Heart rate zone pie chart	
@login_required()
def workout_add_piechart_view(request,id):
    try:
        w = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

    if (checkworkoutuser(request.user,w)==False):
	raise PermissionDenied("You are not allowed add plots to this workout")
    else:
	f1 = w.csvfilename[6:-4] 
	timestr = strftime("%Y%m%d-%H%M%S")
	imagename = f1+timestr+'.png'
	fullpathimagename = 'static/plots/'+imagename
	u = w.user.user
	r = getrower(u)

	powerperc = 100*np.array([r.pw_ut2,
                                  r.pw_ut1,
                                  r.pw_at,
                                  r.pw_tr,r.pw_an])/r.ftp

        ftp = float(r.ftp)
        if w.workouttype in ('water','coastal'):
            ftp = ftp*(100.-r.otwslack)/100.
        
	hrpwrdata = {
	    'hrmax':r.max,
	    'hrut2':r.ut2,
	    'hrut1':r.ut1,
	    'hrat':r.at,
	    'hrtr':r.tr,
	    'hran':r.an,
	    'ftp':ftp,
            'powerperc':serialize_list(powerperc),
            'powerzones':serialize_list(r.powerzones),
	    }

	# make plot - asynchronous task
	plotnr = 3

	if w.workouttype in ('water','coastal'):
	    plotnr = plotnr+3

	if settings.DEBUG:	    
	    res = handle_makeplot.delay(f1,w.csvfilename,
					w.name,hrpwrdata,plotnr,imagename)
	else:
	    res = queue.enqueue(handle_makeplot,f1,w.csvfilename,
						w.name,hrpwrdata,plotnr,imagename)
	    
#	i = GraphImage(workout=w,creationdatetime=datetime.datetime.now(),
#			   filename=fullpathimagename)
	i = GraphImage(workout=w,creationdatetime=timezone.now(),
			   filename=fullpathimagename)
	i.save()

    url = "/rowers/workout/"+str(w.id)+"/edit"
    return HttpResponseRedirect(url)

# Create the Power zone pie chart
@login_required()
def workout_add_power_piechart_view(request,id):
    try:
        w = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

    if (checkworkoutuser(request.user,w)==False):
	raise PermissionDenied("You are not allowed add plots to this workout")
    else:
	f1 = w.csvfilename[6:-4] 
	timestr = strftime("%Y%m%d-%H%M%S")
	imagename = f1+timestr+'.png'
	fullpathimagename = 'static/plots/'+imagename
	u = w.user.user
	r = getrower(u)

	powerperc = 100*np.array([r.pw_ut2,
                                  r.pw_ut1,
                                  r.pw_at,
                                  r.pw_tr,r.pw_an])/r.ftp

        ftp = float(r.ftp)
        if w.workouttype in ('water','coastal'):
            ftp = ftp*(100.-r.otwslack)/100.
        
	hrpwrdata = {
	    'hrmax':r.max,
	    'hrut2':r.ut2,
	    'hrut1':r.ut1,
	    'hrat':r.at,
	    'hrtr':r.tr,
	    'hran':r.an,
	    'ftp':ftp,
            'powerperc':serialize_list(powerperc),
            'powerzones':serialize_list(r.powerzones),
	    }

	# make plot - asynchronous task
	plotnr = 13

	if w.workouttype in ('water','coastal'):
	    plotnr = plotnr+3

	if settings.DEBUG:	    
	    res = handle_makeplot.delay(f1,w.csvfilename,
					w.name,hrpwrdata,plotnr,imagename)
	else:
	    res = queue.enqueue(handle_makeplot,f1,w.csvfilename,
						w.name,hrpwrdata,plotnr,imagename)
	    
	i = GraphImage(workout=w,creationdatetime=timezone.now(),
			   filename=fullpathimagename)
	i.save()

    url = "/rowers/workout/"+str(w.id)+"/edit"
    return HttpResponseRedirect(url)

# Create the time based summary chart
@login_required()
def workout_add_timeplot_view(request,id):
    try:
        w = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

    if (checkworkoutuser(request.user,w)==False):
	raise PermissionDenied("You are not allowed add plots to this workout")
    else:
	f1 = w.csvfilename[6:-4] 
	timestr = strftime("%Y%m%d-%H%M%S")
	imagename = f1+timestr+'.png'
	fullpathimagename = 'static/plots/'+imagename
	u = w.user.user
	r = getrower(u)
	powerperc = 100*np.array([r.pw_ut2,
                                  r.pw_ut1,
                                  r.pw_at,
                                  r.pw_tr,r.pw_an])/r.ftp

        ftp = float(r.ftp)
        if w.workouttype in ('water','coastal'):
            ftp = ftp*(100.-r.otwslack)/100.
        
	hrpwrdata = {
	    'hrmax':r.max,
	    'hrut2':r.ut2,
	    'hrut1':r.ut1,
	    'hrat':r.at,
	    'hrtr':r.tr,
	    'hran':r.an,
	    'ftp':ftp,
            'powerperc':serialize_list(powerperc),
            'powerzones':serialize_list(r.powerzones),
	    }

	# make plot - asynchronous task
	plotnr = 1

	if  w.workouttype in ('water','coastal'):
	    plotnr = plotnr+3
		    
	if settings.DEBUG:	    
	    res = handle_makeplot.delay(f1,w.csvfilename,
					w.name,hrpwrdata,plotnr,imagename)
	else:
	    res = queue.enqueue(handle_makeplot,f1,w.csvfilename,
						w.name,hrpwrdata,plotnr,imagename)

	i = GraphImage(workout=w,creationdatetime=timezone.now(),
			   filename=fullpathimagename)
#	i = GraphImage(workout=w,creationdatetime=datetime.datetime.now(),
#			   filename=fullpathimagename)
	i.save()

    url = "/rowers/workout/"+str(w.id)+"/edit"
    return HttpResponseRedirect(url)
	
# Create the distance based summary chart
@login_required()
def workout_add_distanceplot_view(request,id):
    try:
        w = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

    if (checkworkoutuser(request.user,w)==False):
	raise PermissionDenied("You are not allowed add plots to this workout")
    else:
	f1 = w.csvfilename[6:-4] 
	timestr = strftime("%Y%m%d-%H%M%S")
	imagename = f1+timestr+'.png'
	fullpathimagename = 'static/plots/'+imagename
	u = w.user.user
	r = getrower(u)
	powerperc = 100*np.array([r.pw_ut2,
                                  r.pw_ut1,
                                  r.pw_at,
                                  r.pw_tr,r.pw_an])/r.ftp

        ftp = float(r.ftp)
        if w.workouttype in ('water','coastal'):
            ftp = ftp*(100.-r.otwslack)/100.
        
	hrpwrdata = {
	    'hrmax':r.max,
	    'hrut2':r.ut2,
	    'hrut1':r.ut1,
	    'hrat':r.at,
	    'hrtr':r.tr,
	    'hran':r.an,
	    'ftp':ftp,
            'powerperc':serialize_list(powerperc),
            'powerzones':serialize_list(r.powerzones),
	    }

	# make plot - asynchronous task
	plotnr = 2

	if w.workouttype in ('water','coastal'):
	    plotnr = plotnr+3
		    
	if settings.DEBUG:	    
	    res = handle_makeplot.delay(f1,w.csvfilename,
					w.name,hrpwrdata,plotnr,imagename)
	else:
	    res = queue.enqueue(handle_makeplot,f1,w.csvfilename,
						w.name,hrpwrdata,plotnr,imagename)
	
	i = GraphImage(workout=w,creationdatetime=timezone.now(),
			   filename=fullpathimagename)
	i.save()

    url = "/rowers/workout/"+str(w.id)+"/edit"
    return HttpResponseRedirect(url)

# Create the advanced parameters distance overview chart
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def workout_add_distanceplot2_view(request,id):
    try:
        w = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

    if (checkworkoutuser(request.user,w)==False):
	raise PermissionDenied("You are not allowed add plots to this workout")
    else:
	f1 = w.csvfilename[6:-4] 
	timestr = strftime("%Y%m%d-%H%M%S")
	imagename = f1+timestr+'.png'
	fullpathimagename = 'static/plots/'+imagename
	u = w.user.user
	r = getrower(u)
	powerperc = 100*np.array([r.pw_ut2,
                                  r.pw_ut1,
                                  r.pw_at,
                                  r.pw_tr,r.pw_an])/r.ftp

        ftp = float(r.ftp)
        if w.workouttype in ('water','coastal'):
            ftp = ftp*(100.-r.otwslack)/100.
        
	hrpwrdata = {
	    'hrmax':r.max,
	    'hrut2':r.ut2,
	    'hrut1':r.ut1,
	    'hrat':r.at,
	    'hrtr':r.tr,
	    'hran':r.an,
	    'ftp':ftp,
            'powerperc':serialize_list(powerperc),
            'powerzones':serialize_list(r.powerzones),
	    }

	# make plot - asynchronous task
	plotnr = 7

	if w.workouttype in ('water','coastal'):
	    plotnr = plotnr+3
		    
	if settings.DEBUG:	    
	    res = handle_makeplot.delay(f1,w.csvfilename,
					w.name,hrpwrdata,plotnr,imagename)
	else:
	    res = queue.enqueue(handle_makeplot,f1,w.csvfilename,
						w.name,hrpwrdata,plotnr,imagename)
	
	i = GraphImage(workout=w,creationdatetime=timezone.now(),
			   filename=fullpathimagename)

	i.save()

    url = "/rowers/workout/"+str(w.id)+"/edit"
    return HttpResponseRedirect(url)


# Create the advanced parameters time based overview chart
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def workout_add_timeplot2_view(request,id):
    try:
        w = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

    if (checkworkoutuser(request.user,w)==False):
	raise PermissionDenied("You are not allowed add plots to this workout")
    else:
	f1 = w.csvfilename[6:-4] 
	timestr = strftime("%Y%m%d-%H%M%S")
	imagename = f1+timestr+'.png'
	fullpathimagename = 'static/plots/'+imagename
	u = w.user.user
	r = getrower(u)
	powerperc = 100*np.array([r.pw_ut2,
                                  r.pw_ut1,
                                  r.pw_at,
                                  r.pw_tr,r.pw_an])/r.ftp

        ftp = float(r.ftp)
        if w.workouttype in ('water','coastal'):
            ftp = ftp*(100.-r.otwslack)/100.
        
	hrpwrdata = {
	    'hrmax':r.max,
	    'hrut2':r.ut2,
	    'hrut1':r.ut1,
	    'hrat':r.at,
	    'hrtr':r.tr,
	    'hran':r.an,
	    'ftp':ftp,
            'powerperc':serialize_list(powerperc),
            'powerzones':serialize_list(r.powerzones),
	    }

	# make plot - asynchronous task
	plotnr = 8

	if w.workouttype in ('water','coastal'):
	    plotnr = plotnr+3
		    
	if settings.DEBUG:	    
	    res = handle_makeplot.delay(f1,w.csvfilename,
					w.name,hrpwrdata,plotnr,imagename)
	else:
	    res = queue.enqueue(handle_makeplot,f1,w.csvfilename,
						w.name,hrpwrdata,plotnr,imagename)
	
	i = GraphImage(workout=w,creationdatetime=timezone.now(),
			   filename=fullpathimagename)

	i.save()

    url = "/rowers/workout/"+str(w.id)+"/edit"
    return HttpResponseRedirect(url)

# The page where you select which Strava workout to import
@login_required()
def workout_stravaimport_view(request,message=""):
    res = stravastuff.get_strava_workout_list(request.user)
    if (res.status_code != 200):
	if (res.status_code == 401):
	    r = getrower(request.user)
	    if (r.stravatoken == '') or (r.stravatoken is None):
		s = "Token doesn't exist. Need to authorize"
		return HttpResponseRedirect("/rowers/me/stravaauthorize/")
	message = "Something went wrong in workout_stravaimport_view"
        messages.error(request,message)
	if settings.DEBUG:
	    return HttpResponse(res)
	else:
	    url = reverse(workouts_view)
	    return HttpResponseRedirect(url)
    else:
        workouts = []
        r = getrower(request.user)
        stravaids = [int(item['id']) for item in res.json()]
        knownstravaids = uniqify([
            w.uploadedtostrava for w in Workout.objects.filter(user=r)
            ])
        newids = [stravaid for stravaid in stravaids if not stravaid in knownstravaids]
        
	for item in res.json():
            d = int(float(item['distance']))
            i = item['id']
            if i in knownstravaids:
                nnn = ''
            else:
                nnn = 'NEW'
            n = item['name']
            ttot = str(datetime.timedelta(seconds=int(float(item['elapsed_time']))))
            s = item['start_date']
            r = item['type']
            keys = ['id','distance','duration','starttime','type','name','new']
	    values = [i,d,ttot,s,r,n,nnn]
	    res = dict(zip(keys,values))
	    workouts.append(res)


	return render(request,'strava_list_import.html',
		      {'workouts':workouts,
                       'teams':get_my_teams(request.user),
		       })

    return HttpResponse(res)

# The page where you select which RunKeeper workout to import
@login_required()
def workout_runkeeperimport_view(request,message=""):
    res = runkeeperstuff.get_runkeeper_workout_list(request.user)
    if (res.status_code != 200):
	if (res.status_code == 401):
	    r = getrower(request.user)
	    if (r.runkeepertoken == '') or (r.runkeepertoken is None):
		s = "Token doesn't exist. Need to authorize"
		return HttpResponseRedirect("/rowers/me/runkeeperauthorize/")
	message = "Something went wrong in workout_runkeeperimport_view"
        messages.error(request,message)

	if settings.DEBUG:
	    return HttpResponse(res)
	else:
	    url = reverse(workouts_view)
	    return HttpResponseRedirect(url)
    else:
	workouts = []
	for item in res.json()['items']:
	    d = int(float(item['total_distance']))
	    i = getidfromsturi(item['uri'],length=9)
	    ttot = str(datetime.timedelta(seconds=int(float(item['duration']))))
	    s = item['start_time']
	    r = item['type']
	    keys = ['id','distance','duration','starttime','type']
	    values = [i,d,ttot,s,r]
	    res = dict(zip(keys,values))
	    workouts.append(res)
	return render(request,'runkeeper_list_import.html',
		      {'workouts':workouts,
                       'teams':get_my_teams(request.user),
		       })

    return HttpResponse(res)

# The page where you select which RunKeeper workout to import
@login_required()
def workout_underarmourimport_view(request,message=""):
    res = underarmourstuff.get_underarmour_workout_list(request.user)
    if (res.status_code != 200):
	if (res.status_code == 401):
	    r = getrower(request.user)
	    if (r.underarmourtoken == '') or (r.underarmourtoken is None):
		s = "Token doesn't exist. Need to authorize"
		return HttpResponseRedirect("/rowers/me/underarmourauthorize/")
	message = "Something went wrong in workout_underarmourimport_view"
        messages.error(request,message)
	if settings.DEBUG:
	    return HttpResponse(res)
	else:
	    url = reverse(workouts_view)
	    return HttpResponseRedirect(url)
    else:
	workouts = []
        items = res.json()['_embedded']['workouts']
	for item in items:
            if 'has_time_series' in item:
                if item['has_time_series']:
	            s = item['start_datetime']
                    i,r = underarmourstuff.get_idfromuri(request.user,item['_links'])
	            n = item['name']
                    try:
                        d = item['aggregates']['distance_total']
                    except KeyError:
                        d = 0
                    try:
                        ttot = item['aggregates']['active_time_total']
                    except KeyError:
                        ttot = 0
                        
	            keys = ['id','distance','duration','starttime','type']
	            values = [i,d,ttot,s,r]
	            thedict = dict(zip(keys,values))

	            workouts.append(thedict)

	return render(request,'underarmour_list_import.html',
		      {'workouts':workouts,
                       'teams':get_my_teams(request.user),
		       })

    return HttpResponse(res)

# The page where you select which SportTracks workout to import
@login_required()
def workout_sporttracksimport_view(request,message=""):
    res = sporttracksstuff.get_sporttracks_workout_list(request.user)
    if (res.status_code != 200):
	if (res.status_code == 401):
	    r = getrower(request.user)
	    if (r.sporttrackstoken == '') or (r.sporttrackstoken is None):
		s = "Token doesn't exist. Need to authorize"
		return HttpResponseRedirect("/rowers/me/sporttracksauthorize/")
	message = "Something went wrong in workout_sporttracksimport_view"
        messages.error(request,message)
	if settings.DEBUG:
	    return HttpResponse(res)
	else:
	    url = reverse(workouts_view)
	    return HttpResponseRedirect(url)
    else:
	workouts = []
        r = getrower(request.user)
        stids = [int(getidfromsturi(item['uri'])) for item in res.json()['items']]
        knownstids = uniqify([
            w.uploadedtosporttracks for w in Workout.objects.filter(user=r)
                      ])
        newids = [stid for stid in stids if not stid in knownstids]
	for item in res.json()['items']:
	    d = int(float(item['total_distance']))
	    i = int(getidfromsturi(item['uri']))
            if i in knownstids:
                nnn = ''
            else:
                nnn = 'NEW'
	    n = item['name']
	    ttot = str(datetime.timedelta(seconds=int(float(item['duration']))))
	    s = item['start_time']
	    r = item['type']
	    keys = ['id','distance','duration','starttime','type','name','new']
	    values = [i,d,ttot,s,r,n,nnn]
	    res = dict(zip(keys,values))
	    workouts.append(res)
	return render(request,'sporttracks_list_import.html',
		      {'workouts':workouts,
                       'teams':get_my_teams(request.user),
		       })

    return HttpResponse(res)
	
# List of workouts on Concept2 logbook. This view only used for debugging
@login_required()
def c2listdebug_view(request,message=""):
    try:
	thetoken = c2_open(request.user)
    except C2NoTokenError:
	return HttpResponseRedirect("/rowers/me/c2authorize/")

    r = getrower(request.user)

    res = c2stuff.get_c2_workout_list(request.user)

    if (res.status_code != 200):
	message = "Something went wrong in workout_c2import_view (C2 token renewal)"
        messages.error(request,message)
	if settings.DEBUG:
	    return HttpResponse(res)
	else:
	    url = reverse(workouts_view)
	    return HttpResponseRedirect(url)
    else:
	workouts = []
	for item in res.json()['data']:
	    d = item['distance']
	    i = item['id']
	    ttot = item['time_formatted']
	    s = item['date']
	    r = item['type']
	    s2 = item['source']
	    c = item['comments']
	    keys = ['id','distance','duration','starttime','rowtype','source','comment']
	    values = [i,d,ttot,s,r,s2,c]
	    res = dict(zip(keys,values))
	    workouts.append(res)

	    
	return render(request,
		      'c2_list_import2.html',
		      {'workouts':workouts,
                       'teams':get_my_teams(request.user),
                      })

# Import all unknown workouts available on Concept2 logbook
@login_required()
def workout_getc2workout_all(request,message=""):
    try:
	thetoken = c2_open(request.user)
    except C2NoTokenError:
	return HttpResponseRedirect("/rowers/me/c2authorize/")

    res = c2stuff.get_c2_workout_list(request.user)

    if (res.status_code != 200):
	message = "Something went wrong in workout_c2import_view (C2 token refresh)"
        messages.error(request,message)
    else:
        r = getrower(request.user)
        c2ids = [item['id'] for item in res.json()['data']]
        knownc2ids = uniqify([
            w.uploadedtoc2 for w in Workout.objects.filter(user=r)
        ])
        newids = [c2id for c2id in c2ids if not c2id in knownc2ids]
        for c2id in newids:
            res = c2stuff.get_c2_workout(request.user,c2id)
            if (res.status_code == 200):
	        data = res.json()['data']
                splitdata = None
                if 'workout' in data:
                    if 'splits' in data['workout']:
                        splitdata = data['workout']['splits']
                    if 'intervals' in data['workout']:
                        splitdata = data['workout']['intervals']

                # Check if workout has stroke data, and get the stroke data
                if data['stroke_data']:
	            res2 = c2stuff.get_c2_workout_strokes(request.user,c2id)
                    # We have stroke data
	            if res2.status_code == 200:
	                strokedata = pd.DataFrame.from_dict(res2.json()['data'])
                        # create the workout
	                id,message = add_workout_from_strokedata(
                            request.user,c2id,data,strokedata,
			    source='c2')
	                w = Workout.objects.get(id=id)
	                w.uploadedtoc2=c2id
                        w.save()
                        if message:
                            messages.error(request,message)

    url = reverse(workouts_view)
    return HttpResponseRedirect(url)
            
    
# List of workouts available on Concept2 logbook - for import
@login_required()
def workout_c2import_view(request,message=""):
    try:
	thetoken = c2_open(request.user)
    except C2NoTokenError:
	return HttpResponseRedirect("/rowers/me/c2authorize/")

    res = c2stuff.get_c2_workout_list(request.user)

    if (res.status_code != 200):
	message = "Something went wrong in workout_c2import_view (C2 token refresh)"
        messages.error(request,message)
	if settings.DEBUG:
	    return HttpResponse(res)
	else:
	    url = reverse(workouts_view)
	    return HttpResponseRedirect(url)
    else:
	workouts = []
        r = getrower(request.user)
        c2ids = [item['id'] for item in res.json()['data']]
        knownc2ids = uniqify([
            w.uploadedtoc2 for w in Workout.objects.filter(user=r)
                      ])
        newids = [c2id for c2id in c2ids if not c2id in knownc2ids]
	for item in res.json()['data']:
	    d = item['distance']
	    i = item['id']
	    ttot = item['time_formatted']
	    s = item['date']
	    r = item['type']
	    s2 = item['source']
	    c = item['comments']
            if i in knownc2ids:
                nnn = ''
            else:
                nnn = 'NEW'
	    keys = ['id','distance','duration','starttime','rowtype','source','comment','new']
	    values = [i,d,ttot,s,r,s2,c,nnn]
	    res = dict(zip(keys,values))
	    workouts.append(res)

	    
	return render(request,
		      'c2_list_import2.html',
		      {'workouts':workouts,
                       'teams':get_my_teams(request.user),
                      })

# Import a workout from Strava
@login_required()
def workout_getstravaworkout_view(request,stravaid):
    res = stravastuff.get_strava_workout(request.user,stravaid)
    if not res[0]:
        messages.error(request,res[1])
        return imports_view(request)
        
    strokedata = res[1]
    data = res[0]
    id,message = add_workout_from_strokedata(request.user,stravaid,data,strokedata,
				             source='strava',
                                             workoutsource='strava')
    try:
        w = Workout.objects.get(id=id)
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

    w.uploadedtostrava=stravaid
    w.save()
    if message:
        messages.error(request,message)


    url = reverse(workout_edit_view,
                  kwargs = {
                      'id':int(id),
                  })
        
    return HttpResponseRedirect(url)

# Imports a workout from Runkeeper
@login_required()
def workout_getrunkeeperworkout_view(request,runkeeperid):
    res = runkeeperstuff.get_runkeeper_workout(request.user,runkeeperid)
    data = res.json()

    id,message = add_workout_from_runkeeperdata(request.user,runkeeperid,data)
    w = Workout.objects.get(id=id)
    w.uploadedtorunkeeper=runkeeperid
    thetoken = runkeeper_open(request.user)
    w.save()
    if message:
        messages.error(request,message)

    url = reverse(workout_edit_view,
                  kwargs = {
                      'id':int(id),
                  })
    return HttpResponseRedirect(url)

# Imports a workout from Underarmour
@login_required()
def workout_getunderarmourworkout_view(request,underarmourid):
    res = underarmourstuff.get_underarmour_workout(request.user,underarmourid)
    data = res.json()

    id,message = add_workout_from_underarmourdata(request.user,underarmourid,data)
    w = Workout.objects.get(id=id)
    w.uploadedtounderarmour=underarmourid
    w.save()
    if message:
        messages.error(request,message)

    url = reverse(workout_edit_view,
                  kwargs = {
                      'id':int(id),
                  })
    return HttpResponseRedirect(url)



# Imports a workout from SportTracks
@login_required()
def workout_getsporttracksworkout_view(request,sporttracksid):
    res = sporttracksstuff.get_sporttracks_workout(request.user,sporttracksid)
    data = res.json()

    id,message = add_workout_from_stdata(request.user,sporttracksid,data)
    if id==0:
        messages.error(request,message)
        url = reverse(workouts_view)
        return HttpResponseRedirect(url)
    w = Workout.objects.get(id=id)
    w.uploadedtosporttracks=sporttracksid
    w.save()
    if message:
        messages.error(request,message)

    url = reverse(workout_edit_view,
                  kwargs = {
                      'id':int(id),
                  })
    return HttpResponseRedirect(url)

# Imports all new workouts from SportTracks
@login_required()
def workout_getsporttracksworkout_all(request):
    res = sporttracksstuff.get_sporttracks_workout_list(request.user)
    if (res.status_code == 200):
        r = getrower(request.user)
        stids = [int(getidfromsturi(item['uri'])) for item in res.json()['items']]
        knownstids = uniqify([
            w.uploadedtosporttracks for w in Workout.objects.filter(user=r)
                      ])
        newids = [stid for stid in stids if not stid in knownstids]
        for sporttracksid in newids:
            res = sporttracksstuff.get_sporttracks_workout(
                request.user,sporttracksid)
            data = res.json()

            id,message = add_workout_from_stdata(request.user,sporttracksid,data)
            if id==0:
                messages.error(request,message)

            else:
                w = Workout.objects.get(id=id)
                w.uploadedtosporttracks=sporttracksid
                w.save()

    url = reverse(workouts_view)
    return HttpResponseRedirect(url)


# Imports all new workouts from SportTracks
@login_required()
def workout_getstravaworkout_all(request):
    res = stravastuff.get_strava_workout_list(request.user)
    if (res.status_code == 200):
        r = getrower(request.user)
        stravaids = [int(item['id']) for item in res.json()]
        knownstravaids = uniqify([
            w.uploadedtostrava for w in Workout.objects.filter(user=r)
            ])
        newids = [stravaid for stravaid in stravaids if not stravaid in knownstravaids]

        for stravaid in newids:
            res = stravastuff.get_strava_workout(request.user,stravaid)
            strokedata = res[1]
            data = res[0]

            if data:
                id,message = add_workout_from_strokedata(
                    request.user,stravaid,data,strokedata,
                    source='strava',
                    workoutsource='strava')

                if id==0:
                    messages.error(request,message)

                else:
                    messages.info(request,"imported Strava workout "+str(stravaid))
                    w = Workout.objects.get(id=id)
                    w.uploadedtostrava=stravaid
                    w.save()

            else:
                messages.error(request,"Couldn't import Strava workout "+str(stravaid))

    url = reverse(workouts_view)
    return HttpResponseRedirect(url)



# Imports a workout from Concept2 
@login_required()
def workout_getc2workout_view(request,c2id):
    try:
	thetoken = c2_open(request.user)
    except C2NoTokenError:
	return HttpResponseRedirect("/rowers/me/c2authorize/")

    res = c2stuff.get_c2_workout(request.user,c2id)
    if (res.status_code == 200):
	data = res.json()['data']
        splitdata = None
        if 'workout' in data:
            if 'splits' in data['workout']:
                splitdata = data['workout']['splits']
            if 'intervals' in data['workout']:
                splitdata = data['workout']['intervals']

        # Check if workout has stroke data, and get the stroke data
        if data['stroke_data']:
	    res2 = c2stuff.get_c2_workout_strokes(request.user,c2id)
        else:
            message = "This workout does not have any stroke data associated with it"
            messages.error(request,message)
            url = reverse(workout_c2import_view)
	    return HttpResponseRedirect(url)

        # We have stroke data
	if res2.status_code == 200:
	    strokedata = pd.DataFrame.from_dict(res2.json()['data'])
            # create the workout
	    id,message = add_workout_from_strokedata(request.user,c2id,data,strokedata,
					     source='c2')
	    w = Workout.objects.get(id=id)
	    w.uploadedtoc2=c2id
            # If we have split data, update the stroke data so they
            # match exactly (some users are anal about this)
            if splitdata:
                try:
                    w.summary,sa,results = c2stuff.summaryfromsplitdata(splitdata,data,w.csvfilename)
                except:
                    sa = []
                    results = []
                    with open("media/c2splitdata.log","a") as errorlog:
                        errorstring = str(sys.exc_info()[0])
                        timestr = strftime("%Y%m%d-%H%M%S")
                        errorlog.write(timestr+errorstring+"\r\n")
                        errorlog.write("views.py line 952\r\n")

                w.save()

                from rowingdata.trainingparser import getlist
                # set stroke data in CSV file
                if sa:
                    values = getlist(sa)
                    units = getlist(sa,sel='unit')
                    types = getlist(sa,sel='type')

                    rowdata = rdata(w.csvfilename)
                    if rowdata:
                        rowdata.updateintervaldata(values,
                                                   units,types,results)

                        rowdata.write_csv(w.csvfilename,gzip=True)
                        dataprep.update_strokedata(w.id,rowdata.df)

            if message:
                messages.error(request,message)

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

	    return HttpResponseRedirect(url)
	else:
	    # message = json.loads(s.text)['message']
            message = json.loads(res2.text)['message']
            messages.error(request,message)

	url = reverse(workout_c2import_view)
	return HttpResponseRedirect(url)

    else:
	message = "Received error code from Concept2"
        messages.error(request,message)
	if settings.DEBUG:
	    return HttpResponse(res)
	else:
	    url = reverse(workout_c2import_view)
	    return HttpResponseRedirect(url)

# This is the main view for processing uploaded files
@login_required()
def workout_upload_view(request,
                        uploadoptions={
                            'makeprivate':False,
                            'make_plot':False,
                            'upload_to_C2':False,
                            'plottype':'timeplot',
                        },
                        docformoptions={
                            'workouttype':'rower',
                        }):

    if 'uploadoptions' in request.session:
        uploadoptions = request.session['uploadoptions']
    else:
        request.session['uploadoptions'] = uploadoptions

    if 'docformoptions' in request.session:
        docformoptions = request.session['docformoptions']
    else:
        request.session['docformoptions'] = docformoptions

    try:
        makeprivate = uploadoptions['makeprivate']
    except KeyError:
        makeprivate = False
    try:
        make_plot = uploadoptions['make_plot']
    except KeyError:
        make_plot = False

    try:
        workouttype = docformoptions['workouttype']
    except KeyError:
        workouttype = 'rower'

    try:
        plottype = uploadoptions['plottype']
    except KeyError:
        plottype = 'timeplot'

    try:
        upload_toc2 = uploadoptions['upload_to_C2']
    except KeyError:
        upload_toc2 = False

    try:
        upload_tostrava = uploadoptions['upload_to_Strava']
    except KeyError:
        upload_tostrava = False

    try:
        upload_tost = uploadoptions['upload_to_SportTracks']
    except KeyError:
        upload_tost = False

    try:
        upload_tork = uploadoptions['upload_to_RunKeeper']
    except KeyError:
        upload_tork = False

    try:
        upload_toua = uploadoptions['upload_to_MapMyFitness']
    except KeyError:
        upload_toua = False

    try:
        upload_totp = uploadoptions['upload_to_TrainingPeaks']
    except KeyError:
        upload_totp = False

    r = getrower(request.user)
    if request.method == 'POST':
	form = DocumentsForm(request.POST,request.FILES)
	optionsform = UploadOptionsForm(request.POST)
	if form.is_valid():
	    f = request.FILES['file']
	    res = handle_uploaded_file(f)
	    t = form.cleaned_data['title']
	    workouttype = form.cleaned_data['workouttype']
            request.session['docformoptions'] = {
                'workouttype':workouttype,
                }
            
	    notes = form.cleaned_data['notes']

            if optionsform.is_valid():
	        make_plot = optionsform.cleaned_data['make_plot']
	        plottype = optionsform.cleaned_data['plottype']
	        upload_to_c2 = optionsform.cleaned_data['upload_to_C2']
	        upload_to_strava = optionsform.cleaned_data['upload_to_Strava']
	        upload_to_st = optionsform.cleaned_data['upload_to_SportTracks']
	        upload_to_rk = optionsform.cleaned_data['upload_to_RunKeeper']
	        upload_to_ua = optionsform.cleaned_data['upload_to_MapMyFitness']
	        upload_to_tp = optionsform.cleaned_data['upload_to_TrainingPeaks']
                makeprivate = optionsform.cleaned_data['makeprivate']

                uploadoptions = {
                    'makeprivate':makeprivate,
                    'make_plot':make_plot,
                    'plottype':plottype,
                    'upload_to_C2':upload_to_c2,
                    'upload_to_Strava':upload_to_strava,
                    'upload_to_SportTracks':upload_to_st,
                    'upload_to_RunKeeper':upload_to_rk,
                    'upload_to_MapMyFitness':upload_to_ua,
                    'upload_to_TrainingPeaks':upload_to_tp,
                }


            request.session['uploadoptions'] = uploadoptions

	    f1 = res[0] # file name
	    f2 = res[1] # file name incl media directory


            id,message,f2 = dataprep.new_workout_from_file(r,f2,
                                                           workouttype=workouttype,
                                                           makeprivate=makeprivate,
                                                           title = t,
                                                           notes='')
            if not id:
                messages.error(request,message)
		url = reverse(workout_upload_view)
		response = HttpResponseRedirect(url)
                return response
            elif id == -1:
                message = 'The zip archive will be processed in the background. The files in the archive will only be uploaded without the extra actions. You will receive email when the workouts are ready.'
                messages.info(request,message)
                url = reverse(workout_upload_view)
                response = HttpResponseRedirect(url)
                return response
            else:
                if message:
                    messages.error(request,message)

                url = reverse(workout_edit_view,
                              kwargs = {
                                  'id':int(id),
                              })
                    
                response = HttpResponseRedirect(url)
                w = Workout.objects.get(id=id)

	    if (make_plot):        
		imagename = f1[:-4]+'.png'
		fullpathimagename = 'static/plots/'+imagename
		u = request.user
		r = getrower(request.user)
	        powerperc = 100*np.array([r.pw_ut2,
                                          r.pw_ut1,
                                          r.pw_at,
                                          r.pw_tr,r.pw_an])/r.ftp

                ftp = float(r.ftp)
                if w.workouttype in ('water','coastal'):
                    ftp = ftp*(100.-r.otwslack)/100.

	        hrpwrdata = {
	            'hrmax':r.max,
	            'hrut2':r.ut2,
	            'hrut1':r.ut1,
	            'hrat':r.at,
	            'hrtr':r.tr,
	            'hran':r.an,
	            'ftp':ftp,
                    'powerperc':serialize_list(powerperc),
                    'powerzones':serialize_list(r.powerzones),
	        }

		# make plot - asynchronous task
		plotnrs = {
		    'timeplot':1,
		    'distanceplot':2,
		    'pieplot':3,
		}

		plotnr = plotnrs[plottype]
		if workouttype in ('water','coastal'):
		    plotnr = plotnr+3

		    
		if settings.DEBUG:	    
		    res = handle_makeplot.delay(f1,f2,t,
						hrpwrdata,plotnr,
						imagename)
		else:
		    res = queue.enqueue(handle_makeplot,f1,f2,
					t,hrpwrdata,
					plotnr,imagename)

		    
		i = GraphImage(workout=w,
			       creationdatetime=timezone.now(),
			       filename=fullpathimagename)
		i.save()

	    # upload to C2
	    if (upload_to_c2):
                try:
                    message,id = c2stuff.workout_c2_upload(request.user,w)
                except C2NoTokenError:
                    id = 0
                    message = "Something went wrong with the Concept2 sync"
                if id>1:
                    messages.info(request,message)
                else:
                    messages.error(request,message)
                    
            if (upload_to_strava):
                try:
                    message,id = stravastuff.workout_strava_upload(
                        request.user,w
                    )
                except StravaNoTokenError:
                    id = 0
                    message = "Please connect to Strava first"
                if id>1:
                    messages.info(request,message)
                else:
                    messages.error(request,message)
                    
            if (upload_to_st):
                try:
                    message,id = sporttracksstuff.workout_sporttracks_upload(
                        request.user,w
                    )
                except SportTracksNoTokenError:
                    message = "Please connect to SportTracks first"
                    id = 0
                if id>1:
                    messages.info(request,message)
                else:
                    messages.error(request,message)
                    
            if (upload_to_rk):
                try:
                    message,id = runkeeperstuff.workout_runkeeper_upload(
                        request.user,w
                        )
                except RunKeeperNoTokenError:
                    message = "Please connect to Runkeeper first"
                    id = 0

                if id>1:
                    messages.info(request,message)
                else:
                    messages.error(request,message)


            if (upload_to_ua):
                try:
                    message,id = underarmourstuff.workout_ua_upload(
                        request.user,w
                    )
                except UnderArmourNoTokenError:
                    message = "Please connect to MapMyFitness first"
                    id = 0

                if id>1:
                    messages.info(request,message)
                else:
                    messages.error(request,message)


            if (upload_to_tp):
                try:
                    message,id = tpstuff.workout_tp_upload(
                        request.user,w
                        )
                except TPNoTokenError:
                    message = "Please connect to TrainingPeaks first"
                    id = 0

                if id>1:
                    messages.info(request,message)
                else:
                    messages.error(request,message)
                    
            url = reverse(workout_edit_view,
                          kwargs = {
                              'id':w.id,
                          })
            return HttpResponseRedirect(url)
	else:
	   response = render(request,
			     'document_form.html',
			     {'form':form,
                              'teams':get_my_teams(request.user),
			      'optionsform': optionsform,
                             })

	return response
    else:
	form = DocumentsForm(initial=docformoptions)
	optionsform = UploadOptionsForm(initial=uploadoptions)
	return render(request, 'document_form.html',
		      {'form':form, 
                       'teams':get_my_teams(request.user),
		       'optionsform': optionsform,
                      })

# This is the main view for processing uploaded files
@user_passes_test(iscoachmember,login_url="/",redirect_field_name=None)
def team_workout_upload_view(request,message="",
                             successmessage="",
                             uploadoptions={
                                 'make_plot':False,
                                 'plottype':'timeplot',
                             }):

    if 'uploadoptions' in request.session:
        uploadoptions = request.session['uploadoptions']
    else:
        request.session['uploadoptions'] = uploadoptions


    myteams = Team.objects.filter(manager=request.user)
        
    make_plot = uploadoptions['make_plot']
    plottype = uploadoptions['plottype']

    r = getrower(request.user)
    if request.method == 'POST':
	form = DocumentsForm(request.POST,request.FILES)
	optionsform = TeamUploadOptionsForm(request.POST)
        
        rowerform = TeamInviteForm(request.POST)
        rowerform.fields.pop('email')
        rowerform.fields['user'].queryset = User.objects.filter(rower__isnull=False,rower__team__in=myteams).distinct()
	if form.is_valid():
	    f = request.FILES['file']
	    res = handle_uploaded_file(f)
	    t = form.cleaned_data['title']
            if rowerform.is_valid():
                u = rowerform.cleaned_data['user']
                if u:
                    r = getrower(u)
                else:
                    message = 'Please select a rower'
                    messages.error(request,message)
                    messages.info(request,successmessage)
                    response = render(request,
			      'team_document_form.html',
			     {'form':form,
                              'teams':get_my_teams(request.user),
			      'optionsform': optionsform,
                              'rowerform': rowerform,
                             })

	            return response

                workouttype = form.cleaned_data['workouttype']

	    notes = form.cleaned_data['notes']

            if optionsform.is_valid():
	        make_plot = optionsform.cleaned_data['make_plot']
	        plottype = optionsform.cleaned_data['plottype']

                uploadoptions = {
                    'makeprivate':False,
                    'make_plot':make_plot,
                    'plottype':plottype,
                    'upload_to_C2':False,
                }


            request.session['uploadoptions'] = uploadoptions

	    f1 = res[0] # file name
	    f2 = res[1] # file name incl media directory


            id,message,f2 = dataprep.new_workout_from_file(r,f2,
                                                           workouttype=workouttype,
                                                           makeprivate=False,
                                                           title = t,
                                                           notes='')
            if not id:
                messages.error(request,message)
		url = reverse(team_workout_upload_view)
		response = HttpResponseRedirect(url)
                return response
            elif id == -1:
                message = 'The zip archive will be processed in the background. The files in the archive will only be uploaded without the extra actions. You will receive email when the workouts are ready.'
                messages.info(request,message)
                url = reverse(team_workout_upload_view)
                response = HttpResponseRedirect(url)
                return response

            else:
                successmessage = "The workout was added to the user's account"
                messages.info(request,successmessage)

                url = reverse(team_workout_upload_view)
                    
                response = HttpResponseRedirect(url)
                w = Workout.objects.get(id=id)

	    if (make_plot):        
		imagename = f1[:-4]+'.png'
		fullpathimagename = 'static/plots/'+imagename
	        powerperc = 100*np.array([r.pw_ut2,
                                          r.pw_ut1,
                                          r.pw_at,
                                          r.pw_tr,r.pw_an])/r.ftp

                ftp = float(r.ftp)
                if w.workouttype in ('water','coastal'):
                    ftp = ftp*(100.-r.otwslack)/100.

	        hrpwrdata = {
	            'hrmax':r.max,
	            'hrut2':r.ut2,
	            'hrut1':r.ut1,
	            'hrat':r.at,
	            'hrtr':r.tr,
	            'hran':r.an,
	            'ftp':ftp,
                    'powerperc':serialize_list(powerperc),
                    'powerzones':serialize_list(r.powerzones),
	        }

		# make plot - asynchronous task
		plotnrs = {
		    'timeplot':1,
		    'distanceplot':2,
		    'pieplot':3,
		}

		plotnr = plotnrs[plottype]
		if workouttype in ('water','coastal'):
		    plotnr = plotnr+3

		    
		if settings.DEBUG:	    
		    res = handle_makeplot.delay(f1,f2,t,
						hrpwrdata,plotnr,
						imagename)
		else:
		    res = queue.enqueue(handle_makeplot,f1,f2,
					t,hrpwrdata,
					plotnr,imagename)

		    
		i = GraphImage(workout=w,
			       creationdatetime=timezone.now(),
			       filename=fullpathimagename)
		i.save()



	else:
            
            response = render(request,
			      'team_document_form.html',
			     {'form':form,
                              'teams':get_my_teams(request.user),
			      'optionsform': optionsform,
                              'rowerform': rowerform,
                             })

	return response
    else:
	form = DocumentsForm()
	optionsform = TeamUploadOptionsForm(initial=uploadoptions)
        rowerform = TeamInviteForm()
        rowerform.fields.pop('email')
        rowerform.fields['user'].queryset = User.objects.filter(rower__isnull=False,rower__team__in=myteams).distinct()
	return render(request, 'team_document_form.html',
		      {'form':form, 
                       'teams':get_my_teams(request.user),
		       'optionsform': optionsform,
                       'rowerform':rowerform,
                      })



# Ask the user if he really wants to delete the workout
@login_required()
def workout_delete_confirm_view(request, id=0):
    try:
	row = Workout.objects.get(id=id)
	if (checkworkoutuser(request.user,row)==False):
	    raise PermissionDenied("You are not allowed to delete this workout")
	else:
            url = request.META.get('HTTP_REFERER','/')
	    return render(request,'workout_delete_confirm.html',
			  {'id':int(id),
                           'teams':get_my_teams(request.user),
			   'workout':row,
                           'url':url})
		
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

# Really deleting the workout
@login_required()
def workout_delete_view(request,id=0):
    try:
	row = Workout.objects.get(id=id)
	if (checkworkoutuser(request.user,row)==False):
	    raise PermissionDenied("You are not allowed to delete this workout")
	else:
	    # files are removed by pre-delete in models.py
	    row.delete()

        messages.info(request,'Workout deleted')
        try:
            url = request.session['referer']
            if 'rowers/workout/' in url:
                url = reverse(workouts_view)
        except KeyError:
            url = reverse(workouts_view)
            
        
	return HttpResponseRedirect(url)
		
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

# Ask the user to confirm that he wants to delete a chart
@login_required()
def graph_delete_confirm_view(request, id=0):
    try:
	img = GraphImage.objects.get(id=id)
	row = Workout.objects.get(id=img.workout.id)
	if (checkworkoutuser(request.user,row)==False):
	    raise PermissionDenied("You are not allowed to delete this workout")
	else:
            try:
                url = request.session['referer']
            except KeyError:
                url = '/rowers/list-graphs'
                request.session['referer'] = url
	    return render(request,'graphimage_delete_confirm.html',
			  {'id':int(id),
                           'teams':get_my_teams(request.user),
			   'graph':img,
                           'url':url})
		
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")
    except GraphImage.DoesNotExist:
        raise Http404("The image doesn't exist")

# Really deleting the chart
@login_required()
def graph_delete_view(request,id=0):
    try:
	img = GraphImage.objects.get(id=id)
	row = Workout.objects.get(id=img.workout.id)
	if (checkworkoutuser(request.user,row)==False):
	    raise PermissionDenied("You are not allowed to delete this graph")
	else:
	    img.delete()
            messages.info(request,'Graph deleted')
            try:
                url = request.session['referer']
            except KeyError:
                url = reverse(graphs_view)
	    return HttpResponseRedirect(url)

    except GraphImage.DoesNotExist:
	raise Http404("Graph Image doesn't exist")
    except Workout.DoesNotExist:
        raise Http404("Workout doesn't exist")

# A page with all the recent graphs (searchable on workout name)
@login_required()
def graphs_view(request):
    request.session['referer'] = reverse(graphs_view)
    try:
	r = getrower(request.user)
	workouts = Workout.objects.filter(user=r).order_by("-date", "-starttime")
        query = request.GET.get('q')
        if query:
            query_list = query.split()
            workouts = workouts.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))
                )

	g = GraphImage.objects.filter(workout__in=workouts).order_by("-creationdatetime")
	if (len(g)<=5):
	    return render(request, 'list_graphs.html',
			  {'graphs1': g[0:4],
                          'teams':get_my_teams(request.user),
                          })
	else:
	    return render(request, 'list_graphs.html',
			  {'graphs1': g[0:5],
                           'teams':get_my_teams(request.user),
			   'graphs2': g[5:10]})
    except Rower.DoesNotExist:
	raise Http404("User has no rower instance")

# Show the chart (png image)
def graph_show_view(request,id):
    try:
	g = GraphImage.objects.get(id=id)
	w = Workout.objects.get(id=g.workout.id)
	r = Rower.objects.get(id=w.user.id)

	return render(request,'show_graph.html',
		      {'graph':g,
                       'teams':get_my_teams(request.user),
		       'workout':w,
		       'rower':r,})
			 
    except GraphImage.DoesNotExist:
	raise Http404("This graph doesn't exist")
    except Workout.DoesNotExist:
        raise Http404("This workout doesn't exist")
    
# Restore original stroke data and summary
@login_required()
def workout_summary_restore_view(request,id,message="",successmessage=""):
    try:
	row = Workout.objects.get(id=id)
	if (checkworkoutuser(request.user,row)==False):
	    raise PermissionDenied("You are not allowed to edit this workout")
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

    s = ""
    # still here - this is a workout we may edit
    f1 = row.csvfilename
    u = row.user.user
    r = getrower(u)
    powerperc = 100*np.array([r.pw_ut2,
                              r.pw_ut1,
                              r.pw_at,
                              r.pw_tr,r.pw_an])/r.ftp

    ftp = float(r.ftp)
    if row.workouttype in ('water','coastal'):
        ftp = ftp*(100.-r.otwslack)/100.
        
    rr = rrower(hrmax=r.max,hrut2=r.ut2,
		hrut1=r.ut1,hrat=r.at,
		hrtr=r.tr,hran=r.an,ftp=ftp,
                powerperc=powerperc,powerzones=r.powerzones)
    rowdata = rdata(f1,rower=rr)
    if rowdata == 0:
	raise Http404("Error: CSV Data File Not Found")
    rowdata.restoreintervaldata()
    rowdata.write_csv(f1,gzip=True)
    dataprep.update_strokedata(id,rowdata.df)
    intervalstats = rowdata.allstats()
    row.summary = intervalstats
    row.save()
    itime,idist,itype = rowdata.intervalstats_values()
    nrintervals = len(idist)

    # create interactive plot
    try:
	res = interactive_chart(id,promember=1)
	script = res[0]
	div = res[1]
    except ValueError:
	pass
    

    messages.info(request,'Original Interval Data Restored')
    url = reverse(workout_summary_edit_view,
                  kwargs={
	              'id':int(id),
                  }			  
    )
    return HttpResponseRedirect(url)

# Split a workout
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def workout_split_view(request,id=id):
    try:
	row = Workout.objects.get(id=id)
	if (checkworkoutuser(request.user,row)==False):
	    raise PermissionDenied("You are not allowed to edit this workout")
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

    r = row.user
    
    if request.method == 'POST':
        form = WorkoutSplitForm(request.POST)
        if form.is_valid():
            splittime = form.cleaned_data['splittime']
            splitsecond = splittime.hour*3600
            splitsecond += splittime.minute*60
            splitsecond += splittime.second
            splitsecond += splittime.microsecond/1.e6
            splitmode = form.cleaned_data['splitmode']
            ids,mesgs = dataprep.split_workout(r,row,splitsecond,splitmode)
            for message in mesgs:
                messages.info(request,message)


            if request.user == r:
                url = reverse(workouts_view)
            else:
                mgrids = [team.id for team in Team.objects.filter(manager=request.user)]
                rwrids = [team.id for team in r.team.all()]
                teamids = list(set(mgrids) & set(rwrids))
                if len(teamids) > 0:
                    teamid = teamids[0]
                
                    url = reverse(workouts_view,
                                  kwargs={
	                              'teamid':int(teamid),
                                  }
                    )
                else:
                    url = reverse(workouts_view)

            qdict = {'q':row.name}
            url+='?'+urllib.urlencode(qdict)

            return HttpResponseRedirect(url)

    form = WorkoutSplitForm()

    # create interactive plot
    try:
	res = interactive_chart(id,promember=1)
	script = res[0]
	div = res[1]
    except ValueError:
	pass

    return render(request, 'splitworkout.html',
		  {'form':form,
                   'workout':row,
                   'thediv':script,
                   'thescript':div,
                  })


# Fuse two workouts
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def workout_fusion_view(request,id1=0,id2=1):
    try:
        w1 = Workout.objects.get(id=id1)
        w2 = Workout.objects.get(id=id2)
        r = w1.user
        if (checkworkoutuser(request.user,w1)==False) or \
           (checkworkoutuser(request.user,w2)==False):
            raise PermissionDenied("You are not allowed to use these workouts")
    except Workout.DoesNotExist:
        raise Http404("One of the workouts doesn't exist")

    if request.method == 'POST':
        form = FusionMetricChoiceForm(request.POST,instance=w2)
        if form.is_valid():
            cd = form.cleaned_data
            columns = cd['columns']
            timeoffset = cd['offset']
            posneg = cd['posneg']
            if posneg == 'neg':
                timeoffset = -timeoffset

            # Create DataFrame
            df = dataprep.datafusion(id1,id2,columns,timeoffset)

            idnew,message = dataprep.new_workout_from_df(r,df,
                                                         title='Fused data',
                                                         parent=w1)
            if message != None:
                messages.error(request,message)
            else:
                successmessage = 'Data fused'
                messages.info(request,message)

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

            return HttpResponseRedirect(url)
        else:
            return render(request, 'fusion.html',
		          {'form':form,
                           'teams':get_my_teams(request.user),
                           'workout1':w1,
                           'workout2':w2,
                          })
        

    form = FusionMetricChoiceForm(instance=w2)
    
    return render(request, 'fusion.html',
		  {'form':form,
                   'teams':get_my_teams(request.user),
                   'workout1':w1,
                   'workout2':w2,
                  })


# Edit the splits/summary
@login_required()
def workout_summary_edit_view(request,id,message="",successmessage=""
			      ):
    try:
	row = Workout.objects.get(id=id)
	if (checkworkoutuser(request.user,row)==False):
	    raise PermissionDenied("You are not allowed to edit this workout")
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")

    s = ""
    # still here - this is a workout we may edit
    f1 = row.csvfilename
    u = row.user.user
    r = getrower(u)
    powerperc = 100*np.array([r.pw_ut2,
                              r.pw_ut1,
                              r.pw_at,
                              r.pw_tr,r.pw_an])/r.ftp

    ftp = float(r.ftp)
    if row.workouttype in ('water','coastal'):
        ftp = ftp*(100.-r.otwslack)/100.
        
    rr = rrower(hrmax=r.max,hrut2=r.ut2,
		hrut1=r.ut1,hrat=r.at,
		hrtr=r.tr,hran=r.an,ftp=ftp,
                powerperc=powerperc,powerzones=r.powerzones)
    rowdata = rdata(f1,rower=rr)
    if rowdata == 0:
	return HttpResponse("Error: CSV Data File Not Found")
    intervalstats = rowdata.allstats()
    itime,idist,itype = rowdata.intervalstats_values()
    nrintervals = len(idist)

    # create interactive plot
    try:
	res = interactive_chart(id,promember=1)
	script = res[0]
	div = res[1]
    except ValueError:
	pass
    
    savebutton = 'nosavebutton'

    # We have submitted the mini language interpreter
    if request.method == 'POST' and "intervalstring" in request.POST:
	form = SummaryStringForm(request.POST)
	if form.is_valid():
	    cd = form.cleaned_data
	    s = cd["intervalstring"]
            try:
	        rowdata.updateinterval_string(s)
            except IndexError:
                messages.error(request,'Interval string parse error')
	    intervalstats = rowdata.allstats()
	    itime,idist,itype = rowdata.intervalstats_values()
	    nrintervals = len(idist)
	    savebutton = 'savestringform'
	    
    # we are saving the results obtained from the mini language interpreter
    elif request.method == 'POST' and "savestringform" in request.POST:
	s = request.POST["savestringform"]
	rowdata.updateinterval_string(s)
	intervalstats = rowdata.allstats()
	itime,idist,itype = rowdata.intervalstats_values()
	nrintervals = len(idist)
	row.summary = intervalstats
	#intervalstats = rowdata.allstats()
        if s:
            try:
	        row.notes += u'{n} \n {s}'.format(
                    n = row.notes,
                    s = s
                )
            except TypeError:
                pass
            
	row.save()
	rowdata.write_csv(f1,gzip=True)
        dataprep.update_strokedata(id,rowdata.df)
	messages.info(request,"Updated interval data saved")
	data = {'intervalstring':s}
	form = SummaryStringForm(initial=data)
	savebutton = 'savestringform'

    # we are saving the results obtained from the detailed form
    elif request.method == 'POST' and "savedetailform" in request.POST:
	savebutton = 'savedetailform'
	form = SummaryStringForm()
	nrintervals = int(request.POST['nrintervals'])
	detailform = IntervalUpdateForm(request.POST,aantal=nrintervals)
	itime = []
	idist = []
	itype = []
	ivalues = []
	iunits = []
	itypes = []
	iresults = []
	for i in xrange(nrintervals):
	    try:
		t = datetime.datetime.strptime(request.POST['intervalt_%s' % i],"%H:%M:%S.%f")
	    except ValueError:
		t = datetime.datetime.strptime(request.POST['intervalt_%s' % i],"%H:%M:%S")
		
	    timesecs = 3600*t.hour+60*t.minute+t.second+t.microsecond/1.e6
	    itime += [timesecs]
	    idist += [int(request.POST['intervald_%s' % i])]
	    itype += [int(request.POST['type_%s' % i])]

	    if itype[i] == 3: # rest
		itypes += ['rest']
		ivalues += [timesecs]
		iresults += [idist[i]]
		iunits += ['seconds']
	    if itype[i] == 5 or itype[i] == 2:  # distance based work
		itypes += ['work']
		ivalues += [idist[i]]
		iresults += [timesecs]
		iunits += ['meters']
	    if itype[i] == 4 or itype[i] == 1:  # time based work
		itypes += ['work']
		ivalues += [timesecs]
		iresults += [idist[i]]
		iunits += ['seconds']


	rowdata.updateintervaldata(ivalues,iunits,itypes,iresults=iresults)
	intervalstats = rowdata.allstats()
	row.summary = intervalstats
	row.notes += "\n"+s
	row.save()
	rowdata.write_csv(f1,gzip=True)
        dataprep.update_strokedata(id,rowdata.df)
	messages.info(request,"Updated interval data saved")

	form = SummaryStringForm()

    # we are processing the details form
    elif request.method == 'POST' and "nrintervals" in request.POST:
	savebutton = 'savedetailform'
	nrintervals = int(request.POST['nrintervals'])
	detailform = IntervalUpdateForm(request.POST,aantal=nrintervals)
	if detailform.is_valid():
	    cd = detailform.cleaned_data
	    itime = []
	    idist = []
	    itype = []
	    ivalues = []
	    iunits = []
	    itypes = []
	    iresults = []
	    for i in xrange(nrintervals):
		t = cd['intervalt_%s' % i]
		timesecs = t.total_seconds()
		itime += [timesecs]
		idist += [cd['intervald_%s' % i]]
		itype += [cd['type_%s' % i]]

		if itype[i] == '3': # rest
		    itypes += ['rest']
		    ivalues += [timesecs]
		    iresults += [idist[i]]
		    iunits += ['seconds']
		if itype[i] == '5' or itype[i] == '2':  # distance based work
		    itypes += ['work']
		    ivalues += [idist[i]]
		    iresults += [timesecs]
		    iunits += ['meters']
		if itype[i] == '4' or itype[i] == '1':  # time based work
		    itypes += ['work']
		    ivalues += [timesecs]
		    iresults += [idist[i]]
		    iunits += ['seconds']

	    rowdata.updateintervaldata(ivalues,iunits,
				       itypes,iresults=iresults)
	    intervalstats = rowdata.allstats()


	form = SummaryStringForm()
	
    else:
	form = SummaryStringForm()

    initial = {}
    for i in xrange(nrintervals):
	initial['intervald_%s' % i] = idist[i]
	initial['intervalt_%s' % i] = get_time(itime[i])
	initial['type_%s' % i] = itype[i]


    detailform = IntervalUpdateForm(aantal=nrintervals,initial=initial)


    # render page

    return render(request, 'summary_edit.html',
		  {'form':form,
		   'detailform':detailform,
		   'workout':row,
                   'teams':get_my_teams(request.user),
		   'intervalstats':intervalstats,
		   'nrintervals':nrintervals,
		   'interactiveplot':script,
		   'the_div':div,
		   'intervalstring':s,
		   'savebutton':savebutton,
		   })

# Page where user can manage his favorite charts
@user_passes_test(ispromember,login_url="/rowers/me/edit",redirect_field_name=None)
def rower_favoritecharts_view(request):
    message = ''
    successmessage = ''
    r = getrower(request.user)
    favorites = FavoriteChart.objects.filter(user=r).order_by('id')
    aantal = len(favorites)
    favorites_data = [{'yparam1':f.yparam1,
                       'yparam2':f.yparam2,
                       'xparam':f.xparam,
                       'plottype':f.plottype,
                       'workouttype':f.workouttype,
                       'reststrokes':f.reststrokes}
                       for f in favorites]
    FavoriteChartFormSet = formset_factory(FavoriteForm,formset=BaseFavoriteFormSet,extra=0)
    if aantal==0:
        FavoriteChartFormSet = formset_factory(FavoriteForm,formset=BaseFavoriteFormSet,extra=1)
        

    if request.method == 'POST':
        favorites_formset = FavoriteChartFormSet(request.POST)

        if favorites_formset.is_valid():
            new_instances = []
            for favorites_form in favorites_formset:
                yparam1 = favorites_form.cleaned_data.get('yparam1')
                yparam2 = favorites_form.cleaned_data.get('yparam2')
                xparam = favorites_form.cleaned_data.get('xparam')
                plottype = favorites_form.cleaned_data.get('plottype')
                workouttype = favorites_form.cleaned_data.get('workouttype')
                reststrokes = favorites_form.cleaned_data.get('reststrokes')
                new_instances.append(FavoriteChart(user=r,
                                                   yparam1=yparam1,
                                                   yparam2=yparam2,
                                                   xparam=xparam,
                                                   plottype=plottype,
                                                   workouttype=workouttype,
                                                   reststrokes=reststrokes))
            try:
                with transaction.atomic():
                    FavoriteChart.objects.filter(user=r).delete()
                    FavoriteChart.objects.bulk_create(new_instances)
                    successmessage = "You have updated your favorites"
                    messages.info(request,message)
                    if len(new_instances)==0:
                        FavoriteChartFormSet=formset_factory(FavoriteForm,formset=BaseFavoriteFormSet,extra=1)
                        favorites_formset = FavoriteChartFormSet()
            except IntegrityError:
                message = "something went wrong"
                messages.error(request,message)

    else:
        favorites_formset = FavoriteChartFormSet(initial=favorites_data)
                

    context = {
        'favorites_formset':favorites_formset,
        'teams':get_my_teams(request.user),
        }

    
    
    return render(request,'favoritecharts.html',context)

# Page where user can set his details
# Add email address to form so user can change his email address
@login_required()
def rower_edit_view(request,message=""):
    r = getrower(request.user)
    if request.method == 'POST' and "ut2" in request.POST:
	form = RowerForm(request.POST)
	if form.is_valid():
	    # something
	    cd = form.cleaned_data
	    hrmax = cd['max']
	    ut2 = cd['ut2']
	    ut1 = cd['ut1']
	    at = cd['at']
	    tr = cd['tr']
	    an = cd['an']
	    rest = cd['rest']
	    try:
		r = getrower(request.user)
		r.max = max(min(hrmax,250),10)
		r.ut2 = max(min(ut2,250),10)
		r.ut1 = max(min(ut1,250),10)
		r.at = max(min(at,250),10)
		r.tr = max(min(tr,250),10)
		r.an = max(min(an,250),10)
		r.rest = max(min(rest,250),10)
		r.save()
                successmessage = "Your Heart Rate data were changed"
                messages.info(request,successmessage)
	        form = RowerForm(instance=r)
	        powerform = RowerPowerForm(instance=r)
                powerzonesform = RowerPowerZonesForm(instance=r)
                accountform = AccountRowerForm(instance=r)
                userform = UserForm(instance=request.user)
                return render(request, 'rower_form.html',
			  {'form':form,
                           'powerzonesform':powerzonesform,
                           'teams':get_my_teams(request.user),
                           'powerform':powerform,
                           'rower':r,
                           'accountform':accountform,
                           'userform':userform,
                          })
	    except Rower.DoesNotExist:
		message = "Funny. This user doesn't exist."
                messages.error(request,message)
		url = reverse(workouts_view)
		response = HttpResponseRedirect(url)
	else:
	    message = HttpResponse("invalid form")
	    #form = RowerForm(instance=r)
	    powerform = RowerPowerForm(instance=r)
            powerzonesform = RowerPowerZonesForm(instance=r)
            userform = UserForm(instance=request.user)
            accountform = AccountRowerForm(instance=r)
	    return render(request, 'rower_form.html',
			  {'form':form,
                           'teams':get_my_teams(request.user),
                           'powerzonesform':powerzonesform,
                           'userform':userform,
                           'accountform':accountform,
                           'powerform':powerform,
                           'rower':r,
                          })

			  

	return response
    elif request.method == 'POST' and "ftp" in request.POST:
	powerform = RowerPowerForm(request.POST)
	if powerform.is_valid():
	    cd = powerform.cleaned_data
	    ftp = cd['ftp']
            otwslack = cd['otwslack']
	    try:
		r = getrower(request.user)
                powerfrac = 100*np.array([r.pw_ut2,
                                          r.pw_ut1,
                                          r.pw_at,
                                          r.pw_tr,r.pw_an])/r.ftp
		r.ftp = max(min(ftp,650),50)
                r.otwslack = max(min(otwslack,50),0)
                ut2,ut1,at,tr,an = (r.ftp*powerfrac/100.).astype(int)
                r.pw_ut2 = ut2
                r.pw_ut1 = ut1
                r.pw_at = at
                r.pw_tr = tr
                r.pw_an = an
		r.save()
		message = "FTP and/or OTW slack values changed."
                messages.info(request,message)
		url = reverse(rower_edit_view)
		response = HttpResponseRedirect(url)
	    except Rower.DoesNotExist:
		message = "Funny. This user doesn't exist."
                messages.error(request,message)
		url = reverse(rower_edit_view)
		response = HttpResponseRedirect(url)	    
	else:
	    message = HttpResponse("invalid form")
	    form = RowerForm(instance=r)
	    #powerform = RowerPowerForm(instance=r)
            powerzonesform = RowerPowerZonesForm(instance=r)
            userform = UserForm(instance=request.user)
            accountform = AccountRowerForm(instance=r)
	    return render(request, 'rower_form.html',
			  {'form':form,
                           'teams':get_my_teams(request.user),
			   'powerform':powerform,
                           'rower':r,
                           'userform':userform,
                           'accountform':accountform,
			   })
			  
	    
	return response
    elif request.method == 'POST' and "ut3name" in request.POST:
	powerzonesform = RowerPowerZonesForm(request.POST)
	if powerzonesform.is_valid():
	    cd = powerzonesform.cleaned_data
            pw_ut2 = cd['pw_ut2']
            pw_ut1 = cd['pw_ut1']
            pw_at = cd['pw_at']
            pw_tr = cd['pw_tr']
            pw_an = cd['pw_an']
            ut3name = cd['ut3name']
            ut2name = cd['ut2name']
            ut1name = cd['ut1name']
            atname = cd['atname']
            trname = cd['trname']
            anname = cd['anname']
            powerzones = [ut3name,ut2name,ut1name,atname,trname,anname]
            try:
                r = getrower(request.user)
                r.pw_ut2 = pw_ut2
                r.pw_ut1 = pw_ut1
                r.pw_at = pw_at
                r.pw_tr = pw_tr
                r.pw_an = pw_an
                r.powerzones = powerzones
                r.save()
                successmessage = "Your Power Zone data were changed"
                messages.info(request,successmessage)
	        form = RowerForm(instance=r)
                accountform = AccountRowerForm(instance=r)
                userform = UserForm(instance=request.user)
	        powerform = RowerPowerForm(instance=r)
                powerzonesform = RowerPowerZonesForm(instance=r)
                return render(request, 'rower_form.html',
			  {'form':form,
                           'teams':get_my_teams(request.user),
                           'powerzonesform':powerzonesform,
                           'powerform':powerform,
                           'userform':userform,
                           'accountform':accountform,
                           'rower':r,
                          })
            except Rower.DoesNotExist:
		message = "Funny. This user doesn't exist."
                messages.error(request,message)
		url = reverse(workouts_view)
		response = HttpResponseRedirect(url)
            return response
        else:
	    form = RowerForm(instance=r)
	    powerform = RowerPowerForm(instance=r)
            accountform = AccountRowerForm(instance=r)
            userform = UserForm(instance=request.user)
            #powerzonesform = RowerPowerZonesForm(instance=r)
	    message = HttpResponse("invalid form")
	    return render(request, 'rower_form.html',
		          {'form':form,
                           'teams':get_my_teams(request.user),
		           'powerform':powerform,
                           'powerzonesform':powerzonesform,
                           'accountform':accountform,
                           'userform':userform,
                           'rower':r,
		          })
    elif request.method == 'POST' and "weightcategory" in request.POST:
        accountform = AccountRowerForm(request.POST)
        userform = UserForm(request.POST)
        if accountform.is_valid() and userform.is_valid():
            # process
            cd = accountform.cleaned_data
            ucd = userform.cleaned_data
            first_name = ucd['first_name']
            last_name = ucd['last_name']
            email = ucd['email']
            weightcategory = cd['weightcategory']
            getemailnotifications = cd['getemailnotifications']
            u = request.user
            if len(first_name):
                u.first_name = first_name
            u.last_name = last_name
            if len(email):
                u.email = email
            u.save()
            r = getrower(u)
            r.weightcategory = weightcategory
            r.getemailnotifications = getemailnotifications
            r.save()
            form = RowerForm(instance=r)
	    powerform = RowerPowerForm(instance=r)
            powerzonesform = RowerPowerZonesForm(instance=r)
            accountform = AccountRowerForm(instance=r)
            userform = UserForm(instance=u)
            successmessage = 'Account Information changed'
            messages.info(request,successmessage)
            return render(request, 'rower_form.html',
			  {'form':form,
                           'teams':get_my_teams(request.user),
                           'powerzonesform':powerzonesform,
                           'powerform':powerform,
                           'accountform':accountform,
                           'userform':userform,
                           'rower':r,
                          })
        else:
            form = RowerForm(instance=r)
	    powerform = RowerPowerForm(instance=r)
            powerzonesform = RowerPowerZonesForm(instance=r)
            return render(request, 'rower_form.html',
			  {'form':form,
                           'teams':get_my_teams(request.user),
                           'powerzonesform':powerzonesform,
                           'powerform':powerform,
                           'accountform':accountform,
                           'userform':userform,
                           'rower':r,
                          })
        
	    
    else:
	try:
	    r = getrower(request.user)
            
	    form = RowerForm(instance=r)
	    powerform = RowerPowerForm(instance=r)
            powerzonesform = RowerPowerZonesForm(instance=r)
            accountform = AccountRowerForm(instance=r)
            userform = UserForm(instance=request.user)
            grants = AccessToken.objects.filter(user=request.user)
	    return render(request, 'rower_form.html',
			  {
			      'form':form,
                              'teams':get_my_teams(request.user),
			      'powerform':powerform,
                              'powerzonesform':powerzonesform,
                              'userform':userform,
                              'accountform':accountform,
                              'grants':grants,
                              'rower':r,
			      })
	except Rower.DoesNotExist:
	    raise Http404("This user doesn't exist")

# Revoke an app that you granted access through the API.
# this views is called when you press a button on the User edit page
# the button is only there when you have granted access to an app
@login_required()
def rower_revokeapp_view(request,id=0):
    try:
        tokens = AccessToken.objects.filter(user=request.user,application=id)
        refreshtokens = AccessToken.objects.filter(user=request.user,application=id)
        for token in tokens:
            token.revoke()
        for token in refreshtokens:
            token.revoke()

        r = getrower(request.user)
        form = RowerForm(instance=r)
        powerform = RowerPowerForm(instance=r)
        grants = AccessToken.objects.filter(user=request.user)
        return render(request, 'rower_form.html',
		      {
		          'form':form,
                          'teams':get_my_teams(request.user),
		          'powerform':powerform,
                          'grants':grants,
                      })
    except AccessToken.DoesNotExist:
        raise Http404("Access token doesn't exist")


# Utility to get stroke data in a JSON response
class JSONResponse(HttpResponse):
    def __init__(self, data, **kwargs):
        content = JSONRenderer().render(data)
        kwargs['content_type'] = 'application/json'
        super(JSONResponse, self).__init__(content, **kwargs)

# Creates unix time stamp from a datetime object
def totimestamp(dt, epoch=datetime.datetime(1970,1,1,tzinfo=tz('UTC'))):
    td = dt - epoch
    # return td.total_seconds()
    return (td.microseconds + (td.seconds + td.days * 86400) * 10**6) / 10**6
# Check if a column of a dataframe has the required (aantal)
# number of elements. Also checks if the column is a numerical type
# Replaces any faulty columns with zeros
def trydf(df,aantal,column):
    try:
        s = df[column]
        if len(s) != aantal:
            return np.zeros(aantal)
        if not np.issubdtype(s,np.number):
            return np.zeros(aantal)
    except KeyError:
        s = np.zeros(aantal)

    return s

# Stroke data form to test API upload
@login_required()
def strokedataform(request,id=0):
    if request.method == 'GET':
        form = StrokeDataForm()
        return render(request, 'strokedata_form.html',
		      {
		          'form':form,
                          'teams':get_my_teams(request.user),
                          'id':int(id),
		      })
    elif request.method == 'POST':
        form = StrokeDataForm()

    return render(request, 'strokedata_form.html',
		  {
		      'form':form,
                      'teams':get_my_teams(request.user),
                      'id':int(id),
		  })

# Process the POSTed stroke data according to the API definition
# Return the GET stroke data according to the API definition
from rest_framework_swagger.renderers import OpenAPIRenderer, SwaggerUIRenderer
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
@login_required()
@api_view(['GET','POST'])
def strokedatajson(request,id):
    """
    POST: Add Stroke data to workout
    GET: Get stroke data of workout
    """
    try:
	row = Workout.objects.get(id=id)
	if (checkworkoutuser(request.user,row)==False):
	    return HttpResponseForbidden("Permission error")
    except Workout.DoesNotExist:
	raise Http404("Workout doesn't exist")
    try:
        id = int(id)
    except ValueError:
        return HttpResponse("Not a valid workout number",status=400)


    if request.method == 'GET':
        # currently only returns a subset. 
        columns = ['spm','time','hr','pace','power','distance']
        datadf = dataprep.getsmallrowdata_db(columns,ids=[id])
        with open('media/apilog.log','a') as logfile:
            logfile.write(str(timezone.now())+": ")
            logfile.write(request.user.username+"(GET) \n")
        return JSONResponse(datadf)

    if request.method == 'POST':
        checkdata,r = dataprep.getrowdata_db(id=row.id)
        if not checkdata.empty:
            return HttpResponse("Duplicate Error",409)
        # strokedata = request.POST['strokedata']
        # checking/validating and cleaning
        try:
            strokedata = json.loads(request.POST['strokedata'])
        except:
            return HttpResponse("No JSON object could be decoded",400)

        df = pd.DataFrame(strokedata)
        df.index = df.index.astype(int)
        df.sort_index(inplace=True)
        # time, hr, pace, spm, power, drivelength, distance, drivespeed, dragfactor, strokerecoverytime, averagedriveforce, peakdriveforce, lapidx
        time = df['time']/1.e3
        aantal = len(time)
        pace = df['pace']/1.e3
        if len(pace) != aantal:
            return HttpResponse("Pace array has incorrect length",status=400)
        distance = df['distance']
        if len(distance) != aantal:
            return HttpResponse("Distance array has incorrect length",status=400)
        
        spm = df['spm']
        if len(spm) != aantal:
            return HttpResponse("SPM array has incorrect length",status=400)

        res = dataprep.testdata(time,distance,pace,spm)
        if not res:
            return HttpResponse("Data are not numerical",status=400)
            
        power = trydf(df,aantal,'power')
        drivelength = trydf(df,aantal,'drivelength')
        drivespeed = trydf(df,aantal,'drivespeed')
        dragfactor = trydf(df,aantal,'dragfactor')
        drivetime = trydf(df,aantal,'drivetime')
        strokerecoverytime = trydf(df,aantal,'strokerecoverytime')
        averagedriveforce = trydf(df,aantal,'averagedriveforce')
        peakdriveforce = trydf(df,aantal,'peakdriveforce')
        lapidx = trydf(df,aantal,'lapidx')
        hr = trydf(df,aantal,'hr')

        starttime = totimestamp(row.startdatetime)+time
        unixtime = starttime+time

        with open('media/apilog.log','a') as logfile:
            logfile.write(starttime+": ")
            logfile.write(request.user.username+"(POST) \r\n")
            
        data = pd.DataFrame({'TimeStamp (sec)':unixtime,
			     ' Horizontal (meters)': distance,
			     ' Cadence (stokes/min)':spm,
			     ' HRCur (bpm)':hr,
			     ' DragFactor':dragfactor,
			     ' Stroke500mPace (sec/500m)':pace,
			     ' Power (watts)':power,
			     ' DriveLength (meters)':drivelength,
			     ' DriveTime (ms)':drivetime,
			     ' StrokeRecoveryTime (ms)':strokerecoverytime,
			     ' AverageDriveForce (lbs)':averagedriveforce,
			     ' PeakDriveForce (lbs)':peakdriveforce,
			     ' lapIdx':lapidx,
			     ' ElapsedTime (sec)':time,
	})

        # Following part should be replaced with dataprep.new_workout_from_df
            
        timestr = row.startdatetime.strftime("%Y%m%d-%H%M%S")
        csvfilename ='media/Import_'+timestr+'.csv'
        
        res =  data.to_csv(csvfilename+'.gz',index_label='index',
                           compression='gzip')
        row.csvfilename = csvfilename
        row.save()

	r = getrower(request.user)
        powerperc = 100*np.array([r.pw_ut2,
                                  r.pw_ut1,
                                  r.pw_at,
                                  r.pw_tr,r.pw_an])/r.ftp

        ftp = float(r.ftp)
        if row.workouttype in ('water','coastal'):
            ftp = ftp*(100.-r.otwslack)/100.
            
        rr = rrower(hrmax=r.max,hrut2=r.ut2,
		    hrut1=r.ut1,hrat=r.at,
		    hrtr=r.tr,hran=r.an,ftp=ftp,
                    powerperc=powerperc,powerzones=r.powerzones)
        rowdata = rdata(row.csvfilename,rower=rr).df
        
        datadf = dataprep.dataprep(rowdata,id=row.id,bands=True,barchart=True,otwpower=True,empower=True)    
        # mangling

        #
        return HttpResponse(row.id,status=201)

    #Method not supported
    return HttpResponseNotAllowed("Method not supported")


# Teams related views
import teams

@login_required()
def team_view(request,id=0):
    ismember = 0
    hasrequested = 0
    r = getrower(request.user)
    myteams = Team.objects.filter(manager=request.user)
    
    try:
        t = Team.objects.get(id=id)
    except Team.DoesNotExist:
        raise Http404("Team doesn't exist")

    
    if request.method == 'POST' and request.user == t.manager:
        inviteform = TeamInviteForm(request.POST)
        inviteform.fields['user'].queryset = User.objects.filter(rower__isnull=False,rower__team__in=myteams).distinct().exclude(rower__team__name=t.name)
        if inviteform.is_valid():
            cd = inviteform.cleaned_data
            newmember = cd['user']
            email = cd['email']
            inviteid,text = teams.create_invite(t,t.manager,
                                                   user=newmember,
                                                   email=email)
            if inviteid:
                teams.send_invite_email(inviteid)
                successmessage = text
                messages.info(request,successmessage)
            else:
                message = text
                messages.error(request,message)
                
    elif request.user == t.manager:
        inviteform = TeamInviteForm()
        inviteform.fields['user'].queryset = User.objects.filter(rower__isnull=False,rower__team__in=myteams).distinct().exclude(rower__team__name=t.name)
    else:
        inviteform = ''
        
    members = Rower.objects.filter(team=t).order_by('user__last_name','user__first_name')
    thisteammyrequests = TeamRequest.objects.filter(team=t,user=request.user)
    if len(thisteammyrequests):
        hasrequested = 1

    if r in members:
        ismember = 1



    return render(request, 'team.html',
                  {
                      'team':t,
                      'teams':get_my_teams(request.user),
                      'members':members,
                      'inviteform':inviteform,
                      'ismember':ismember,
                      'hasrequested':hasrequested,
                      })

@login_required()
def team_leaveconfirm_view(request,id=0):
    try:
        t = Team.objects.get(id=id)
    except Team.DoesNotExist:
        raise Http404("Team doesn't exist")

    return render(request,'teamleaveconfirm.html',
                  {
                      'team':t,
                      'teams':get_my_teams(request.user),
                      })

@login_required()
def team_leave_view(request,id=0):
    r = getrower(request.user)
    teams.remove_member(id,r)
                            
    url = reverse(rower_teams_view)
    response = HttpResponseRedirect(url)
    return response

from rowers.forms import TeamInviteCodeForm

@login_required()
def rower_teams_view(request,message='',successmessage=''):
    if request.method == 'POST':
        form = TeamInviteCodeForm(request.POST)
        if form.is_valid():
            code = form.cleaned_data['code']
            res,text = teams.process_invite_code(request.user,code)
            if res:
                successmessage = text
            else:
                message = text
    else:
        form = TeamInviteCodeForm()
            
    r = getrower(request.user)
    ts = Team.objects.filter(rower=r)
    myteams = Team.objects.filter(manager=request.user)
    otherteams = Team.objects.filter(private='open').exclude(rower=r).exclude(manager=request.user).order_by('name')
    teams.remove_expired_invites()

    invites = TeamInvite.objects.filter(user=request.user)
    requests = TeamRequest.objects.filter(user=request.user)
    myrequests = TeamRequest.objects.filter(team__in=myteams)
    myinvites = TeamInvite.objects.filter(team__in=myteams)
    clubsize = teams.count_invites(request.user)+teams.count_club_members(request.user)
    max_clubsize = r.clubsize

    messages.info(request,successmessage)
    messages.error(request,message)
    return render(request, 'teams.html',
		  {
                      'teams':ts,
                      'clubsize':clubsize,
                      'max_clubsize':max_clubsize,
                      'myteams':myteams,
                      'invites':invites,
                      'otherteams':otherteams,
                      'requests':requests,
                      'myrequests':myrequests,
                      'form':form,
                      'myinvites':myinvites,
		  })

@user_passes_test(iscoachmember,login_url="/",redirect_field_name=None)
def invitation_revoke_view(request,id):
    res,text = teams.revoke_invite(request.user,id)
    if res:
        messages.info(request,text)
        successmessage = text
    else:
        message = text
        messages.error(request,text)

    url = reverse(rower_teams_view)

    return HttpResponseRedirect(url)

@user_passes_test(iscoachmember,login_url="/",redirect_field_name=None)
def manager_member_drop_view(request,teamid,userid,
                             message='',successmessage=''):
    rower = Rower.objects.get(user__id=userid)
    res, text = teams.mgr_remove_member(teamid,request.user,rower)
    if res:
        messages.info(request,text)
    else:
        messages.error(request,text)
        
    url = reverse(rower_teams_view)

    return HttpResponseRedirect(url)

@user_passes_test(iscoachmember,login_url="/",redirect_field_name=None)
def manager_requests_view(request,code=None,message='',successmessage=''):
    if code:
        res,text = teams.process_request_code(request.user,code)
        if res:
            successmessage = text
            message = ''
        else:
            message = text
            successmessage = ''

    messages.info(request,successmessage)
    messages.error(request,message)
    url = reverse(rower_teams_view,kwargs={
    })
    return HttpResponseRedirect(url)


@login_required()
def team_requestmembership_view(request,teamid,userid):
    try:
        t = Team.objects.get(id=teamid)
    except Team.DoesNotExist:
        raise Http404("Team doesn't exist")
    
    res,text = teams.create_request(t,userid)
    if res:
        messages.info(request,text)
    else:
        messages.error(request,text)
        
    url = reverse(team_view,kwargs={
	'id':int(teamid),
        })


    return HttpResponseRedirect(url)

@login_required()
def request_revoke_view(request,id=0):
    res,text = teams.revoke_request(request.user,id)

    if res:
        messages.info(request,text)

    else:
        messages.error(request,text)

    url = reverse(rower_teams_view)

    return HttpResponseRedirect(url)

@user_passes_test(iscoachmember,login_url="/",redirect_field_name=None)
def request_reject_view(request,id=0):
    res,text = teams.reject_request(request.user,id)

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

    url = reverse(rower_teams_view)

    return HttpResponseRedirect(url)

@user_passes_test(iscoachmember,login_url="/",redirect_field_name=None)
def invitation_reject_view(request,id=0):
    res,text = teams.reject_invitation(request.user,id)

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

    url = reverse(rower_teams_view)

    return HttpResponseRedirect(url)

@login_required()
def rower_invitations_view(request,code=None,message='',successmessage=''):

    if code:
        teams.remove_expired_invites()
        res,text = teams.process_invite_code(request.user,code)
        if res:
            messages.info(request,text)
            teamid=res
            url = reverse(team_view,kwargs={
	        'id':teamid,
            })
        else:
            messages.error(request,text)

            url = reverse(rower_teams_view)

        return HttpResponseRedirect(url)

    url = reverse(rower_teams_view,kwargs={
    })
    return HttpResponseRedirect(url)
    
@user_passes_test(iscoachmember,login_url="/",redirect_field_name=None)
def team_edit_view(request,id=0):
    try:
        t = Team.objects.get(id=id)
    except Team.DoesNotExist:
        raise Http404("Team does not exist")
        
    if request.method == 'POST':
        teamcreateform = TeamForm(request.POST,instance=t)
        if teamcreateform.is_valid():
            cd = teamcreateform.cleaned_data
            name = cd['name']
            notes = cd['notes']
            manager = request.user
            private = cd['private']
            viewing = cd['viewing']
            res,message=teams.update_team(t,name,manager,private,notes,
                                          viewing)
            if res:
                messages.info(request,message)
            else:
                messages.error(request,message)

            url = reverse(team_view,
                          kwargs={
                              'id':int(id),
                          }
            )
                
            response = HttpResponseRedirect(url)
            return response

    else:
        teamcreateform = TeamForm(instance=t)

    return render(request,'teamedit.html',
                  {
                      'form':teamcreateform,
                      'teams':get_my_teams(request.user),
                      'team':t,
                      })

@user_passes_test(iscoachmember,login_url="/",redirect_field_name=None)
def team_create_view(request):
    if request.method == 'POST':
        teamcreateform = TeamForm(request.POST)
        if teamcreateform.is_valid():
            cd = teamcreateform.cleaned_data
            name = cd['name']
            notes = cd['notes']
            manager = request.user
            private = cd['private']
            viewing = cd['viewing']
            res,message=teams.create_team(name,manager,private,notes,
                                          viewing)
            url = reverse(rower_teams_view)
            response = HttpResponseRedirect(url)
            return response

    else:
        teamcreateform = TeamForm()

    return render(request,'teamcreate.html',
                  {
                      'teams':get_my_teams(request.user),
                      'form':teamcreateform,
                      })

@user_passes_test(iscoachmember,login_url="/",redirect_field_name=None)
def team_deleteconfirm_view(request,id):
    r = getrower(request.user)
    try:
        t = Team.objects.get(id=id)
    except Team.DoesNotExist:
        raise Http404("This team doesn't exist")
    if t.manager != request.user:
        raise PermissionDenied("You are not allowed to delete this team")

    return render(request,'teamdeleteconfirm.html',
                  {
                      'teams':get_my_teams(request.user),
                      'team':t
                  })

@user_passes_test(iscoachmember,login_url="/",redirect_field_name=None)
def team_delete_view(request,id):
    r = getrower(request.user)
    try:
        t = Team.objects.get(id=id)
    except Team.DoesNotExist:
        raise Http404("This team doesn't exist")
    if t.manager != request.user:
        raise PermissionDenied("You are not allowed to delete this team")

    teams.remove_team(t.id)
    
    url = reverse(rower_teams_view)
    response = HttpResponseRedirect(url)
    return response

@user_passes_test(iscoachmember,login_url="/",redirect_field_name=None)
def team_members_stats_view(request,id):
    r = getrower(request.user)
    try:
        t = Team.objects.get(id=id)
    except Team.DoesNotExist:
        raise Http404("This team doesn't exist")
    if t.manager != request.user:
        raise PermissionDenied("You are not allowed to see this page")

    members = Rower.objects.filter(team=t).order_by("user__last_name","user__first_name")
    
    theusers = [member.user for member in members]

    
    
    response = render(request,'teamstats.html',
                  {
                      'teams':get_my_teams(request.user),
                      'team':t,
                      'theusers':theusers,
                  })

    return response
