import json
from django.core import serializers
from django.template import RequestContext
from django.shortcuts import render_to_response, render
from rest_framework import viewsets, mixins, status
from rest_framework.decorators import api_view, permission_classes, authentication_classes
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from sensor_net.models import Network, Node, Reading, Sensor, User
from sensor_net.serializers import NetworkSerializer, NodeSerializer, ReadingSerializer, SensorSerializer, AlertLogSerializer, AlertSerializer
from sensor_net.utils import build_map_view_model
from agent.models import Alert, AlertLog


def network(request):
    """
    Network controller should make available all nodes owned by the user associated with the request
    This code presently selects all user networks, but you can choose to show only networks associated with the logged in user

    user_networks = Network.objects.all().filter(user=request.user.id)

    """

    user_networks = Network.objects.all()

    nodes = []
    for user_network in user_networks:
        for node in user_network.nodes.all():
            nodes.append(node)
    map_view_model = build_map_view_model(nodes)
    context = {'nodes': nodes, 'map_view_model': map_view_model, 'user_networks': user_networks}
    return render_to_response('sensor_net/network.html', context, context_instance=RequestContext(request))



def historical(request):
    """
    As with network, this defaults to showing all networks. Filter by
    user_networks = Network.objects.all().filter(user=request.user.id)

    """
    readings = Reading.objects.all()[0:100]
    # user_networks = Network.objects.all()
    user_networks = Network.objects.all()
    nodes = []
    for user_network in user_networks:
        for node in user_network.nodes.all():
            nodes.append(node)

    context = {'readings': readings, 'user_networks': user_networks}
    return render_to_response('sensor_net/historical_readings.html', context, context_instance=RequestContext(request))

def dashboard(request):

    sensors = Sensor.objects.all()          # TODO filter to fetch only the user's sensors
    nodes = Node.objects.all()
    network = Network.objects.all()
    alerts = Alert.objects.all()
    alert_logs = AlertLog.objects.all().order_by('-id')[0:10]
    readings = Reading.objects.all().order_by('-date_of_reading')[0:25]
    #light_meter = Reading.objects.all().filter(sensor_id='photocell').order_by('-date_of_reading')[0]

    context = {'sensors': sensors, 'nodes': nodes, 'network' : network,
               'alerts': alerts, 'alert_logs': alert_logs ,
               'readings': readings}
    return render_to_response('sensor_net/dashboard.html', context, context_instance=RequestContext(request))

def light_meter(request):
    light_meter = Reading.objects.all().filter(sensor_id='photocell').order_by('-date_of_reading')[0]
    return render_to_response('sensor_net/light-meter.html', {'light_meter': light_meter},
                              context_instance=RequestContext(request))


# view for the partial recent-readings
def recent_readings(request):
    readings = Reading.objects.all().order_by('-date_of_reading')[0:25]
    return render_to_response('sensor_net/recent-readings.html',{ "readings":readings}, context_instance=RequestContext(request))


def recent_alerts(request):
    alerts = AlertLog.objects.all().order_by('-id')
    return render_to_response('sensor_net/recent-alerts.html', {'alert_logs': alerts}, context_instance=RequestContext(request))


def door_status(request):
    switch_readings = Reading.objects.all().filter(sensor_id='reed_switch')
    open_count = int(len(switch_readings)) / 2
    present_status = int(switch_readings.order_by('-date_of_reading')[0].val)   # the first one should be the most recent
    last_open = switch_readings.order_by('-date_of_reading')[0].date_of_reading
    context = {'switch_readings' : switch_readings, 'open_count' : open_count,
               'present_status': present_status, 'last_open': last_open}
    return render_to_response('sensor_net/door-status.html', context, context_instance=RequestContext(request))


def nodes(request):
    # user_networks = Network.objects.all().filter(user=request.user.id)
    user_networks = Network.objects.all()
    nodes = []
    for user_network in user_networks:
        for node in user_network.nodes.all():
            nodes.append(node)
    context = {'nodes': nodes}

    return render_to_response('sensor_net/nodes.html', context, context_instance=RequestContext(request))

def all_sensors(request):
    sensors = Sensor.objects.all()
    context = {'sensors':sensors}
    return render_to_response("sensor_net/sensors.html", context, context_instance=RequestContext(request))

def individual_node(request, nodeslug):
    """
    Queries db for a particular node, then filters by Reading object associated with that node.
    """
    node = Node.objects.get(id=nodeslug)
    readings = Reading.objects.all().filter(node=node).order_by('-date_of_reading')

    # get the max value to pass to the context
    # max_list = get_highs(nodeslug)
    # min_list = get_lows(nodeslug)
    # averages = get_averages(nodeslug)
    # context = {'node': node, 'readings': readings, 'max_vals': max_list, 'min_vals': min_list, 'avg_vals': averages}
    #context = {'node': node, 'readings': readings}
    context = {'node' : node, 'readings': readings}

    return render_to_response("sensor_net/individual_node.html", context, context_instance=RequestContext(request))

def individual_sensor(request, nodeslug):
    sensor = Sensor.objects.get(id=nodeslug)
    readings = Reading.objects.all().order_by('-date_of_reading').filter(sensor=sensor)
    context = {'sensor': sensor, 'readings': readings}
    return render_to_response('sensor_net/individual_sensor.html', context, context_instance=RequestContext(request))


# Begin API ViewSets

class NetworkListViewSet(viewsets.GenericViewSet, mixins.ListModelMixin):
    queryset = Network.objects.all()
    serializer_class = NetworkSerializer


class NodeListViewSet(viewsets.GenericViewSet, mixins.ListModelMixin, mixins.CreateModelMixin, mixins.UpdateModelMixin):
    queryset = Node.objects.all()
    serializer_class = NodeSerializer

    @authentication_classes(['TokenAuthentication'])
    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)


class NodeDetailViewSet(viewsets.GenericViewSet, mixins.ListModelMixin):
    queryset = Node.objects.all()
    serializer_class = NodeSerializer


class ReadingListViewSet(viewsets.GenericViewSet, mixins.ListModelMixin):
    queryset = Reading.objects.all()[0:100]
    serializer_class = ReadingSerializer

class ReadingDetailViewSet(viewsets.GenericViewSet, mixins.ListModelMixin, mixins.CreateModelMixin):
    queryset = Reading.objects.all().order_by('-date_of_reading')[0:100]
    serializer_class = ReadingSerializer

    @authentication_classes(['TokenAuthentication'])
    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)


class SensorListViewSet(viewsets.GenericViewSet, mixins.ListModelMixin):
    queryset = Sensor.objects.all()
    serializer_class = SensorSerializer


class SensorDetailViewSet(viewsets.GenericViewSet, mixins.ListModelMixin):
    queryset = Sensor.objects.all()
    serializer_class = SensorSerializer


class AlertLogViewSet(viewsets.GenericViewSet, mixins.ListModelMixin):
    queryset = AlertLog.objects.all()
    serializer_class = AlertLogSerializer


class AlertViewSet(viewsets.GenericViewSet, mixins.ListModelMixin):
    querySet = Alert.objects.all()
    serializer_class = AlertSerializer

