from rest_framework import generics, views, status
from rest_framework.response import Response
from django.shortcuts import get_list_or_404
from rest_framework.permissions import IsAuthenticated
from  photo_log.models import (
        PhotoGroup,
        Photo,
        PhotoLog,
        PhotoTag,
        PhotoLogTemplate,
)
from .serializers import (
        PhotoGroupSerializer,
        PhotosSerializer,
        PhotoSerializer, 
        AddPhotoSerializer, 
        PhotoUpdateSerializer, 
        PhotoLogSerializer,
        PhotoLogsSerializer,
        PhotoTagSerializer,
        PhotoLogTemplateSerializer,
        UserSerializer,
)

from photo_log import tasks

from django.db.models import FileField
from django.core.files.uploadedfile import InMemoryUploadedFile
from django.core.files.base import ContentFile
from django.contrib.auth import get_user_model

from io import BytesIO
from PIL import Image, ExifTags


class PhotoTagsAPIView(generics.ListAPIView):
    queryset = PhotoTag.objects.all()
    serializer_class = PhotoTagSerializer


class CreatePhotoTagAPIView(generics.CreateAPIView):
    queryset = PhotoTag.objects.all()
    serializer_class = PhotoTagSerializer


class RetrieveUpdateDestroyPhotoTagAPIView(generics.RetrieveUpdateDestroyAPIView):
    queryset = PhotoTag.objects.all()
    serializer_class = PhotoTagSerializer


class PhotoLogTemplatesAPIView(generics.ListAPIView):
    queryset = PhotoLogTemplate.objects.all()
    serializer_class = PhotoLogTemplateSerializer


class CreatePhotoLogTemplateAPIView(generics.CreateAPIView):
    queryset = PhotoLogTemplate.objects.all()
    serializer_class = PhotoLogTemplateSerializer


class RetrieveUpdateDestroyPhotoLogTemplateAPIView(generics.RetrieveUpdateDestroyAPIView):
    queryset = PhotoLogTemplate.objects.all()
    serializer_class = PhotoLogTemplateSerializer


class PhotoGroupAPIView(generics.ListAPIView):
    serializer_class = PhotoGroupSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        queryset = PhotoGroup.objects.all()

        user = self.request.user
        if not user.is_superuser:
            queryset = queryset.filter(owner=user)

        return queryset


class PhotosAPIView(generics.ListAPIView):
    
    serializer_class = PhotoSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        queryset = Photo.objects.all()

        user = self.request.user
        if not user.is_superuser:
            queryset = queryset.filter(owner=user)

        self.serializer_class = PhotosSerializer

        photogroup = self.request.query_params.get('photogroup')
        if photogroup is not None:
            queryset = get_list_or_404(queryset, group=photogroup)
            self.serializer_class = PhotoSerializer

        return queryset


class PhotoAPIView(generics.RetrieveAPIView):
        serializer_class = PhotoSerializer
        queryset = Photo.objects.all()


class AddPhotoAPIView(generics.CreateAPIView):
    queryset = Photo.objects.all()
    serializer_class = AddPhotoSerializer
    permission_classes = [IsAuthenticated]

    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)


class AddPhotoGroupAPIView(generics.CreateAPIView):
    queryset = PhotoGroup.objects.all()
    serializer_class = PhotoGroupSerializer
    permission_classes = [IsAuthenticated]

    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)


class PhotoLogAPIView(generics.RetrieveAPIView):
        serializer_class = PhotoLogSerializer
        queryset = PhotoLog.objects.all()


class PhotoLogsAPIView(generics.ListAPIView):
    serializer_class = PhotoLogsSerializer
    queryset = PhotoLog.objects.all()


class AddPhotoLogAPIView(generics.CreateAPIView):
    queryset = PhotoLog.objects.all()
    serializer_class = PhotoLogSerializer


class DestroyPhotoLogAPIView(generics.DestroyAPIView):
    queryset = PhotoLog.objects.all()
    serializer_class = PhotoLogSerializer


class DestroyPhotoAPIView(generics.DestroyAPIView):
    queryset = Photo.objects.all()
    serializer_class = PhotoSerializer


class UpdatePhotoLogAPIView(generics.UpdateAPIView):
    queryset = PhotoLog.objects.all()
    serializer_class = PhotoLogSerializer
    lookup_field = 'pk'

    def update(self, request, *args, **kwargs):
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=True)

        if serializer.is_valid():
            serializer.save()
            return Response({'ok'})
        else:
            return Response({"error": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)


class UpdatePhotoAPIView(generics.UpdateAPIView):
    queryset = Photo.objects.all()
    serializer_class = PhotoUpdateSerializer
    lookup_field = 'pk'

    def update(self, request, *args, **kwargs):
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=True)

        if serializer.is_valid():
            serializer.save()
            return Response({'ok'})
        else:
            return Response({"error": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
            

class GeneratePhotoLogAPIView(generics.RetrieveAPIView):

    queryset = PhotoLog.objects.all()
    serializer_class = PhotoLogSerializer

    def get(self, request, *args, **kwargs):
        photolog = self.get_object()
        photolog_data = self.get_serializer(photolog).data

        if photolog_data:
            tasks.generate_photo_log_chain(
                photolog_data['id'],
            )

            return Response({'status': 'task created'})

        return Response({"error": "Not Found"}, status=status.HTTP_404_NOT_FOUND)


class AutoCropPhotoAPIView(generics.RetrieveAPIView):

    queryset = Photo.objects.all()
    serializer_class = PhotoSerializer

    def get(self, request, *args, **kwargs):
        photo = None

        photo_data = self.get_serializer(self.get_object()).data

        if photo_data:
            photo_id = photo_data['id']

            if photo_id:
                if not 'mode' in request.query_params:
                    return Response({'error':'cropping mode not specified (auto, bbox or inters)'}, status=status.HTTP_400_BAD_REQUEST)
                mode = request.query_params.get('mode')

                photo = Photo.objects.get(id=photo_id)

                cropped_img = photo.cropped_image
                if cropped_img:
                    cropped_img = cropped_img.name
                else:
                    cropped_img = None
                
                if mode == 'bbox':
                    tasks.crop_image_bbox_chain(
                        photo.id,
                        photo.original_image.name,
                        photo.bbox_coords,
                        photo.rotate,
                        cropped_img
                    )
                elif mode == 'auto' or mode == 'inters':
                    # TODO: mode 'inters': just calculate intersections w/o saving the cropped image
                    tasks.crop_image_auto_chain(
                        photo.id,
                        photo.original_image.name,
                        cropped_img
                    )
                else:
                    return Response({'error':'invalid cropping mode (auto, bbox or inters)'}, status=status.HTTP_400_BAD_REQUEST)

        if photo:
            return self.retrieve(request, *args, **kwargs)

        return Response({"error": "Not Found"}, status=status.HTTP_404_NOT_FOUND)


class UsersAPIView(generics.ListAPIView):
    queryset = get_user_model().objects.all()
    serializer_class = UserSerializer
