# Python
from django.utils import timezone
from datetime import datetime
from datetime import timedelta
from datetime import date
import time
from django.db import IntegrityError
import uuid
from django.conf import settings

from utils import myqueue

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

from rowers.models import (
    Rower, Workout,
    GeoCourse, TrainingMicroCycle,TrainingMesoCycle,TrainingMacroCycle,
    TrainingPlan,PlannedSession,
    )

import metrics
import numpy as np
import dataprep

# Low Level functions - to be called by higher level methods
def add_workouts_plannedsession(ws,ps):
    result = 0
    comments = []
    errors = []

    # check if all sessions have same date
    dates = [w.date for w in ws]
    if (not all(d == dates[0] for d in dates)) and ps.sessiontype != 'challenge':
        errors.append('For tests and training sessions, selected workouts must all be done on the same date')
        return result,comments,errors
    
    # start adding sessions
    for w in ws:
        if w.date>=ps.startdate and w.date<=ps.enddate:
            w.plannedsession = ps
            w.save()
            result += 1
            comments.append('Attached workout %i to session' % w.id)
        else:
            errors.append('Workout %i did not match session dates' % w.id)

    return result,comments,errors
    

def remove_workout_plannedsession(w,ps):
    if w.plannedsession == ps:
        w.plannedsession = None
        w.save()
        return 1

    return 0

def clone_planned_session(ps):
    ps.save()
    ps.pk = None # creates new instance
    ps.save()

def timefield_to_seconds_duration(t):
    duration = t.hour*3600.
    duration += t.minute * 60.
    duration += t.second
    duration += t.microsecond/1.e6

    return duration

def get_session_metrics(ps):
    rowers = ps.rower.all()
    rscore = []
    trimp = []
    duration = []
    distance = []
    firstname = []
    lastname = []

    for r in rowers:
        rscorev = 0 
        trimpv = 0
        durationv = 0
        distancev = 0
        

        ws = Workout.objects.filter(user=r,plannedsession=ps)
        if len(ws) != 0:
            for w in ws:
                distancev += w.distance
                durationv += timefield_to_seconds_duration(w.duration)
                trimpv += dataprep.workout_trimp(w)
                rscorev += dataprep.workout_rscore(w)


            durationv /= 60.

        trimp.append(int(trimpv))
        duration.append(int(durationv))
        distance.append(int(distancev))
        rscore.append(int(rscorev))
        firstname.append(r.user.first_name)
        lastname.append(r.user.last_name)

    thedict = {
        'first_name':firstname,
        'last_name':lastname,
        'duration':duration,
        'distance':distance,
        'rscore':rscore,
        'trimp':trimp
    }

    return thedict

def is_session_complete(r,ps):
    status = 'not done'
    
    ws = Workout.objects.filter(user=r,plannedsession=ps)

    if len(ws)==0:
        today = date.today()
        if today > ps.enddate:
            status = 'missed'
            ratio = 0
            return ratio,status
        else:
            return 0,'not done'
    
    score = 0
    for w in ws:
        if ps.sessionmode == 'distance':
            score += w.distance
        elif ps.sessionmode == 'time':
            durationseconds = timefield_to_seconds_duration(w.duration)
            score += durationseconds
        elif ps.sessionmode == 'TRIMP':
            trimp = dataprep.workout_trimp(w)
            score += trimp
        elif ps.sessionmode == 'rScore':
            rscore = dataprep.workout_rscore(w)
            score += rscore

    value = ps.sessionvalue
    if ps.sessionunit == 'min':
        value *= 60.
    elif ps.sessionunit == 'km':
        value *= 1000.

    ratio = score/float(value)

    status = 'partial'

    if ps.sessiontype == 'session':
        if ps.criterium == 'exact':
            if ratio == 1.0:
                return ratio,'completed'
            else:
                return ratio,'partial'
        elif ps.criterium == 'minimum':
            if ratio > 1.0:
                return ratio,'completed'
            else:
                return ratio,'partial'
        else:
            if ratio>0.8 and ratio<1.2:
                return ratio,'completed'
            else:
                return ratio,'partial'
    elif ps.sessiontype == 'test':
        if ratio==1.0:
            return ratio,'completed'
        else:
            return ratio,'partial'
    elif ps.sessiontype == 'challenge':
        if ps.criterium == 'exact':
            if ratio == 1.0:
                return ratio,'completed'
            else:
                return ratio,'partial'
        elif ps.criterium == 'minimum':
            if ratio > 1.0:
                return ratio,'completed'
            else:
                return ratio,'partial'
        else:
            return ratio,'partial'
            
    else:
        return ratio,status
    
def rank_results(ps):
    return 1

def add_team_session(t,ps):
    ps.team.add(t)
    ps.save()

    return 1

def add_rower_session(r,ps):
    ps.rower.add(r)
    ps.save()
    
    return 1

def remove_team_session(t,ps):
    ps.team.remove(t)

    return 1

def remove_rower_session(r,ps):
    ps.rower.remove(r)

    return 1

def get_dates_timeperiod(timeperiod):
    # set start end date according timeperiod
    if timeperiod=='today':
        startdate=date.today()
        enddate=date.today()
    elif timeperiod=='tomorrow':
        startdate=date.today()+timezone.timedelta(days=1)
        enddate=date.today()+timezone.timedelta(days=1)
    elif timeperiod=='thisweek':
        today = date.today()
        startdate = date.today()-timezone.timedelta(days=today.weekday())
        enddate = startdate+timezone.timedelta(days=6)
    elif timeperiod=='thismonth':
        today = date.today()
        startdate = today.replace(day=1)
        enddate = startdate+timezone.timedelta(days=32)
        enddate = enddate.replace(day=1)
        enddate = enddate-timezone.timedelta(days=1)
    elif timeperiod=='lastweek':
        today = date.today()
        enddate = today-timezone.timedelta(days=today.weekday())-timezone.timedelta(days=1)
        startdate = enddate-timezone.timedelta(days=6)
    elif timeperiod=='lastmonth':
        today = date.today()
        startdate = today.replace(day=1)
        startdate = startdate-timezone.timedelta(days=3)
        startdate = startdate.replace(day=1)
        enddate = startdate+timezone.timedelta(days=32)
        enddate = enddate.replace(day=1)
        enddate = enddate-timezone.timedelta(days=1)
    else:
        startdate = date.today()
        enddate = date.today()

    return startdate,enddate

def get_sessions(r,startdate=date.today(),
                 enddate=date.today()+timezone.timedelta(+1000)):

    sps = PlannedSession.objects.filter(
        rower__in=[r],
        startdate__lte=enddate,
        enddate__gte=startdate,
    ).order_by("startdate","enddate")
        
    return sps

def get_sessions_manager(manager,startdate=date.today(),
                 enddate=date.today()+timezone.timedelta(+1000)):

    sps = PlannedSession.objects.filter(
        manager=manager,
        startdate__lte=enddate,
        enddate__gte=startdate,
    ).order_by("startdate","enddate").exclude(team__isnull=True)
        
    return sps

def get_workouts_session(r,ps):
    ws = Workout.objects.filter(user=r,plannedsession=ps)

    return ws

def update_plannedsession(ps,cd):
    for attr, value in cd.items():
        setattr(ps, attr, value)

    ps.save()

    return 1,'Planned Session Updated'
