# *coding: utf-8*
from api.serializers import *
from oauth2_provider.ext.rest_framework import TokenHasReadWriteScope
from django.shortcuts import render, HttpResponse
import django_filters
from backoffice.models import *
from api.views.user import *
from api.serializers import *
from django.db.models import F,Q
from django.shortcuts import HttpResponse
from django.http import JsonResponse
import django_filters
from django.db.models import Lookup
from django.db.models.fields import Field
from django.db import connection
from collections import namedtuple
import json
from base64 import b64decode
from django.core.files.base import ContentFile

@Field.register_lookup
class NotEqual(Lookup):
    lookup_name = 'ne'

    def as_sql(self, compiler, connection):
        lhs, lhs_params = self.process_lhs(compiler, connection)
        rhs, rhs_params = self.process_rhs(compiler, connection)
        params = lhs_params + rhs_params
        return '%s <> %s' % (lhs, rhs), params

class NoChatFilter(django_filters.rest_framework.FilterSet):
    class Meta:
        model = Chat
        fields = '__all__'

class ChatListView(generics.ListAPIView):
    """
        Renvoi la liste des chats disponible pour un user ou pour chat (id) donné

        Parametres : id ou refUser ou forUser ou mixte : (userId,forUser)
    """
    #permission_classes = [permissions.IsAuthenticated, TokenHasReadWriteScope]
    queryset = Chat.objects.all()
    serializer_class = ChatSerializer
    #filter_fields = ('refUserOne')
    ordering_fields = ('createdAt')
    ordering = ('-createdAt',)
    pagination_class = NoPaginationResults
    def get_queryset(self):
        userId = self.request.query_params.get('refUser', None)
        logger.info("userID %s"%self.request.query_params)
        if userId is None:
            id = self.request.query_params.get('id', None)
            if id is None:
                queryset = Chat.objects.all().select_related('refUserOne').select_related('refUserTwo')
            else:
                queryset = Chat.objects.get(pk=id).select_related('refUserOne').select_related('refUserTwo')
            return queryset
        else:
            logger.info("on filtre")
            queryset = Chat.objects.filter(Q(refUserOne=userId) | Q(refUserTwo=userId)).select_related('refUserOne').select_related('refUserTwo')
            return queryset


class ChatBetweenUserListView(generics.ListAPIView):
    """
        Renvoi la liste des chats disponible pour un user ou pour chat (id) donné

        Parametres : refUserOne refUserTwo
    """
    #permission_classes = [permissions.IsAuthenticated, TokenHasReadWriteScope]
    queryset = Chat.objects.all()
    serializer_class = ChatSerializer
    # filter_fields = ('refUserOne')
    ordering_fields = ('createdAt')
    ordering = ('-createdAt',)
    pagination_class = NoPaginationResults

    def get_queryset(self):
        refUserOne = self.request.query_params.get('refUserOne', None)
        refUserTwo = self.request.query_params.get('refUserTwo', None)
        logger.info("userID %s" % self.request.query_params)
        queryset = Chat.objects.filter(Q(refUserOne=refUserOne,refUserTwo=refUserTwo) | Q(refUserOne=refUserTwo,refUserTwo=refUserOne)).select_related(
                'refUserOne').select_related('refUserTwo')
        return queryset


### On remove la classe filter qui empêche de renvoyer toutes les données.
class AllChatListView(generics.ListAPIView):
    """
        Renvoi la liste des chats auxquels un utilisateur (userId) participe.
        La différence avec le WS précédent est que l'utilisateur peut être à l'origine du chat (userId)
        ou être le destinaire du chat (si quelqu'un a commencé à lui parler en 1ere) (forUser=userId)

        Parameter : userId
    """
    #permission_classes = [permissions.IsAuthenticated, TokenHasReadWriteScope]
    queryset = Chat.objects.all()
    serializer_class = ChatSerializer
    ordering_fields = ('createdAt')
    ordering = ('-createdAt',)
    filter_class = NoChatFilter
    def get_queryset(self):
        userId = self.request.query_params.get('refUser', None)
        if userId is None:
            id = self.request.query_params.get('id', None)
            if id is None:
                queryset = Chat.objects.all().select_related('refUserOne').select_related('refUserTwo')
            else:
                queryset = Chat.objects.get(pk=id).select_related('refUserOne').select_related('refUserTwo')
            return queryset
        else:
            queryset = Chat.objects.filter(Q(refUserOne=userId) | Q(refUserTwo=userId)).select_related('refUserOne').select_related('refUserTwo')
            return queryset

class AddChatView(generics.CreateAPIView):
    #permission_classes = [permissions.IsAuthenticated, TokenHasReadWriteScope]
    queryset = Chat.objects.all()
    serializer_class = CreateChatSerializer


class ChatDetailView(generics.RetrieveUpdateDestroyAPIView):
    #permission_classes = [permissions.IsAuthenticated, TokenHasReadWriteScope]
    queryset = Chat.objects.all()
    serializer_class = ChatSerializer


class ChatMediaListView(generics.ListCreateAPIView):
    def post(self, request, format=None):
        if request.method == "POST":
            data = request._data
            refChat = data['refChat']
            image_base64 = data['media']
            fileName = data['filename']
            format, imgstr = image_base64.split(';base64,')  # format ~= data:image/X,
            # Get user
            chat = Chat.objects.get(pk=refChat)
            chatMedia = ChatMedia()
            chatMedia.refChat = chat
            chatMedia.media = ContentFile(b64decode(imgstr), name=fileName)
            chatMedia.save()
            newdict = {'media': chatMedia.media.name}
            return JsonResponse(newdict, safe=False)
        else:
            HttpResponse(status=404)


class ChatMessageListView(generics.ListAPIView):
    #permission_classes = [permissions.IsAuthenticated, TokenHasReadWriteScope]
    serializer_class = ChatMessageSerializer

    def get_queryset(self):
        chatId = self.request.query_params.get('refChat', None)
        unread = self.request.query_params.get('unread', None)
        sender = self.request.query_params.get('senderId', None)
        if chatId:
            if unread:
                queryset = ChatMessage.objects.filter(refChat=chatId,isRead=False,senderId__ne=sender).order_by('id').select_related('senderId')
            else:
                queryset = ChatMessage.objects.filter(refChat=chatId).order_by('id').select_related('senderId')
        else:
            queryset = ChatMessage.objects.all().order_by('id').select_related('senderId')

        return queryset

class AddMessageView(generics.CreateAPIView):
    #permission_classes = [permissions.IsAuthenticated, TokenHasReadWriteScope]
    queryset = ChatMessage.objects.all()
    serializer_class = CreateChatMessageSerializer

class MessageDetailView(generics.RetrieveUpdateDestroyAPIView):
    #permission_classes = [permissions.IsAuthenticated, TokenHasReadWriteScope]
    queryset = ChatMessage.objects.all()
    serializer_class = ChatMessageSerializer


def namedtuplefetchall(cursor):
    "Return all rows from a cursor as a namedtuple"
    desc = cursor.description
    nt_result = namedtuple('ChatMessage', [col[0] for col in desc])
    return [nt_result(*row) for row in cursor.fetchall()]

@api_view(['GET'])
def nbNewMessage(request):
    if request.method == 'GET':
        userId = request.query_params.get('userId', None)
        query = 'select distinct (backoffice_chatmessage.\"refChat_id\") from backoffice_chatmessage'
        query +=' join backoffice_chat on backoffice_chat.id=backoffice_chatmessage.\"refChat_id\"'
        query += ' where (backoffice_chat.\"refUserOne_id\"=%s or backoffice_chat.\"refUserTwo_id\"=%s) and \"backoffice_chatmessage\".\"isRead\"=\'0\'' % (str(userId),str(userId))
        query += ' and \"backoffice_chatmessage\".\"senderId_id\"!=%s' %(str(userId))
        with connection.cursor() as cursor:
            cursor.execute(query)
            listeChat = namedtuplefetchall(cursor)
        return HttpResponse(json.dumps(listeChat), content_type='application/json')
    else:
        return HttpResponse.HttpResponseServerError


class ChatFullDetailListView(generics.ListAPIView):
    """
        Renvoi la liste des chats disponible pour un user ou pour chat (id) donné

        Parametres : id ou refUser ou forUser ou mixte : (userId,forUser)
    """
    #permission_classes = [permissions.IsAuthenticated, TokenHasReadWriteScope]
    queryset = Chat.objects.all()
    serializer_class = ChatFullDetailSerializer
    #filter_fields = ('refUserOne')
    ordering_fields = ('createdAt')
    ordering = ('-createdAt',)
    pagination_class = NoPaginationResults

    def get_queryset(self):
        userId = self.request.query_params.get('refUser', None)
        if userId is None:
            id = self.request.query_params.get('id', None)
            if id is None:
                queryset = Chat.objects.all().select_related('refUserOne').select_related('refUserTwo')
            else:
                queryset = Chat.objects.get(pk=id).select_related('refUserOne').select_related('refUserTwo')
            return queryset
        else:
            queryset = Chat.objects.filter(Q(refUserOne=userId) | Q(refUserTwo=userId)).select_related('refUserOne').select_related('refUserTwo')
            return queryset
