# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db.models import Count, Sum
from django.db.models.functions import TruncDate

import plotly.offline as plotly
import plotly.graph_objs as go

from core.utils import duration_parts

from reports import utils


def feeding_duration(instances):
    """
    Create a graph showing average duration of feeding instances over time.

    This function originally used the Avg() function from django.db.models but
    for some reason it was returning None any time the exact count of entries
    was equal to seven.

    :param instances: a QuerySet of Feeding instances.
    :returns: a tuple of the the graph's html and javascript.
    """
    totals = instances.annotate(date=TruncDate('start')) \
        .values('date') \
        .annotate(count=Count('id')) \
        .annotate(sum=Sum('duration')) \
        .order_by('-date')

    averages = []
    for total in totals:
        averages.append(total['sum']/total['count'])

    trace = go.Bar(
        name='Average duration',
        x=list(totals.values_list('date', flat=True)),
        y=[td.seconds/60 for td in averages],
        hoverinfo='text',
        textposition='outside',
        text=[_duration_string_minutes(td) for td in averages]
    )

    layout_args = utils.default_graph_layout_options()
    layout_args['barmode'] = 'stack'
    layout_args['title'] = '<b>Average Feeding Durations</b>'
    layout_args['xaxis']['title'] = 'Date'
    layout_args['xaxis']['rangeselector'] = utils.rangeselector_date()
    layout_args['yaxis']['title'] = 'Average duration (minutes)'

    fig = go.Figure({
        'data': [trace],
        'layout': go.Layout(**layout_args)
    })
    output = plotly.plot(fig, output_type='div', include_plotlyjs=False)
    return utils.split_graph_output(output)


def _duration_string_minutes(duration):
    """
    Format a "short" duration string with only minutes precision. This is
    intended to fit better in smaller spaces on a graph.
    :returns: a string of the form Xm.
    """
    h, m, s = duration_parts(duration)
    return '{}m'.format(m)

@@ -1007,16 +1007,24 @@
 race
+_avg
  = go.
-Ba
+Scatte
 r(%0A 
@@ -1055,16 +1055,51 @@
 ation',%0A
+        line=dict(shape='spline'),%0A
         
@@ -1281,21 +1281,16 @@
 string_m
-inute
 s(td) fo
@@ -1312,16 +1312,260 @@
 s%5D%0A    )
+%0A    trace_count = go.Scatter(%0A        name='Total feedings',%0A        mode='markers',%0A        x=list(totals.values_list('date', flat=True)),%0A        y=list(totals.values_list('count', flat=True)),%0A        yaxis='y2',%0A        hoverinfo='y'%0A    )
 %0A%0A    la
@@ -1617,45 +1617,8 @@
 s()%0A
-    layout_args%5B'barmode'%5D = 'stack'%0A
     
@@ -1853,16 +1853,219 @@
 inutes)'
+%0A    layout_args%5B'yaxis2'%5D = dict(layout_args%5B'yaxis'%5D)%0A    layout_args%5B'yaxis2'%5D%5B'title'%5D = 'Number of feedings'%0A    layout_args%5B'yaxis2'%5D%5B'overlaying'%5D = 'y'%0A    layout_args%5B'yaxis2'%5D%5B'side'%5D = 'right'
 %0A%0A    fi
@@ -2102,16 +2102,33 @@
 : %5Btrace
+_avg, trace_count
 %5D,%0A     
@@ -2313,21 +2313,16 @@
 string_m
-inute
 s(durati
@@ -2393,17 +2393,19 @@
 tes 
-precision
+and seconds
 . Th
@@ -2568,16 +2568,19 @@
 urn '%7B%7Dm
+%7B%7Ds
 '.format
@@ -2581,10 +2581,13 @@
 format(m
+, s
 )%0A

Change feeding durations to a scatter/line plot with number of feedings included.