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

""" Background tasks done by Celery (develop) or QR (production) """
import os
import time
import gc
import gzip
import shutil
import numpy as np
import re
import sys

from scipy import optimize
from scipy.signal import savgol_filter

import rowingdata

from rowingdata import rowingdata as rdata
from datetime import timedelta
from sqlalchemy import create_engine

#from celery import app
from rowers.celery import app
from celery import shared_task

import datetime
import pytz
import iso8601


from matplotlib.backends.backend_agg import FigureCanvas
#from matplotlib.backends.backend_cairo import FigureCanvasCairo as FigureCanvas
import matplotlib.pyplot as plt
from matplotlib import path

import grpc
import rowers.otw_power_calculator_pb2 as calculator_pb2
import rowers.otw_power_calculator_pb2_grpc as calculator_pb2_grpc
import rowers.rowing_workout_metrics_pb2 as metrics_pb2
import rowers.rowing_workout_metrics_pb2_grpc as metrics_pb2_grpc

from rowsandall_app.settings import SITE_URL
from rowsandall_app.settings_dev import SITE_URL as SITE_URL_DEV
from rowsandall_app.settings import PROGRESS_CACHE_SECRET
from rowsandall_app.settings import SETTINGS_NAME
from rowsandall_app.settings import workoutemailbox

import pandas as pd

from django_rq import job
from django.utils import timezone
from django.utils.html import strip_tags

from rowers.utils import deserialize_list,ewmovingaverage,wavg
from rowers.emails import htmlstrip

#from HTMLParser import HTMLParser
from html.parser import HTMLParser
class MLStripper(HTMLParser):
    def __init__(self):
        self.reset()
        self.fed = []
    def handle_data(self, d):
        self.fed.append(d)
    def get_data(self):
        return ''.join(self.fed)

def strip_tags(html):
    s = MLStripper()
    s.feed(html)
    return s.get_data()


from rowers.dataprepnodjango import (
    update_strokedata, new_workout_from_file,
    getsmallrowdata_db, updatecpdata_sql,update_c2id_sql,
    update_workout_field_sql,
    update_agegroup_db,fitnessmetric_to_sql,
    add_c2_stroke_data_db,totaltime_sec_to_string,
    create_c2_stroke_data_db,update_empower,
    database_url_debug,database_url,dataprep,
    #    create_strava_stroke_data_db
)

from rowers.opaque import encoder

from django.core.mail import (
    send_mail,
    EmailMessage,EmailMultiAlternatives,
)

from django.template import Context
from django.db.utils import OperationalError
from jinja2 import Template,Environment,FileSystemLoader
env = Environment(loader = FileSystemLoader(["rowers/templates"]))

import rowers.datautils as datautils
import rowers.utils as utils
import requests
import rowers.longtask as longtask
import arrow
import stravalib
from stravalib.exc import ActivityUploadFailed

from rowers.utils import get_strava_stream

def safetimedelta(x):
    try:
        return timedelta(seconds=x)
    except ValueError:
        return timedelta(seconds=0)

siteurl = SITE_URL

# testing task

from rowers.emails import send_template_email
from rowers.courseutils import coursetime_paths, coursetime_first, time_in_path

@app.task
def add(x, y):
    return x + y


@app.task
def handle_c2_sync(workoutid,url,headers,data,debug=False,**kwargs):
    response = requests.post(url,headers=headers,data=data)
    if response.status_code not in [200,201]:
        return 0

    s = response.json()
    c2id = s['data']['id']

    res = update_workout_field_sql(workoutid,'uploadedtoc2',c2id,debug=debug)

    return res

@app.task
def handle_sporttracks_sync(workoutid,url,headers,data,debug=False,**kwargs):
    response = requests.post(url,headers=headers,data=data)
    if response.status_code not in [200,201]:
        return 0

    t = response.json()
    uri = t['uris'][0]
    regex = '.*?sporttracks\.mobi\/api\/v2\/fitnessActivities/(\d+)\.json$'
    m = re.compile(regex).match(uri).group(1)

    id = int(m)

    res = update_workout_field_sql(workoutid,'uploadedtosporttracks',id,debug=debug)

app.task
def handle_runkeeper_sync(workoutid,url,headers,data,debug=False,**kwargs):
    response = requests.post(url,headers=headers,data=data)
    if response.status_code not in [200,201]:
        return 0

    t = response.json()
    uri = t['uris'][0]
    regex = '.*?sporttracks\.mobi\/api\/v2\/fitnessActivities/(\d+)\.json$'
    m = re.compile(regex).match(uri).group(1)

    id = int(m)

    res = update_workout_field_sql(workoutid,'uploadedtorunkeeper',id,debug=debug)



@app.task
def handle_strava_sync(stravatoken,workoutid,filename,name,activity_type,description,debug=False,**kwargs):
    client = stravalib.Client(access_token=stravatoken)
    failed = False
    with open(filename,'rb') as f:
        act = client.upload_activity(f,'tcx.gz',name=name)
        try:
            res = act.wait(poll_interval=5.0, timeout=60)
        except ActivityUploadFailed:
            failed = True
        except JSONDecodeError:
            failed = True
    if not failed:
        try:
            act = client.update_activity(res.id,activity_type=activity_type,
                                        description=description,device_name='Rowsandall.com')
        except TypeError:
            act = client.update_activity(res.id,activity_type=activity_type,
                                        description=description)
        except:
            e = sys.exc_info()[0]
            t = time.localtime()
            timestamp = time.strftime('%b-%d-%Y_%H%M', t)
            with open('stravalog.log','a') as f:
                f.write('\n')
                f.write(timestamp)
                f.write(str(e))

        result = update_workout_field_sql(workoutid,'uploadedtostrava',res.id,debug=debug)
    try:
        os.remove(filename)
    except WindowsError:
        pass

    return 1

@app.task
def handle_c2_import_stroke_data(c2token,
                                 c2id,workoutid,
                                 starttimeunix,
                                 csvfilename,debug=True,**kwargs):

    if 'workouttype' in kwargs:
        workouttype = kwargs['workouttype']
    else:
        workouttype = 'rower'

    authorizationstring = str('Bearer ' + c2token)
    headers = {'Authorization': authorizationstring,
           'user-agent': 'sanderroosendaal',
           'Content-Type': 'application/json'}
    url = "https://log.concept2.com/api/users/me/results/"+str(c2id)+"/strokes"
    s = requests.get(url,headers=headers)
    if s.status_code == 200:
        strokedata = pd.DataFrame.from_dict(s.json()['data'])
        result = add_c2_stroke_data_db(
            strokedata,workoutid,starttimeunix,
            csvfilename,debug=debug,workouttype=workouttype
        )

        return 1
    else:
        url = "https://log.concept2.com/api/users/me/results/{id}".format(id=c2id)

        s = requests.get(url,headers=headers)

        if s.status_code == 200:
            workoutdata = s.json()['data']
            distance = workoutdata['distance']
            c2id = workoutdata['id']
            workouttype = workoutdata['type']
            verified = workoutdata['verified']
            startdatetime = iso8601.parse_date(workoutdata['date'])
            weightclass = workoutdata['weight_class']
            weightcategory = 'hwt'
            if weightclass == "L":
                weightcategory = 'lwt'
            totaltime = workoutdata['time']/10.
            duration = totaltime_sec_to_string(totaltime)
            duration = datetime.datetime.strptime(duration,'%H:%M:%S.%f').time()

            try:
                timezone_str = tz(workoutdata['timezone'])
            except:
                timezone_str = 'UTC'

            workoutdate = startdatetime.astimezone(
                pytz.timezone(timezone_str)
            ).strftime('%Y-%m-%d')
            starttime = startdatetime.astimezone(
                pytz.timezone(timezone_str)
            ).strftime('%H:%M:%S')

            result = create_c2_stroke_data_db(
                distance,duration,workouttype,
                workoutid,starttimeunix,
                csvfilename,debug=debug,
            )


            return 1

        return 0

    return 0

def getagegrouprecord(age,sex='male',weightcategory='hwt',
                      distance=2000,duration=None,indf=pd.DataFrame()):

    if not duration:
        try:
            df = indf[indf['distance'] == distance]
        except KeyError:
            df = pd.DataFrame()
    else:
        duration = 60*int(duration)
        df = indf[indf['duration'] == duration]

    if not df.empty:
        ages = df['age']
        powers = df['power']

        #poly_coefficients = np.polyfit(ages,powers,6)
        fitfunc = lambda pars, x: np.abs(pars[0])*(1-x/max(120,pars[1]))-np.abs(pars[2])*np.exp(-x/np.abs(pars[3]))+np.abs(pars[4])*(np.sin(np.pi*x/max(50,pars[5])))
        errfunc = lambda pars, x,y: fitfunc(pars,x)-y

        p0 = [700,120,700,10,100,100]

        p1, success = optimize.leastsq(errfunc,p0[:],
                                       args = (ages,powers))

        if success:
            power = fitfunc(p1, float(age))

            #power = np.polyval(poly_coefficients,age)

            power = 0.5*(np.abs(power)+power)
        else:
            power = 0
    else:
        power = 0

    return power

def polygon_to_path(polygon,debug=True):
    pid = polygon[0]
    query = "SELECT id, latitude, longitude FROM rowers_geopoint WHERE polygon_id = {pid} ORDER BY order_in_poly ASC".format(
        pid=pid
        )
    if debug:
        engine = create_engine(database_url_debug, echo=False)
    else:
        engine = create_engine(database_url, echo=False)
    with engine.connect() as conn, conn.begin():
        result = conn.execute(query)
        points = result.fetchall()

    conn.close()
    engine.dispose()
    s = []

    for point in points:
        s.append([point[1],point[2]])

    p = path.Path(s[:-1])

    return p

@app.task(bind=True)
def handle_check_race_course(self,
                             f1,workoutid,courseid,
                             recordid,**kwargs):

    if 'debug' in kwargs:
        debug = kwargs['debug']
    else:
        debug = False

    if 'splitsecond' in kwargs:
        splitsecond = kwargs['splitsecond']
    else:
        splitsecond = 0

    if 'referencespeed' in kwargs:
        referencespeed = kwargs['referencespeed']
    else:
        referencespeed = 5.0

    if 'coursedistance' in kwargs:
        coursedistance = kwargs['coursedistance']
    else:
        coursedistance = 0

    mode = 'race'
    if 'mode' in kwargs:
        mode = kwargs['mode']

    columns = ['time',' latitude',' longitude','cum_dist']

    try:
        row = rdata(csvfile=f1)
    except IOError:
        try:
            row = rdata(csvfile=f1 + '.csv')
        except IOError:
            try:
                row = rdata(csvfile=f1 + '.gz')
            except IOError:
                return 0


    rowdata = row.df

    try:
        s = rowdata[' latitude']
    except KeyError:
        return 0

    rowdata.rename(columns = {
        ' latitude':'latitude',
        ' longitude':'longitude',
        'TimeStamp (sec)': 'time',
        }, inplace=True)

    rowdata.fillna(method='backfill',inplace=True)

    rowdata['time'] = rowdata['time']-rowdata.ix[0,'time']
    rowdata = rowdata[rowdata['time']>splitsecond]
    # we may want to expand the time (interpolate)
    rowdata['dt'] = rowdata['time'].apply(
        lambda x: safetimedelta(x)
        )
    rowdata = rowdata.resample('100ms',on='dt').mean()
    rowdata = rowdata.interpolate()

    # initiate database engine

    if debug:
        engine = create_engine(database_url_debug, echo=False)
    else:
        engine = create_engine(database_url, echo=False)

    # get polygons
    query = "SELECT id FROM rowers_geopolygon WHERE course_id = {courseid} ORDER BY order_in_course ASC".format(
        courseid=courseid
        )

    with engine.connect() as conn, conn.begin():
        result = conn.execute(query)
        polygons = result.fetchall()

    conn.close()
    engine.dispose()

    paths = []
    for polygon in polygons:
        path = polygon_to_path(polygon,debug=debug)
        paths.append(path)

    # check how many times went through start polygon
    entrytimes,entrydistances = time_in_path(rowdata,paths[0],maxmin='max',getall=True)

    cseconds = []
    cmeters = []
    ccomplete = []
    startseconds = []
    endseconds = []

    for startt in entrytimes:

        rowdata2 = rowdata[rowdata['time']>(startt-10.)]

        (
            coursetimeseconds,
            coursemeters,
            coursecompleted,

        ) = coursetime_paths(rowdata2,paths)
        (
            coursetimefirst,
            coursemetersfirst,
            firstcompleted
        ) = coursetime_first(
            rowdata2,paths)



        coursetimesecondsnet = coursetimeseconds-coursetimefirst
        coursemeters = coursemeters-coursemetersfirst


        cseconds.append(coursetimesecondsnet)
        cmeters.append(coursemeters)
        ccomplete.append(coursecompleted)
        endseconds.append(coursetimeseconds)
        startseconds.append(coursetimefirst)


    records = pd.DataFrame({
        'coursetimeseconds':cseconds,
        'coursecompleted': ccomplete,
        'coursemeters': cmeters,
        'startsecond':startseconds,
        'endsecond':endseconds,
        })

    records = records[records['coursecompleted'] == True]


    if len(records):
        coursecompleted = True
        mintime = records['coursetimeseconds'].min()
        coursetimeseconds = records[records['coursetimeseconds'] == mintime]['coursetimeseconds'].min()
        coursemeters = records[records['coursetimeseconds'] == mintime]['coursemeters'].min()
        startsecond = records[records['coursetimeseconds'] == mintime]['startsecond'].min()
        endsecond = records[records['coursetimeseconds'] == mintime]['endsecond'].min()
    else:
        coursecompleted = False

    points = 0
    if coursecompleted:
        if coursedistance == 0:
            coursedistance = coursemeters
        velo = coursedistance/coursetimeseconds
        points = int(100*(2.-referencespeed/velo))
        query = 'UPDATE rowers_virtualraceresult SET coursecompleted = 1, duration = "{duration}", distance = {distance}, workoutid = {workoutid}, startsecond = {startsecond}, endsecond = {endsecond}, points={points} WHERE id={recordid}'.format(
            recordid=recordid,
            duration=totaltime_sec_to_string(coursetimeseconds),
            distance=int(coursemeters),
            points=points,
            workoutid=workoutid,
            startsecond=startsecond,
            endsecond=endsecond,
            )

        if mode == 'coursetest':
            query = 'UPDATE rowers_coursetestresult SET coursecompleted = 1, duration = "{duration}", distance = {distance}, workoutid = {workoutid}, startsecond = {startsecond}, endsecond = {endsecond}, points={points} WHERE id={recordid}'.format(
                recordid=recordid,
                duration=totaltime_sec_to_string(coursetimeseconds),
                distance=int(coursemeters),
                points=points,
                workoutid=workoutid,
                startsecond=startsecond,
                endsecond=endsecond,
            )


        with engine.connect() as conn, conn.begin():
            result = conn.execute(query)

        conn.close()
        engine.dispose()

        return 1

    else:
        return 2

    return 0


@app.task(bind=True)
def handle_getagegrouprecords(self,
                              df,
                              distances,durations,
                              age,sex,weightcategory,
                              **kwargs):
    wcdurations = []
    wcpower = []

    if 'debug' in kwargs:
        debug = kwargs['debug']
    else:
        debug = False


    df = pd.read_json(df)

    if sex == 'not specified':
        return 0

    for distance in distances:
        worldclasspower = getagegrouprecord(
            age,
            sex=sex,
            distance=distance,
            weightcategory=weightcategory,indf=df,
        )
        velo = (worldclasspower/2.8)**(1./3.)
        if not np.isinf(worldclasspower) and not np.isnan(worldclasspower):
            try:
                duration = distance/velo
                wcdurations.append(duration)
                wcpower.append(worldclasspower)
            except ZeroDivisionError:
                pass



    for duration in durations:
        worldclasspower = getagegrouprecord(
            age,
            sex=sex,
            duration=duration,
            weightcategory=weightcategory,indf=df
        )
        if not np.isinf(worldclasspower) and not np.isnan(worldclasspower):
            try:
                velo = (worldclasspower/2.8)**(1./3.)
                distance = int(60*duration*velo)
                wcdurations.append(60.*duration)
                wcpower.append(worldclasspower)
            except ValueError:
                pass

    update_agegroup_db(age,sex,weightcategory,wcdurations,wcpower,
                       debug=debug)

    return 1


@app.task(bind=True)
def long_test_task(self,aantal,debug=False,job=None,session_key=None):
    job = self.request

    return longtask.longtask(aantal,jobid=job.id,debug=debug,
                             session_key=session_key)

@app.task(bind=True)
def long_test_task2(self,aantal,**kwargs):
                    #debug=False,job=None,jobid='aap'):
    job = self.request
    job_id = job.id

    if 'jobkey' in kwargs:
        job_id = kwargs.pop('jobkey')

    kwargs['jobid'] = job_id

    return longtask.longtask2(aantal,**kwargs)




# create workout
@app.task
def handle_new_workout_from_file(r, f2,
                                 workouttype='rower',
                                 boattype='1x',
                                 makeprivate=False,
                                 notes='',debug=False):
    return new_workout_from_file(r, f2, workouttype,
                                 title, makeprivate, notes)

# process and update workouts

@app.task(bind=True)
def handle_update_empower(self,
                          useremail,
                          workoutdicts,
                          debug=False, **kwargs):

    job = self.request
    job_id = job.id

    if 'jobkey' in kwargs:
        job_id = kwargs.pop('jobkey')

    aantal = len(workoutdicts)
    counter = 0

    for workoutdict in workoutdicts:
        wid = workoutdict['id']
        inboard = workoutdict['inboard']
        oarlength = workoutdict['oarlength']
        boattype = workoutdict['boattype']
        f1 = workoutdict['filename']

        # oarlength consistency checks will be done in view

        havedata = 1
        try:
            rowdata = rdata(csvfile=f1)
        except IOError:
            try:
                rowdata = rdata(csvfile=f1 + '.csv')
            except IOError:
                try:
                    rowdata = rdata(csvfile=f1 + '.gz')
                except IOError:
                    havedata = 0

        progressurl = SITE_URL
        siteurl = SITE_URL
        if debug:
            progressurl = SITE_URL_DEV
            siteurl = SITE_URL_DEV
        secret = PROGRESS_CACHE_SECRET

        kwargs['job_id'] = job_id

        progressurl += "/rowers/record-progress/"
        progressurl += job_id

        if havedata:
            success = update_empower(wid, inboard, oarlength, boattype,
                                     rowdata.df, f1, debug=debug)

        counter += 1

        progress = 100.*float(counter)/float(aantal)

        post_data = {
            "secret":secret,
            "value":progress,
            }

        s = requests.post(progressurl, data=post_data)
        status_code = s.status_code

    subject = "Rowsandall.com Your Old Empower Oarlock data have been corrected"
    message = """
We have updated Power and Work per Stroke data according to the instructions by Nielsen-Kellerman.
"""

    email = EmailMessage(subject, message,
                         'Rowsandall <info@rowsandall.com>',
                         [useremail])

    if 'emailbounced' in kwargs:
        emailbounced = kwargs['emailbounced']
    else:
        emailbounced = False

    if not emailbounced:
        res = email.send()
    return 1

@app.task
def handle_calctrimp(id,
                     csvfilename,
                     ftp,
                     sex,
                     hrftp,
                     hrmax,
                     hrmin,
                     debug=False, **kwargs):
    if debug:
        engine = create_engine(database_url_debug, echo=False)
    else:
        engine = create_engine(database_url, echo=False)

    tss = 0
    normp = 0
    trimp = 0
    hrtss = 0
    normv = 0
    normw = 0

    # check what the real file name is
    if os.path.exists(csvfilename):
        csvfile = csvfilename
    elif os.path.exists(csvfilename+'.csv'):
        csvfile = csvfilename+'.csv'
    elif os.path.exists(csvfilename+'.gz'):
        csvfile = csvfilename+'.gz'
    else:
        return 0

    csvfile = os.path.abspath(csvfile)

    with grpc.insecure_channel(
        target='localhost:50052',
        options=[('grpc.lb_policy_name', 'pick_first'),
                 ('grpc.enable_retries', 0), ('grpc.keepalive_timeout_ms',
                                              10000)]
        ) as channel:
        try:
            grpc.channel_ready_future(channel).result(timeout=10)
        except grpc.FutureTimeoutError:
            return 0

        stub = metrics_pb2_grpc.MetricsStub(channel)
        req = metrics_pb2.WorkoutMetricsRequest(
            filename = csvfile,
            ftp=ftp,
            sex=sex,
            hrftp=hrftp,
            hrmax=hrmax,
            hrmin=hrmin,
        )
        response = stub.CalcMetrics(req,timeout=60)

        tss = response.tss
        normp = response.normp
        trimp = response.trimp
        normv = response.normv
        normw = response.normw
        hrtss = response.hrtss

        if np.isnan(tss):
            tss = 0

        if np.isnan(normp):
            normp = 0

        if np.isnan(trimp):
            trimp = 0

        if np.isnan(normv):
            normv = 0

        if np.isnan(normw):
            normw = 0

        if np.isnan(hrtss):
            hrtss = 0

        if tss > 1000:
            tss = 0

        if trimp > 1000:
            trimp = 0

        if normp > 2000:
            normp = 0

        if normv > 2000:
            normv = 0

        if normw > 10000:
            normw = 0

        if hrtss > 1000:
            hrtss = 0


    query = 'UPDATE rowers_workout SET rscore = {tss}, normp = {normp}, trimp={trimp}, hrtss={hrtss}, normv={normv}, normw={normw} WHERE id={id}'.format(
        tss = int(tss),
        normp = int(normp),
        trimp = int(trimp),
        hrtss = int(hrtss),
        normv=normv,
        normw=normw,
        id = id,
        )

    with engine.connect() as conn, conn.begin():
        result = conn.execute(query)
    conn.close()
    engine.dispose()

    return 1


@app.task
def handle_updatedps(useremail, workoutids, debug=False,**kwargs):
    for wid, f1 in workoutids:
        havedata = 1
        try:
            rowdata = rdata(csvfile=f1)
        except IOError:
            try:
                rowdata = rdata(csvfile=f1 + '.csv')
            except IOError:
                try:
                    rowdata = rdata(csvfile=f1 + '.gz')
                except IOError:
                    havedata = 0

        if havedata:
            update_strokedata(wid, rowdata.df, debug=debug)


    subject = "Rowsandall.com Your Distance per Stroke metric has been updated"
    message = "All your workouts now have Distance per Stroke"

    email = EmailMessage(subject, message,
                         'Rowsandall <info@rowsandall.com>',
                         [useremail])

    if 'emailbounced' in kwargs:
        emailbounced = kwargs['emailbounced']
    else:
        emailbounced = False

    if not emailbounced:
        res = email.send()

    return 1

import math
def sigdig(value, digits = 3):
    try:
        order = int(math.floor(math.log10(math.fabs(value))))
    except (ValueError,TypeError):
        return value

    # return integers as is
    if value % 1 == 0:
        return value

    places = digits - order - 1
    if places > 0:
        fmtstr = "%%.%df" % (places)
    else:
        fmtstr = "%.0f"
    return fmtstr % (round(value, places))



@app.task
def handle_send_email_alert(
        useremail, userfirstname, userlastname, rowerfirstname, alertname, stats, **kwargs):

    if 'debug' in kwargs:
        debug = kwargs['debug']
    else:
        debug = False

    if 'othertexts' in kwargs:
        othertexts = kwargs['othertexts']
    else:
        othertexts = None

    report = {}
    try:
        report['Percentage'] = int(stats['percentage'])
    except KeyError:
        pass

    try:
        report['Number of workouts'] = int(stats['workouts'])
    except KeyError:
        pass

    try:
        report['Data set'] = "{a} strokes out of {b}".format(
        a = stats['nr_strokes_qualifying'],
        b = stats['nr_strokes']
        )
    except KeyError:
        pass


    try:
        report['Median'] = sigdig(stats['median'])
    except KeyError:
        pass

    try:
        report['Median of qualifying strokes'] = sigdig(stats['median_q'])
    except KeyError:
        pass

    subject = "Rowsandall.com: {alertname} ({startdate} to {enddate})".format(
        startdate = stats['startdate'],
        enddate = stats['enddate'],
        alertname=alertname,
        )

    from_email = 'Rowsandall <info@rowsandall.com>'

    d = {
        'report':report,
        'first_name':userfirstname,
        'last_name':userlastname,
        'startdate':stats['startdate'],
        'enddate':stats['enddate'],
        'siteurl':siteurl,
        'rowerfirstname':rowerfirstname,
        'alertname':alertname,
        'othertexts':othertexts,
        }

    res = send_template_email(from_email,[useremail],subject,
                              'alertemail.html',
                              d,**kwargs)

    return 1

@app.task
def handle_send_email_transaction(
        username, useremail, amount, **kwargs):

    if 'debug' in kwargs:
        debug = kwargs['debug']
    else:
        debug = True

    subject = "Rowsandall Payment Confirmation"

    from_email = 'Rowsandall <admin@rowsandall.com>'

    d = {
        'name': username,
        'siteurl': siteurl,
        'amount': amount
        }

    res = send_template_email(from_email,[useremail],
                              subject,
                              'paymentconfirmationemail.html',
                              d, **kwargs)

    return 1

@app.task
def handle_send_email_failed_cancel(
        name, email, username, id, **kwargs):

    if 'debug' in kwargs:
        debug = kwargs['debug']
    else:
        debug = True

    subject = "Rowsandall Subscription Cancellation Error"

    from_email = 'Rowsandall <admin@rowsandall.com>'

    d = {
        'name': name,
        'siteurl': siteurl,
        'email': email,
        'username': username,
        'id': id,
        }

    res = send_template_email(from_email,["support@rowsandall.com"],
                              subject,
                              'cancel_subscription_fail_email.html',
                              d, **kwargs)

    return 1


@app.task
def handle_send_email_subscription_update(
        username, useremail, planname, recurring, price, amount,
        end_of_billing_period, method, **kwargs):

    if 'debug' in kwargs:
        debug = kwargs['debug']
    else:
        debug = True


    from_email = 'Rowsandall <admin@rowsandall.com>'

    d = {
        'name': username,
        'siteurl': siteurl,
        'amount': amount,
        'price':price,
        'planname': planname,
        'recurring': recurring,
        'end_of_billing_period': end_of_billing_period,
        }

    if method == 'down':
        template_name = 'subscription_downgrade_email.html'
        notification_template_name = 'subscription_downgrade_notification.html'
        subject = "Rowsandall Change Confirmation"
    else:
        template_name = 'subscription_update_email.html'
        notification_template_name = 'subscription_update_notification.html'
        subject = "Rowsandall Payment Confirmation"

    res = send_template_email(from_email,[useremail],
                              subject,
                              template_name,
                              d, **kwargs)

    res = send_template_email(from_email,['info@rowsandall.com'],
                              'Subscription Update Notification',
                              notification_template_name,
                              d, **kwargs)

    return 1

@app.task
def handle_send_email_subscription_create(
        username, useremail, planname, recurring, price, amount,
        end_of_billing_period, **kwargs):

    if 'debug' in kwargs:
        debug = kwargs['debug']
    else:
        debug = True

    subject = "Rowsandall Payment Confirmation"

    from_email = 'Rowsandall <admin@rowsandall.com>'


    d = {
        'name': username,
        'siteurl': siteurl,
        'amount': amount,
        'price':price,
        'planname': planname,
        'end_of_billing_period': end_of_billing_period,
        'recurring': recurring,
        }

    res = send_template_email(from_email,[useremail],
                              subject,
                              'subscription_create_email.html',
                              d, **kwargs)

    res = send_template_email(from_email,['info@rowsandall.com'],
                              'Subscription Update Notification',
                              'subscription_create_notification.html',
                              d, **kwargs)
    return 1

@app.task
def handle_sendemail_raceregistration(
        useremail, username, registeredname, racename, raceid, **kwargs):

    if 'debug' in kwargs:
        debug = kwargs['debug']
    else:
        debug = True

    subject = "A new competitor has registered for virtual challenge {n}".format(
        n = racename
        )

    from_email = 'Rowsandall <info@rowsandall.com>'

    d = {
        'username':username,
        'registeredname':registeredname,
        'siteurl':siteurl,
        'racename':racename,
        'raceid':raceid,
        }

    res = send_template_email(from_email,[useremail],
                              subject,
                              'raceregisteredemail.html',
                              d,**kwargs)

    return 1

@app.task
def handle_sendemail_racesubmission(
        useremail, username, registeredname, racename, raceid, **kwargs):

    if 'debug' in kwargs:
        debug = kwargs['debug']
    else:
        debug = True

    subject = "A new result has been submitted for virtual challenge {n}".format(
        n = racename
        )

    from_email = 'Rowsandall <info@rowsandall.com>'

    d = {
        'username':username,
        'siteurl':siteurl,
        'registeredname':registeredname,
        'racename':racename,
        'raceid':raceid,
        }

    res = send_template_email(from_email,[useremail],
                              subject,
                              'racesubmissionemail.html',
                              d,**kwargs)

    return 1

@app.task
def handle_send_disqualification_email(
        useremail,username,reason,message, racename, **kwargs):

    if 'debug' in kwargs:
        debug = kwargs['debug']
    else:
        debug = True

    subject = "Your result for {n} has been disqualified on rowsandall.com".format(
        n = racename
        )

    from_email = 'Rowsandall <support@rowsandall.com>'

    d = {
        'username':username,
        'reason':reason,
        'siteurl':siteurl,
        'message': htmlstrip(message),
        'racename':racename,
        }

    res = send_template_email(from_email,[useremail],
                              subject,
                              'disqualificationemail.html',
                              d,**kwargs)

    return 1

@app.task
def handle_send_withdraw_email(
        useremail,username,reason,message, racename, **kwargs):

    if 'debug' in kwargs:
        debug = kwargs['debug']
    else:
        debug = True

    subject = "Your result for {n} has been removed on rowsandall.com".format(
        n = racename
        )

    from_email = 'Rowsandall <support@rowsandall.com>'

    d = {
        'username':username,
        'reason':reason,
        'siteurl':siteurl,
        'message': htmlstrip(message),
        'racename':racename,
        }

    res = send_template_email(from_email,[useremail],
                              subject,
                              'withdraw_email.html',
                              d,**kwargs)

    return 1


@app.task
def handle_sendemail_expired(useremail,userfirstname,userlastname,expireddate,
                             **kwargs):
    if 'debug' in kwargs:
        debug = kwargs['debug']
    else:
        debug = False

    subject = "Your rowsandall.com paid account has expired"
    from_email = 'Rowsandall <info@rowsandall.com>'

    d = {
        'first_name':userfirstname,
        'last_name':userlastname,
        'siteurl':siteurl,
        'expireddate':expireddate,
        }

    res = send_template_email(from_email,[useremail],
                              subject,'accountexpiredemail.html',
                              d,cc=['support@rowsandall.com'],**kwargs)
    return 1

@app.task
def handle_sendemail_breakthrough(workoutid, useremail,
                                  userfirstname, userlastname,
                                  btvalues=pd.DataFrame().to_json(),
                                  **kwargs):

    if 'debug' in kwargs:
        debug = kwargs['debug']
    else:
        debug = False

    btvalues = pd.read_json(btvalues)
    btvalues.sort_values('delta', axis=0, inplace=True)

    tablevalues = [
        {'delta': t.delta,
         'cpvalue': t.cpvalues,
         'pwr': t.pwr
         } for t in btvalues.itertuples()
        ]

    # send email with attachment
    subject = "A breakthrough workout on rowsandall.com"
    from_email = 'Rowsandall <info@rowsandall.com>'

    d = {
        'first_name':userfirstname,
        'siteurl':siteurl,
        'workoutid':encoder.encode_hex(workoutid),
        'btvalues':tablevalues,
        }



    res = send_template_email(from_email,[useremail],
                              subject,'breakthroughemail.html',
                              d,**kwargs)


    return 1

# send email when a breakthrough workout is uploaded


@app.task
def handle_sendemail_hard(workoutid, useremail,
                          userfirstname, userlastname,
                          btvalues=pd.DataFrame().to_json(),
                          debug=False,**kwargs):

    if 'debug' in kwargs:
        debug = kwargs['debug']
    else:
        debug = False


    btvalues = pd.read_json(btvalues)
    btvalues.sort_values('delta', axis=0, inplace=True)

    tablevalues = [
        {'delta': t.delta,
         'cpvalue': t.cpvalues,
         'pwr': t.pwr
         } for t in btvalues.itertuples()
        ]

    # send email with attachment
    subject = "That was a pretty hard workout on rowsandall.com"
    from_email = 'Rowsandall <info@rowsandall.com>'

    d = {
        'first_name':userfirstname,
        'siteurl':siteurl,
        'workoutid':encoder.encode_hex(workoutid),
        'btvalues':tablevalues,
        }

    res = send_template_email(from_email,[useremail],
                              subject,'hardemail.html',d,**kwargs)


    return 1


# send email when user deletes account
@app.task
def handle_sendemail_userdeleted(name, email, debug=False, **kwargs):
    fullemail = 'roosendaalsander@gmail.com'
    subject = 'User account deleted'
    message = 'Sander,\n\n'
    message += 'The user {name} ({email}) has just deleted his account'.format(
        name=name,
        email=email
        )
    email = EmailMessage(subject,message,
                         'Rowsandall <info@rowsandall.com>',
                         [fullemail])

    if 'emailbounced' in kwargs:
        emailbounced = kwargs['emailbounced']
    else:
        emailbounced = False

    if not emailbounced:
        res = email.send()


    return 1

# send email to me when an unrecognized file is uploaded
@app.task
def handle_sendemail_unrecognized(unrecognizedfile, useremail,
                                  debug=False,**kwargs):

    # send email with attachment
    fullemail = 'roosendaalsander@gmail.com'
    subject = "Unrecognized file from Rowsandall.com"
    message = "Dear Sander,\n\n"
    message += "Please find attached a file that someone tried to upload to rowsandall.com. The file was not recognized as a valid file type.\n\n"
    message += "User Email " + useremail + "\n\n"
    message += "Best Regards, the Rowsandall Team"

    email = EmailMessage(subject, message,
                         'Rowsandall <info@rowsandall.com>',
                         [fullemail])

    try:
        email.attach_file(unrecognizedfile)
    except IOError:
        pass

    if 'emailbounced' in kwargs:
        emailbounced = kwargs['emailbounced']
    else:
        emailbounced = False

    if not emailbounced:
        res = email.send()


    # remove tcx file
    try:
        os.remove(unrecognizedfile)
    except:
        pass

    return 1


# send email to owner when an unrecognized file is uploaded
@app.task
def handle_sendemail_unrecognizedowner(useremail, userfirstname,
                                       debug=False,**kwargs):

    # send email with attachment
    fullemail = useremail
    subject = "Unrecognized file from Rowsandall.com"


    d = {
        'first_name':userfirstname,
        'siteurl':siteurl,
    }

    from_email = 'Rowsandall <info@rowsandall.com>'

    res = send_template_email(from_email,[fullemail],
                              subject,'unrecognizedemail.html',d,
                              **kwargs)

    return 1

@app.task
def handle_sendemailics(first_name, last_name, email, icsfile, **kwargs):
    # send email with attachment
    fullemail = first_name + " " + last_name + " " + "<" + email + ">"
    subject = "Calendar File from Rowsandall.com"


    d = {'first_name':first_name,
         'siteurl':siteurl,
    }

    from_email = 'Rowsandall <info@rowsandall.com>'


    res = send_template_email(from_email,[fullemail],
                              subject,'icsemail.html',d,
                              attach_file=icsfile,**kwargs)

    os.remove(icsfile)
    return 1


@app.task
def handle_sendemailkml(first_name, last_name, email, kmlfile,**kwargs):

    # send email with attachment
    fullemail = first_name + " " + last_name + " " + "<" + email + ">"
    subject = "File from Rowsandall.com"


    d = {'first_name':first_name,
         'siteurl':siteurl,
    }

    from_email = 'Rowsandall <info@rowsandall.com>'


    res = send_template_email(from_email,[fullemail],
                              subject,'kmlemail.html',d,
                              attach_file=kmlfile,**kwargs)

    os.remove(kmlfile)
    return 1

# Send email with TCX attachment
@app.task
def handle_sendemailtcx(first_name, last_name, email, tcxfile,**kwargs):

    # send email with attachment
    fullemail = first_name + " " + last_name + " " + "<" + email + ">"
    subject = "File from Rowsandall.com"


    d = {'first_name':first_name,
         'siteurl':siteurl,
    }

    from_email = 'Rowsandall <info@rowsandall.com>'


    res = send_template_email(from_email,[fullemail],
                              subject,'tcxemail.html',d,
                              attach_file=tcxfile,**kwargs)

    os.remove(tcxfile)
    return 1


@app.task
def handle_zip_file(emailfrom, subject, file,**kwargs):
    message = "... zip processing ... "
    try:
        debug = kwargs['debug']
    except KeyError:
        debug = False

    if debug:
        print(message)

    email = EmailMessage(subject, message,
                         emailfrom,
                         ['workouts@rowsandall.com'])
    email.attach_file(file)
    if debug:
        print("attaching")


    res = email.send()


    if debug:
        print("sent")
    time.sleep(60)
    return 1

# Send email with CSV attachment

@app.task
def handle_sendemailsummary(first_name, last_name, email, csvfile, **kwargs):
    fullemail = first_name + " " + last_name + " " + "<" + email + ">"
    subject = "File from Rowsandall.com"


    d = {'first_name':first_name,
         'siteurl':siteurl,
    }

    from_email = 'Rowsandall <info@rowsandall.com>'

    res = send_template_email(from_email,[fullemail],
                              subject,'summarymail.html',d,
                              attach_file=csvfile,
                              **kwargs)

    try:
        os.remove(csvfile)
    except:
        pass

    return 1

#from rowers.emails import sendemail

@app.task
def handle_sendemailcsv(first_name, last_name, email, csvfile,**kwargs):


    # send email with attachment
    fullemail = first_name + " " + last_name + " " + "<" + email + ">"
    subject = "File from Rowsandall.com"

    d = {'first_name':first_name,
         'siteurl':siteurl,
    }

    from_email = 'Rowsandall <info@rowsandall.com>'


    res = send_template_email(from_email,[fullemail],
                              subject,'csvemail.html',d,
                              attach_file=csvfile,**kwargs)


    return 1

@app.task
def handle_sendemail_ical(first_name, last_name, email, url, icsfile, **kwargs):
    # send email with attachment
    fullemail = first_name + " " + last_name + " " + "<" + email + ">"
    subject = "Calendar File for your sessions from Rowsandall.com"

    if 'debug' in kwargs:
        debug = kwargs['debug']
    else:
        debug = False

    siteurl = SITE_URL
    if debug:
        progressurl = SITE_URL_DEV
        siteurl = SITE_URL_DEV


    d = {'first_name':first_name,
         'siteurl':siteurl,
         'url':url,
    }

    from_email = 'Rowsandall <info@rowsandall.com>'


    res = send_template_email(from_email,[fullemail],
                              subject,'icsemail.html',d,
                              attach_file=icsfile,**kwargs)


    try:
        os.remove(csvfile)
    except:
        pass

    return 1


@app.task
def handle_sendemailfile(first_name, last_name, email, csvfile,**kwargs):


    # send email with attachment
    fullemail = first_name + " " + last_name + " " + "<" + email + ">"
    subject = "File from Rowsandall.com"

    d = {'first_name':first_name,
         'siteurl':siteurl,
    }

    from_email = 'Rowsandall <info@rowsandall.com>'


    res = send_template_email(from_email,[fullemail],
                              subject,'fileemail.html',d,
                              attach_file=csvfile,**kwargs)


    if 'delete' in kwargs:
        dodelete = kwargs['delete']
    else:
        dodelete = False

    if dodelete:
        try:
            os.remove(csvfile)
        except:
            pass

    return 1

# Calculate wind and stream corrections for OTW rowing


@app.task(bind=True)
def handle_otwsetpower(self,f1, boattype, weightvalue,
                       first_name, last_name, email, workoutid,
                       **kwargs):

    job = self.request
    job_id = job.id

    if 'jobkey' in kwargs:
        job_id = kwargs.pop('jobkey')
    if 'ps' in kwargs:
        ps = kwargs['ps']
    else:
        ps = [1,1,1,1]

    if 'ratio' in kwargs:
        ratio = kwargs['ratio']
    else:
        ratio = 1.0
    if 'debug' in kwargs:
        debug = kwargs['debug']
    else:
        debug = False

    kwargs['jobid'] = job_id




    weightvalue = float(weightvalue)

    # check what the real file name is
    if os.path.exists(f1):
        csvfile = f1
    elif os.path.exists(f1+'.csv'):
        csvfile = f1+'.csv'
    elif os.path.exists(f1+'.gz'):
        csvfile = f1+'.gz'

    csvfile = os.path.abspath(csvfile)

    # do something with boat type
    try:
        rowdata = rdata(csvfile)
    except IOError:
        try:
            rowdata = rdata(csvfile)
        except IOError:
            rowdata = rdata(csvfile)

    # do calculation, but do not overwrite NK Empower Power data
    powermeasured = False
    try:
        w = rowdata.df['wash']
        if w.mean() != 0:
            powermeasured = True
    except KeyError:
        pass

    progressurl = SITE_URL
    siteurl = SITE_URL
    if debug:
        progressurl = SITE_URL_DEV
        siteurl = SITE_URL_DEV
    secret = PROGRESS_CACHE_SECRET

    progressurl += "/rowers/record-progress/"
    progressurl += job_id+'/'

    goservice = True

    if goservice:
        # do something (this should return from go service)
        with grpc.insecure_channel(
            target='localhost:50051',
            options=[('grpc.lb_policy_name', 'pick_first'),
                     ('grpc.enable_retries', 0), ('grpc.keepalive_timeout_ms',
                                                  10000)]
            ) as channel:
            try:
                grpc.channel_ready_future(channel).result(timeout=10)
            except grpc.FutureTimeoutError:
                return 0

            stub = calculator_pb2_grpc.PowerStub(channel)
            response = stub.CalcPower(calculator_pb2.WorkoutPowerRequest(
                filename = csvfile,
                boattype = boattype,
                crewmass = weightvalue,
                powermeasured = powermeasured,
                progressurl = progressurl,
                secret = secret,
                silent = False,
            ),timeout=1200)
            result = response.result
            if result == 0:
                # send failure email
                return 0
            # do something with boat type
            try:
                rowdata = rdata(csvfile)
            except IOError:
                try:
                    rowdata = rdata(csvfile)
                except IOError:
                    rowdata = rdata(csvfile)

    else:
        boatfile = {
            '1x': 'static/rigging/1x.txt',
            '2x': 'static/rigging/2x.txt',
            '2-': 'static/rigging/2-.txt',
            '4x': 'static/rigging/4x.txt',
            '4-': 'static/rigging/4-.txt',
            '8+': 'static/rigging/8+.txt',
            }
        try:
            rg = rowingdata.getrigging(boatfile[boattype])
        except KeyError:
            rg = rowingdata.getrigging('static/rigging/1x.txt')

        # determine cache file name
        physics_cache = 'media/'+str(boattype)+'_'+str(int(weightvalue))



        rowdata.otw_setpower(skiprows=5, mc=weightvalue, rg=rg,
                             powermeasured=powermeasured,
                             progressurl=progressurl,
                             secret=secret,
                             silent=True,
                             usetable=usetable,storetable=physics_cache,
                             )

        # save data
        rowdata.write_csv(f1, gzip=True)

    # continuing for both
    update_strokedata(workoutid, rowdata.df, debug=debug)

    totaltime = rowdata.df['TimeStamp (sec)'].max(
    ) - rowdata.df['TimeStamp (sec)'].min()
    try:
        totaltime = totaltime + rowdata.df.ix[0, ' ElapsedTime (sec)']
    except KeyError:
        pass
    df = getsmallrowdata_db(
        ['power', 'workoutid', 'time'], ids=[workoutid],
        debug=debug)
    thesecs = totaltime
    maxt = 1.05 * thesecs
    logarr = datautils.getlogarr(maxt)
    dfgrouped = df.groupby(['workoutid'])
    delta, cpvalues, avgpower = datautils.getcp(dfgrouped, logarr)

    #delta,cpvalues,avgpower = datautils.getsinglecp(rowdata.df)
    res, btvalues, res2 = utils.isbreakthrough(
        delta, cpvalues, ps[0], ps[1], ps[2], ps[3], ratio)
    if res:
        handle_sendemail_breakthrough(
            workoutid, email,
            first_name,
            last_name, btvalues=btvalues.to_json())


    subject = "Your OTW Physics Calculations are ready"
    from_email = 'Rowsandall <info@rowsandall.com>'
    fullemail = first_name + " " + last_name + " " + "<" + email + ">"


    d = {
        'first_name':first_name,
        'siteurl':siteurl,
        'workoutid':encoder.encode_hex(workoutid),
        }

    res = send_template_email(from_email,[fullemail],
                                subject,'otwpoweremail.html',d,
                                **kwargs)

    return 1


@app.task
def handle_updateergcp(rower_id,workoutfilenames,debug=False,**kwargs):
    therows = []
    for f1 in workoutfilenames:
        try:
            rowdata = rdata(csvfile=f1)
        except IOError:
            try:
                rowdata = rdata(csvfile=f1 + '.csv')
            except IOError:
                try:
                    rowdata = rdata(csvfile=f1 + '.gz')
                except IOError:
                    rowdata = 0
        if rowdata != 0:
            therows.append(rowdata)

    cpdata = rowingdata.cumcpdata(therows)
    cpdata.columns = cpdata.columns.str.lower()

    updatecpdata_sql(rower_id,cpdata['delta'],cpdata['cp'],
                     table='ergcpdata',distance=cpdata['distance'],
                     debug=debug)

    return 1

def cp_from_workoutids(workoutids,debug=False):
    columns = ['power','workoutid','time']
    df = getsmallrowdata_db(columns,ids=workoutids,debug=debug)
    df.dropna(inplace=True,axis=0)

    if df.empty:
        # change this
        return 0,0,0

    # df is not empty. We continue
    dfgrouped = df.groupby(['workoutid'])
    maxt = 1.05*df['time'].max()/1000.

    logarr = datautils.getlogarr(maxt)

    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)

    p1,fitt,fitpower,ratio = datautils.cpfit(powerdf)
    # This is code duplication from datautils -- correct asap
    fitfunc = lambda pars,x: abs(pars[0])/(1+(x/abs(pars[2]))) + abs(pars[1])/(1+(x/abs(pars[3])))

    powerfourmin = fitfunc(p1,240.)
    powerhour = fitfunc(p1,3600.)

    # 2k power
    velofourmin = (powerfourmin/2.8)**(1./3.)
    dfourmin = 240.*velofourmin
    dratio = 2000./dfourmin
    pacefourmin = 500./velofourmin

    # assume 5 sec per doubling drop
    pace2k = pacefourmin + 5.*np.log10(dratio)/np.log10(2.)
    velo2k = 500./pace2k
    t2k = 2000./velo2k
    pwr2k = fitfunc(p1,t2k)
    velo2 = (pwr2k/2.8)**(1./3.)
    if np.isnan(velo2) or velo2 <= 0:
        velo2 = 1.0

    t2 = 2000./velo2

    pwr2k = fitfunc(p1,t2)

    velo3 = (pwr2k/2.8)**(1./3.)

    t3 = 2000./velo3

    power2k = fitfunc(p1,t3)

    return powerfourmin,power2k,powerhour


@app.task
def handle_updatefitnessmetric(user_id,mode,workoutids,debug=False,
                               **kwargs):

    powerfourmin = -1
    power2k = -1
    powerhour = -1

    mdict = {
        'user_id': user_id,
        'PowerFourMin': powerfourmin,
        'PowerTwoK': power2k,
        'PowerOneHour': powerhour,
        'workoutmode': mode,
        'last_workout': max(workoutids),
        'date': timezone.now().strftime('%Y-%m-%d'),
             }

    result = fitnessmetric_to_sql(mdict,debug=debug,doclean=False)

    powerfourmin,power2k,powerhour = cp_from_workoutids(workoutids,debug=debug)

    if powerfourmin > 0 and power2k > 0 and powerhour > 0:

        mdict = {
            'user_id': user_id,
            'PowerFourMin': powerfourmin,
            'PowerTwoK': power2k,
            'PowerOneHour': powerhour,
            'workoutmode': mode,
            'last_workout': max(workoutids),
            'date': timezone.now().strftime('%Y-%m-%d'),
        }

        result = fitnessmetric_to_sql(mdict,debug=debug,doclean=True)
    else:
        result = 0

    return result

@app.task
def handle_updatecp(rower_id,workoutids,debug=False,table='cpdata',**kwargs):
    columns = ['power','workoutid','time']
    df = getsmallrowdata_db(columns,ids=workoutids,debug=debug)

    if df.empty:
        return 0

    maxt = 1.05*df['time'].max()/1000.

    logarr = datautils.getlogarr(maxt)

    dfgrouped = df.groupby(['workoutid'])

    delta,cpvalue,avgpower = datautils.getcp(dfgrouped,logarr)

    updatecpdata_sql(rower_id,delta,cpvalue,debug=debug,table=table)

    return 1

@app.task
def handle_makeplot(f1, f2, t, hrdata, plotnr, imagename,
                    debug=False,**kwargs):

    hrmax = hrdata['hrmax']
    hrut2 = hrdata['hrut2']
    hrut1 = hrdata['hrut1']
    hrat = hrdata['hrat']
    hrtr = hrdata['hrtr']
    hran = hrdata['hran']
    ftp = hrdata['ftp']
    powerzones = deserialize_list(hrdata['powerzones'])
    powerperc = np.array(deserialize_list(hrdata['powerperc'])).astype(float)

    rr = rowingdata.rower(hrmax=hrmax, hrut2=hrut2,
                          hrut1=hrut1, hrat=hrat,
                          hrtr=hrtr, hran=hran,
                          ftp=ftp, powerperc=powerperc,
                          powerzones=powerzones)
    try:
        row = rdata(csvfile=f2, rower=rr)
    except IOError:
        row = rdata(csvfile=f2 + '.gz', rower=rr)

    try:
        haspower = row.df[' Power (watts)'].mean() > 50
    except (TypeError, KeyError):
        haspower = False

    oterange = kwargs.pop('oterange',[85,240])
    otwrange = kwargs.pop('otwrange',[85,185])


    nr_rows = len(row.df)
    if (plotnr in [1, 2, 4, 5, 8, 11, 9, 12]) and (nr_rows > 1200):
        bin = int(nr_rows / 1200.)
        df = row.df.groupby(lambda x: x / bin).mean()
        row.df = df
    nr_rows = len(row.df)
    if (plotnr == 1):
        fig1 = row.get_timeplot_erg(t,pacerange=oterange,**kwargs)
    elif (plotnr == 2):
        fig1 = row.get_metersplot_erg(t,pacerange=oterange,**kwargs)
    elif (plotnr == 3):
        t += ' - Heart Rate Distribution'
        fig1 = row.get_piechart(t,**kwargs)
    elif (plotnr == 4):
        if haspower:
            fig1 = row.get_timeplot_otwempower(t,pacerange=otwrange,**kwargs)
        else:
            fig1 = row.get_timeplot_otw(t,pacerange=otwrange,**kwargs)
    elif (plotnr == 5):
        if haspower:
            fig1 = row.get_metersplot_otwempower(t,pacerange=otwrange,**kwargs)
        else:
            fig1 = row.get_metersplot_otw(t,pacerange=otwrange,**kwargs)
    elif (plotnr == 6):
        t += ' - Heart Rate Distribution'
        fig1 = row.get_piechart(t,**kwargs)
    elif (plotnr == 7) or (plotnr == 10):
        fig1 = row.get_metersplot_erg2(t,**kwargs)
    elif (plotnr == 8) or (plotnr == 11):
        fig1 = row.get_timeplot_erg2(t,**kwargs)
    elif (plotnr == 9) or (plotnr == 12):
        fig1 = row.get_time_otwpower(t,pacerange=otwrange,**kwargs)
    elif (plotnr == 13) or (plotnr == 16):
        t += ' - Power Distribution'
        fig1 = row.get_power_piechart(t,**kwargs)

    if fig1 is None:
        return 0


    canvas = FigureCanvas(fig1)

    canvas.print_figure('static/plots/' + imagename)
    plt.close(fig1)
    fig1.clf()
    gc.collect()

    return imagename

# Team related remote tasks

@app.task
def handle_sendemail_coachrequest(email,name,code,coachname,
                                   debug=False,**kwargs):

    fullemail = email
    subject = 'Invitation to add {n} to your athletes'.format(n=name)
    from_email = 'Rowsandall <info@rowsandall.com>'
    siteurl = SITE_URL
    if debug:
        siteurl = SITE_URL_DEV

    d = {
        'name':name,
        'coach':coachname,
        'code':code,
        'siteurl':siteurl
        }

    form_email = 'Rowsandall <info@rowsandall.com>'

    res = send_template_email(from_email,[fullemail],
                              subject,'coachrequestemail.html',d,
                              **kwargs)

    return 1

@app.task
def handle_sendemail_coachoffer_rejected(coachemail,coachname,name,
                                         debug=False,**kwargs):

    fullemail = coachemail
    subject = '{n} has rejected your offer to be his coach on rowsandall.com'.format(n=name)
    from_email = 'Rowsandall <info@rowsandall.com>'
    siteurl = SITE_URL
    if debug:
        siteurl = SITE_URL_DEV

    d = {
        'name':name,
        'coach':coachname,
        'siteurl':siteurl,
        }

    res = send_template_email(from_email,[fullemail],
                              subject,'coachofferrejectedemail.html',
                              d,
                              **kwargs)
    return 1

@app.task
def handle_sendemail_coachrequest_rejected(email,coachname,name,
                                         debug=False,**kwargs):

    fullemail = email
    subject = '{n} has rejected your coaching request on rowsandall.com'.format(n=coachname)
    from_email = 'Rowsandall <info@rowsandall.com>'
    siteurl = SITE_URL
    if debug:
        siteurl = SITE_URL_DEV

    d = {
        'name':name,
        'coach':coachname,
        'siteurl':siteurl,
        }

    res = send_template_email(from_email,[fullemail],
                              subject,'coachrequestrejectedemail.html',
                              d,
                              **kwargs)
    return 1

@app.task
def handle_sendemail_coachrequest_accepted(email,coachname,name,
                                         debug=False,**kwargs):

    fullemail = email
    subject = '{n} has accepted your coaching request on rowsandall.com'.format(n=coachname)
    from_email = 'Rowsandall <info@rowsandall.com>'
    siteurl = SITE_URL
    if debug:
        siteurl = SITE_URL_DEV

    d = {
        'name':name,
        'coach':coachname,
        'siteurl':siteurl,
        }

    res = send_template_email(from_email,[fullemail],
                              subject,'coachrequestacceptedemail.html',
                              d,
                              **kwargs)
    return 1

@app.task
def handle_sendemail_coachoffer_accepted(coachemail,coachname,name,
                                         debug=False,**kwargs):

    fullemail = coachemail
    subject = '{n} has accepted your coaching offer on rowsandall.com'.format(n=name)
    from_email = 'Rowsandall <info@rowsandall.com>'
    siteurl = SITE_URL
    if debug:
        siteurl = SITE_URL_DEV

    d = {
        'name':name,
        'coach':coachname,
        'siteurl':siteurl,
        }

    res = send_template_email(from_email,[fullemail],
                              subject,'coachofferacceptedemail.html',
                              d,
                              **kwargs)
    return 1

@app.task
def handle_sendemail_coacheerequest(email,name,code,coachname,
                                   debug=False,**kwargs):

    fullemail = email
    subject = '{n} requests coach access to your data on rowsandall.com'.format(n=coachname)
    from_email = 'Rowsandall <info@rowsandall.com>'
    siteurl = SITE_URL
    if debug:
        siteurl = SITE_URL_DEV

    d = {
        'name':name,
        'coach':coachname,
        'code':code,
        'siteurl':siteurl
        }

    res = send_template_email(from_email,[fullemail],
                              subject,'coacheerequestemail.html',d,
                              **kwargs)

    return 1

@app.task
def handle_sendemail_invite(email, name, code, teamname, manager,
                            debug=False,**kwargs):
    fullemail = email
    subject = 'Invitation to join team ' + teamname

    siteurl = SITE_URL
    if debug:
        siteurl = SITE_URL_DEV

    d = {
        'name':name,
        'manager':manager,
        'code':code,
        'teamname':teamname,
        'siteurl':siteurl
        }

    from_email = 'Rowsandall <info@rowsandall.com>'

    res = send_template_email(from_email,[fullemail],
                              subject,'teaminviteemail.html',d,
                              **kwargs)

    return 1


@app.task
def handle_sendemailnewresponse(first_name, last_name,
                                email,
                                commenter_first_name,
                                commenter_last_name,
                                comment,
                                workoutname, workoutid, commentid,
                                debug=False,**kwargs):
    fullemail = email
    from_email = 'Rowsandall <info@rowsandall.com>'
    subject = 'New comment on session ' + workoutname

    comment = u''+comment

    siteurl = SITE_URL
    if debug:
        siteurl = SITE_URL_DEV

    sessiontype = 'workout'
    if 'sessiontype' in kwargs:
        sessiontype=kwargs.pop('sessiontype')

    commentlink = '/rowers/workout/{workoutid}/comment/'.format(
        workoutid=encoder.encode_hex(workoutid))
    if 'commentlink' in kwargs:
        commentlink = kwargs.pop('commentlink')

    d = {
        'first_name':first_name,
        'commenter_first_name':commenter_first_name,
        'commenter_last_name':commenter_last_name,
        'comment':comment,
        'workoutname':workoutname,
        'siteurl':siteurl,
        'workoutid':workoutid,
        'commentid':commentid,
        'sessiontype':sessiontype,
        'commentlink':commentlink,
        }

    res = send_template_email(from_email,
                              [fullemail],
                              subject,'teamresponseemail.html',d,**kwargs)

    return 1


@app.task
def handle_sendemailnewcomment(first_name,
                               last_name,
                               email,
                               commenter_first_name,
                               commenter_last_name,
                               comment, workoutname,
                               workoutid,
                               debug=False,**kwargs):



    fullemail = email
    from_email = 'Rowsandall <info@rowsandall.com>'
    subject = 'New comment on session ' + workoutname

    comment = u''+comment

    siteurl = SITE_URL
    if debug:
        siteurl = SITE_URL_DEV

    sessiontype = 'workout'
    if 'sessiontype' in kwargs:
        sessiontype=kwargs.pop('sessiontype')

    commentlink = '/rowers/workout/{workoutid}/comment/'.format(
        workoutid=encoder.encode_hex(workoutid))
    if 'commentlink' in kwargs:
        commentlink = kwargs.pop('commentlink')

    d = {
        'first_name':first_name,
        'commenter_first_name':commenter_first_name,
        'commenter_last_name':commenter_last_name,
        'comment':comment,
        'workoutname':workoutname,
        'siteurl':siteurl,
        'workoutid':encoder.encode_hex(workoutid),
        'sessiontype':sessiontype,
        'commentlink':commentlink,
        }

    res = send_template_email(from_email,[fullemail],subject,
                              'teamresponseemail.html',d,**kwargs)


    return 1

@app.task
def handle_sendemail_message(email,fromemail,rowername,message,teamname,managername,
                             debug=False,**kwargs):

    fullemail = email
    subject = 'New message from team ' + teamname
    from_email = 'Rowsandall <info@rowsandall.com>'

    d = {
        'rowername':rowername,
        'teamname':teamname,
        'managername':managername,
        'message':message,
        }

    res = send_template_email(from_email,[fullemail],subject,
                              'teammessage.html',d,**kwargs)

    return 1

@app.task
def handle_sendemail_request(email, name, code, teamname, requestor, id,
                             debug=False,**kwargs):
    fullemail = email
    subject = 'Request to join team ' + teamname
    from_email = 'Rowsandall <info@rowsandall.com>'

    siteurl = SITE_URL
    if debug:
        siteurl = SITE_URL_DEV

    d = {
        'requestor':requestor,
        'teamname':teamname,
        'code': code,
        'siteurl':siteurl,
        'id':id,
        'first_name':name,
        }

    res = send_template_email(from_email,[fullemail],subject,
                              'teamrequestemail.html',d,**kwargs)


    return 1


@app.task
def handle_sendemail_request_accept(email, name, teamname, managername,
                                    debug=False,**kwargs):
    fullemail = email
    subject = 'Welcome to ' + teamname
    from_email = 'Rowsandall <info@rowsandall.com>'

    siteurl = SITE_URL
    if debug:
        siteurl = SITE_URL_DEV

    d = {
        'first_name':name,
        'managername':managername,
        'teamname':teamname,
        'siteurl':siteurl,
        }
    res = send_template_email(from_email,[fullemail],subject,
                              'teamwelcomeemail.html',d,**kwargs)


    return 1


@app.task
def handle_sendemail_request_reject(email, name, teamname, managername,
                                    debug=False,**kwargs):
    fullemail = email
    subject = 'Your application to ' + teamname + ' was rejected'
    from_email = 'Rowsandall <info@rowsandall.com>'

    siteurl = SITE_URL
    if debug:
        siteurl = SITE_URL_DEV

    d = {
        'first_name':name,
        'managername':managername,
        'teamname':teamname,
        'siteurl':siteurl,
        }
    res = send_template_email(from_email,[fullemail],subject,
                              'teamrejectemail.html',d,**kwargs)

    return 1


@app.task
def handle_sendemail_member_dropped(email, name, teamname, managername,
                                    debug=False,**kwargs):
    fullemail = email
    subject = 'You were removed from ' + teamname
    from_email = 'Rowsandall <info@rowsandall.com>'

    siteurl = SITE_URL
    if debug:
        siteurl = SITE_URL_DEV

    d = {
        'first_name':name,
        'managername':managername,
        'teamname':teamname,
        'siteurl':siteurl,
    }
    res = send_template_email(from_email,[fullemail],subject,
                              'teamdropemail.html',d,**kwargs)


    return 1


@app.task
def handle_sendemail_team_removed(email, name, teamname, managername,
                                  debug=False,**kwargs):

    fullemail = email
    subject = 'You were removed from ' + teamname
    from_email = 'Rowsandall <info@rowsandall.com>'

    siteurl = SITE_URL
    if debug:
        siteurl = SITE_URL_DEV

    d = {
        'first_name':name,
        'managername':managername,
        'teamname':teamname,
        'siteurl':siteurl,
        }
    res = send_template_email(from_email,[fullemail],subject,
                              'teamremoveemail.html',d,**kwargs)


    return 1


@app.task
def handle_sendemail_invite_reject(email, name, teamname, managername,
                                   debug=False,**kwargs):
    fullemail = email
    subject = 'Your invitation to ' + name + ' was rejected'

    from_email = 'Rowsandall <info@rowsandall.com>'

    siteurl = SITE_URL
    if debug:
        siteurl = SITE_URL_DEV

    d = {
        'first_name':name,
        'managername':managername,
        'teamname':teamname,
        'siteurl':siteurl,
        }
    res = send_template_email(from_email,[fullemail],subject,
                              'teaminviterejectemail.html',d,**kwargs)

    return 1


@app.task
def handle_sendemail_invite_accept(email, name, teamname, managername,
                                   debug=False,**kwargs):
    fullemail = email
    subject = 'Your invitation to ' + name + ' was accepted'

    from_email = 'Rowsandall <info@rowsandall.com>'

    siteurl = SITE_URL
    if debug:
        siteurl = SITE_URL_DEV

    d = {
        'first_name':name,
        'managername':managername,
        'teamname':teamname,
        'siteurl':siteurl,
        }
    res = send_template_email(from_email,[fullemail],subject,
                              'teaminviteacceptemail.html',d,**kwargs)


    return 1


# Another simple task for debugging purposes
def add2(x, y,debug=False,**kwargs):
    return x + y
