from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
import json

from .serializers import *
from .imagehandler import *

image_handler = ImageHandler()

# Create your views here.
class Get_All_Uploaded_Images(APIView):
    serializer_class = ImageSerializer

    def get(self, request, *args, **kwargs):
        try:
            li = Image.objects.all()
            serializer = self.serializer_class(li, many=True)
            
            if serializer.data != []:
                return Response(status=status.HTTP_200_OK, data={"status": status.HTTP_200_OK, "details": serializer.data})
            else:
                return Response(status=status.HTTP_204_NO_CONTENT, data={"status": status.HTTP_204_NO_CONTENT, "details": "Empty Docs List"})
        
        except Exception as e:
            print("Exception encountered")
            print("*"*20)
            print(e)

            exception_name = type(e).__name__
            return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": "Exception encountered: " + str(exception_name)})
        
class Get_Editing_History(APIView):
    def get(self, request, *args, **kwargs):
        try:
            data = request.data

            imageId = ''
            if 'imageID' in data:
                if data['imageID'] != '':
                    imageId = data['imageID']
                else:
                    return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "imageID".'})
            else:
                return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Key "imageID" is not in the data.'})
            print(f"Image ID: {imageId}")

            imageId_list = Image.objects.values_list('imageID', flat=True)
            if imageId in imageId_list:

                select_item = Image.objects.filter(imageID=imageId).order_by('uploadtime').last()

                if json.loads(select_item.editinghistory) != []:
                    return Response(status=status.HTTP_200_OK, data={"status": status.HTTP_200_OK, "details": {'history': select_item.editinghistory}})
                else:
                    return Response(status=status.HTTP_204_NO_CONTENT, data={"status": status.HTTP_204_NO_CONTENT, "details": "Empty Editing History"})
            
            print("ImageID not found in the database.")
            return Response(status=status.HTTP_404_NOT_FOUND, data={"status": status.HTTP_404_NOT_FOUND, "details": "ImageID not found in the database."})
        
        except Exception as e:
            print("Exception encountered")
            print("*"*20)
            print(e)

            exception_name = type(e).__name__
            return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": "Exception encountered: " + str(exception_name)})

class Upload_Image(APIView):
    serializer_class = ImageUploadSerializer

    def post(self, request, *args, **kwargs):
        try:
            data = request.data

            image = ''
            if 'image' in data:
                if data['image'] != '':
                    image = data['image']
                else:
                    return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "image".'})
            else:
                return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Key "image" is not in the data.'})
            print(f"Image: {image}")

            if image_handler.check_image_data(image=image):

                if image_handler.check_doc_type(doc=image):

                    image_handler.get_imageID_uploadtime(file_category=FileCategory.INPUT_BASE64)

                    if image_handler.convert_file_to_base64(file_category=FileCategory.INPUT_BASE64, doc=image):
                        
                        if image_handler.originalimagestream != []:
                                
                            post_data = {
                                'imageID': image_handler.imageID, 
                                'uploadtime': image_handler.uploadtime,
                                'originalfolderpath': image_handler.originalfolderpath, 
                                'originalfilename': json.dumps(image_handler.originalimagename), 
                                'originalfiletype': json.dumps(image_handler.originalimagetype), 
                                'originalfilestream': json.dumps(image_handler.originalimagestream),
                                'editinghistory': json.dumps(image_handler.editinghistory)
                                }
                            
                            print(f"Post Data: {post_data}")
                            
                            serializer = self.serializer_class(data=post_data)
                            print("Serializer:\n", serializer)
                            if serializer.is_valid():
                                serializer.save()
                                return Response(status=status.HTTP_201_CREATED, data={"status": status.HTTP_201_CREATED, "details": serializer.data})
                            
                            print("Failed: Data is not valid.")
                            return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": "Data is not valid."})
                        
                        print("Failed: Response could not be obtained.")
                        return Response(status=status.HTTP_204_NO_CONTENT, data={"status": status.HTTP_204_NO_CONTENT, "details": "Response could not be obtained."})
                    
                    print("Failed: Image could not be converted to base64 format.")
                    return Response(status=status.HTTP_412_PRECONDITION_FAILED, data={"status": status.HTTP_412_PRECONDITION_FAILED, "details": "Image could not be converted to base64 format."})
                
                print("Failed: Invalid filetype.")
                return Response(status=status.HTTP_206_PARTIAL_CONTENT, data={"status": status.HTTP_206_PARTIAL_CONTENT, "details": "Invalid filetype."})
            
            print(f"Failed: Empty Image Data: {str(image)}.")
            return Response(status=status.HTTP_204_NO_CONTENT, data={"status": status.HTTP_204_NO_CONTENT, "details": f"Empty Image Data: {str(image)}."})
        
        except Exception as e:
            print("Exception encountered")
            print("*"*20)
            print(e)

            exception_name = type(e).__name__
            return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": "Exception encountered: " + str(exception_name)})

class Upload_Folder(APIView):
    serializer_class = ImageUploadSerializer

    def post(self, request, *args, **kwargs):
        try:
            data = request.data

            folderpath = ''
            if 'folderPath' in data:
                if data['folderPath'] != '':
                    folderpath = data['folderPath']
                else:
                    return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "folderPath".'})
            else:
                return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Key "folderPath" is not in the data.'})
            print(f"Input Folderpath: {folderpath}")

            if image_handler.check_folder_data(folderpath=folderpath):

                type_check_result, skipped_files = image_handler.check_folder_type(folderpath=folderpath)
                if type_check_result:

                    image_handler.get_imageID_uploadtime(file_category=FileCategory.INPUT_FOLDERPATH)

                    if image_handler.convert_file_to_base64(file_category=FileCategory.INPUT_FOLDERPATH):
                        if image_handler.originalimagestream != []:
                                
                            post_data = {
                                'imageID': image_handler.imageID, 
                                'uploadtime': image_handler.uploadtime,
                                'originalfolderpath': image_handler.originalfolderpath, 
                                'originalimagename': json.dumps(image_handler.originalimagename), 
                                'originalimagetype': json.dumps(image_handler.originalimagetype), 
                                'originalimagestream': json.dumps(image_handler.originalimagestream),
                                'edittedimagetype': json.dumps(image_handler.edittedimagetype),
                                'edittedimagestream': json.dumps(image_handler.edittedimagestream),
                                'editinghistory': json.dumps(image_handler.editinghistory),
                                'skippedfiles': json.dumps(skipped_files)
                                }
                            
                            print(f"Post Data: {post_data}")
                            
                            serializer = self.serializer_class(data=post_data)
                            print("Serializer:\n", serializer)
                            if serializer.is_valid():
                                serializer.save()
                                return Response(status=status.HTTP_201_CREATED, data={"status": status.HTTP_201_CREATED, "details": serializer.data})
                            
                            print("Failed: Data is not valid.")
                            return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": "Data is not valid."})
                        
                        print("Failed: Response could not be obtained.")
                        return Response(status=status.HTTP_204_NO_CONTENT, data={"status": status.HTTP_204_NO_CONTENT, "details": "Response could not be obtained."})
                    
                    print("Failed: Image could not be converted to base64 format.")
                    return Response(status=status.HTTP_412_PRECONDITION_FAILED, data={"status": status.HTTP_412_PRECONDITION_FAILED, "details": "Image could not be converted to base64 format."})
                
                print("Failed: Invalid filetype.")
                return Response(status=status.HTTP_206_PARTIAL_CONTENT, data={"status": status.HTTP_206_PARTIAL_CONTENT, "details": "Invalid filetype."})
            
            print("Failed: Empty Folder.")
            return Response(status=status.HTTP_204_NO_CONTENT, data={"status": status.HTTP_204_NO_CONTENT, "details": "Empty Folder."})
        
        except Exception as e:
            print("Exception encountered")
            print("*"*20)
            print(e)

            exception_name = type(e).__name__
            return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": "Exception encountered: " + str(exception_name)})

class Download_File(APIView):

    def post(self, request, *args, **kwargs):
        try:
            data = request.data

            imageId = ''
            if 'imageID' in data:
                if data['imageID'] != '':
                    imageId = data['imageID']
                else:
                    return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "imageID".'})
            else:
                return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Key "imageID" is not in the data.'})
            print(f"Image ID: {imageId}")

            output_filename = None
            if 'fileName' in data:
                if data['fileName'] != '':
                    output_filename = data['fileName']
                else:
                    return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "fileName".'})

            output_filepath = None
            if 'filePath' in data:
                if data['filePath'] != '':
                    output_filepath = data['filePath']
                else:
                    return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "filePath".'})
                
            print(f"Output Filename: {output_filename}")
            print(f"Output Filepath: {output_filepath}")

            imageId_list = Image.objects.values_list('imageID', flat=True)
            if imageId in imageId_list:

                select_item = Image.objects.filter(imageID=imageId).order_by('uploadtime').last()
                if select_item.originalimagestream != []:
                    
                    image_handler.assign_select_item_details(select_item.imageID, select_item.uploadtime, select_item.originalfolderpath, 
                                                        json.loads(select_item.originalimagename), json.loads(select_item.originalimagetype), 
                                                        json.loads(select_item.originalimagestream), json.loads(select_item.edittedimagetype),
                                                        json.loads(select_item.edittedimagestream), json.loads(select_item.editinghistory))
                    
                    if image_handler.edittedimagestream != []:
                        image_handler.declare_output_filepath_details(output_filename=output_filename, output_filepath=output_filepath)
                        
                        if image_handler.save_to_output_folder():
                            select_item.edittedfolderpath = image_handler.edittedfolderpath
                            select_item.edittedimagename = image_handler.edittedimagename
                            select_item.editinghistory = json.dumps(image_handler.editinghistory)
                            select_item.save()
                            return Response(status=status.HTTP_201_CREATED, 
                                            data={"status": status.HTTP_201_CREATED, 
                                                  "details": {
                                                      'editted_folderpath': select_item.edittedfolderpath,
                                                      'editted_imagename': select_item.edittedimagename,
                                                      'editted_imagetype': select_item.edittedimagetype,
                                                      'editted_imagestream': select_item.edittedimagestream,
                                                      'editinghistory': json.dumps(image_handler.editinghistory)
                                            }})
                        
                        print("Failed: File could not be saved to output folder.")
                        return Response(status=status.HTTP_206_PARTIAL_CONTENT, data={"status": status.HTTP_206_PARTIAL_CONTENT, "details": "File could not be saved to output folder."})
                    
                    print("Failed: No changes done. Download cannot be initiated without making any changes.")
                    return Response(status=status.HTTP_205_RESET_CONTENT, data={"status": status.HTTP_205_RESET_CONTENT, "details": "No changes done. Download cannot be initiated without making any changes."})
                    
                print("Failed: Response could not be obtained.")
                return Response(status=status.HTTP_204_NO_CONTENT, data={"status": status.HTTP_204_NO_CONTENT, "details": "Response could not be obtained."})
            
            print("Failed: ImageID not found in the database.")
            return Response(status=status.HTTP_404_NOT_FOUND, data={"status": status.HTTP_404_NOT_FOUND, "details": "ImageID not found in the database."})
        
        except Exception as e:
            print("Exception encountered")
            print("*"*20)
            print(e)

            exception_name = type(e).__name__
            return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": "Exception encountered: " + str(exception_name)})
        
class Convert_Image(APIView):

    def post(self, request, *args, **kwargs):
        try:
            data = request.data

            imageId = ''
            if 'imageID' in data:
                if data['imageID'] != '':
                    imageId = data['imageID']
                else:
                    return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "imageID".'})
            else:
                return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Key "imageID" is not in the data.'})
            print(f"Image ID: {imageId}")

            output_filetype = ''
            if 'fileType' in data:
                if data['fileType'] != '':
                    output_filetype = str.lower(data['fileType']) if data['fileType'][0] == '.' else '.' + str.lower(data['fileType'])
                else:
                    return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "fileType".'})
            else:
                return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Key "fileType" is not in the data.'})
            print(f"Output Filetype: {output_filetype}")

            if image_handler.check_file_extension(output_filetype):
                imageId_list = Image.objects.values_list('imageID', flat=True)
                if imageId in imageId_list:

                    select_item = Image.objects.filter(imageID=imageId).order_by('uploadtime').last()
                    if select_item.originalimagestream != []:

                        image_handler.assign_select_item_details(select_item.imageID, select_item.uploadtime, select_item.originalfolderpath, 
                                                            json.loads(select_item.originalimagename), json.loads(select_item.originalimagetype), 
                                                            json.loads(select_item.originalimagestream), json.loads(select_item.edittedimagetype),
                                                            json.loads(select_item.edittedimagestream), json.loads(select_item.editinghistory))
                        
                        if image_handler.convert_image_format(output_filetype):
                                
                            if image_handler.edittedimagestream != []:
                               
                                select_item.edittedimagetype = json.dumps(image_handler.edittedimagetype)
                                select_item.edittedimagestream = json.dumps(image_handler.edittedimagestream)
                                select_item.editinghistory = json.dumps(image_handler.editinghistory)
                                select_item.save()
                                return Response(status=status.HTTP_201_CREATED, 
                                                data={"status": status.HTTP_201_CREATED, 
                                                    "details": {
                                                    'editted_imagetype': select_item.edittedimagetype,
                                                    'editted_imagestream': select_item.edittedimagestream,
                                                    'editing_history': select_item.editinghistory
                                                }})
                                
                            print("Failed: No changes done. Download cannot be initiated without making any changes.")
                            return Response(status=status.HTTP_205_RESET_CONTENT, data={"status": status.HTTP_205_RESET_CONTENT, "details": "No changes done. Download cannot be initiated without making any changes."})
                
                        print(f"Failed: Image could not be converted to {output_filetype} format.")
                        return Response(status=status.HTTP_412_PRECONDITION_FAILED, data={"status": status.HTTP_412_PRECONDITION_FAILED, "details": f"Image could not be converted to {output_filetype} format."})
                        
                    print("Failed: Response could not be obtained.")
                    return Response(status=status.HTTP_204_NO_CONTENT, data={"status": status.HTTP_400_BAD_REQUEST, "details": "Response could not be obtained."})
                
                print("Failed: ImageID not found in the database.")
                return Response(status=status.HTTP_404_NOT_FOUND, data={"status": status.HTTP_404_NOT_FOUND, "details": "ImageID not found in the database."})
            
            print("Failed: Invalid filetype.")
            return Response(status=status.HTTP_206_PARTIAL_CONTENT, data={"status": status.HTTP_400_BAD_REQUEST, "details": "Invalid filetype."})

        except Exception as e:
            print("Exception encountered")
            print("*"*20)
            print(e)

            exception_name = type(e).__name__
            return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": "Exception encountered: " + str(exception_name)})
        
class Resize_Image(APIView):
    
    def post(self, request, *args, **kwargs):
        try:
            data = request.data

            imageId = ''
            if 'imageID' in data:
                if data['imageID'] != '':
                    imageId = data['imageID']
                else:
                    return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "imageID".'})
            else:
                return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Key "imageID" is not in the data.'})
            print(f"Image ID: {imageId}")

            imageId_list = Image.objects.values_list('imageID', flat=True)
            if imageId in imageId_list:

                select_item = Image.objects.filter(imageID=imageId).order_by('uploadtime').last()
                if select_item.originalimagestream != []:

                    image_handler.assign_select_item_details(select_item.imageID, select_item.uploadtime, select_item.originalfolderpath, 
                                                        json.loads(select_item.originalimagename), json.loads(select_item.originalimagetype), 
                                                        json.loads(select_item.originalimagestream), json.loads(select_item.edittedimagetype),
                                                        json.loads(select_item.edittedimagestream), json.loads(select_item.editinghistory))  
                    resizeBy = ''
                    if 'resizeBy' in data:
                        if data['resizeBy'] != '':
                            resizeBy = data['resizeBy']
                        else:
                            return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "resizeBy".'})
                    else:
                        return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Key "resizeBy" is not in the data.'})
                    print(f"Resize By: {resizeBy}")

                    if resizeBy == ResizeOptions.BY_IMAGESIZE.value:
                        
                        resizeImageSizeBy = ''
                        if 'resizeImageSizeBy' in data:
                            if data['resizeImageSizeBy'] != '':
                                resizeImageSizeBy = data['resizeImageSizeBy']
                            else:
                                return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "resizeImageSizeBy".'})
                        else:
                            return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Key "resizeImageSizeBy" is not in the data.'})
                        print(f"Resize Image Size By: {resizeImageSizeBy}")

                        width = 0
                        height = 0

                        if resizeImageSizeBy == ResizeByImageSizeOptions.BY_DIMENSIONS.value:
                            
                            aspectRatioLock = 0
                            if 'aspectRatioLock' in data:
                                if data['aspectRatioLock'] != '':
                                    aspectRatioLock = int(data['aspectRatioLock'])
                                else:
                                    return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "aspectRatioLock".'})
                            else:
                                return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Key "aspectRatioLock" is not in the data.'})
                            print(f"Aspect Ratio Lock: {aspectRatioLock}")

                            if aspectRatioLock:
                                
                                resizeByDimension = ''
                                if 'resizeByDimension' in data:
                                    if data['resizeByDimension'] != '':
                                        resizeByDimension = data['resizeByDimension']
                                    else:
                                        return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "resizeByDimension".'})
                                else:
                                    return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Key "resizeByDimension" is not in the data.'})
                                print(f"Resize By Dimension: {resizeByDimension}")

                                if resizeByDimension != Dimension.WIDTH.value and resizeByDimension != Dimension.HEIGHT.value:
                                    
                                    print(f"Failed: Invalid Resize By Dimension Option: {resizeByDimension}.")
                                    return Response(status=status.HTTP_206_PARTIAL_CONTENT, data={"status": status.HTTP_400_BAD_REQUEST, "details": f"Invalid Resize By Dimension Option: {resizeByDimension}."})

                                value = ''
                                if 'value' in data:
                                    if data['value'] != '':
                                        value = int(data['value'])
                                    else:
                                        return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "value".'})
                                else:
                                    return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Key "value" is not in the data.'})
                                print(f"Value: {value}")

                                if image_handler.resize_image({"value": value}, ResizeOptions.BY_IMAGESIZE, ResizeByImageSizeOptions.BY_DIMENSIONS, 1, Dimension.WIDTH if resizeByDimension == 'width' else Dimension.HEIGHT):
                                    
                                    if image_handler.edittedimagestream != []:
                               
                                        select_item.edittedimagestream = json.dumps(image_handler.edittedimagestream)
                                        select_item.editinghistory = json.dumps(image_handler.editinghistory)
                                        select_item.save()
                                        return Response(status=status.HTTP_201_CREATED, 
                                                        data={"status": status.HTTP_201_CREATED, 
                                                            "details": {
                                                            'editted_imagestream': select_item.edittedimagestream,
                                                            'editing_history': select_item.editinghistory
                                                        }})
                
                                print(f"Failed: Image could not be resized.")
                                return Response(status=status.HTTP_412_PRECONDITION_FAILED, data={"status": status.HTTP_412_PRECONDITION_FAILED, "details": f"Image could not be resized."})

                            else:
                                
                                width = ''
                                if 'width' in data:
                                    if data['width'] != '':
                                        width = int(data['width'])
                                    else:
                                        return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "width".'})
                                else:
                                    return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Key "width" is not in the data.'})
                                print(f"Width: {width}")

                                height = ''
                                if 'height' in data:
                                    if data['height'] != '':
                                        height = int(data['height'])
                                    else:
                                        return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "height".'})
                                else:
                                    return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Key "height" is not in the data.'})
                                print(f"Height: {height}")

                                if image_handler.resize_image({"width": width, "height": height}, ResizeOptions.BY_IMAGESIZE, ResizeByImageSizeOptions.BY_DIMENSIONS, 0):
                                    
                                    if image_handler.edittedimagestream != []:
                               
                                        select_item.edittedimagestream = json.dumps(image_handler.edittedimagestream)
                                        select_item.editinghistory = json.dumps(image_handler.editinghistory)
                                        select_item.save()
                                        return Response(status=status.HTTP_201_CREATED, 
                                                        data={"status": status.HTTP_201_CREATED, 
                                                            "details": {
                                                            'editted_imagestream': select_item.edittedimagestream,
                                                            'editing_history': select_item.editinghistory
                                                        }})
                
                                print(f"Failed: Image could not be resized.")
                                return Response(status=status.HTTP_412_PRECONDITION_FAILED, data={"status": status.HTTP_412_PRECONDITION_FAILED, "details": f"Image could not be resized."})

                        elif resizeImageSizeBy == ResizeByImageSizeOptions.BY_PERCENTAGE.value:

                            percentage = ''
                            if 'percentage' in data:
                                if data['percentage'] != '':
                                    percentage = float(data['percentage'])
                                else:
                                    return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "percentage".'})
                            else:
                                return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Key "percentage" is not in the data.'})
                            print(f"Height: {percentage}")
                            
                            if image_handler.resize_image({"percentage": percentage}, ResizeOptions.BY_IMAGESIZE, ResizeByImageSizeOptions.BY_PERCENTAGE):
                                    
                                if image_handler.edittedimagestream != []:
                               
                                    select_item.edittedimagestream = json.dumps(image_handler.edittedimagestream)
                                    select_item.editinghistory = json.dumps(image_handler.editinghistory)
                                    select_item.save()
                                    return Response(status=status.HTTP_201_CREATED, 
                                                    data={"status": status.HTTP_201_CREATED, 
                                                        "details": {
                                                        'editted_imagestream': select_item.edittedimagestream,
                                                        'editing_history': select_item.editinghistory
                                                    }})
            
                            print(f"Failed: Image could not be resized.")
                            return Response(status=status.HTTP_412_PRECONDITION_FAILED, data={"status": status.HTTP_412_PRECONDITION_FAILED, "details": f"Image could not be resized."})
        
                        print(f"Failed: Invalid Resize By Image Size Option: {resizeImageSizeBy}.")
                        return Response(status=status.HTTP_206_PARTIAL_CONTENT, data={"status": status.HTTP_400_BAD_REQUEST, "details": f"Invalid Resize By Image Size Option: {resizeImageSizeBy}."})

                    elif resizeBy == ResizeOptions.BY_FILESIZE.value:
                        
                        targetSize = ''
                        if 'targetSize' in data:
                            if data['targetSize'] != '':
                                targetSize = float(data['targetSize'])
                            else:
                                return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "targetSize".'})
                        else:
                            return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Key "targetSize" is not in the data.'})
                        print(f"Target Size: {targetSize}")
                        
                        unit = ''
                        if 'unit' in data:
                            if data['unit'] != '':
                                unit = data['unit']
                            else:
                                return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "unit".'})
                        else:
                            return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Key "unit" is not in the data.'})
                        print(f"Unit: {unit}")
                        
                        if unit != FileSizeUnit.BYTES.value and unit != FileSizeUnit.KILO_BYTES.value and unit != FileSizeUnit.MEGA_BYTES.value and unit != FileSizeUnit.GIGA_BYTES.value:
                                    
                            print(f"Failed: Invalid File Size Unit: {unit}.")
                            return Response(status=status.HTTP_206_PARTIAL_CONTENT, data={"status": status.HTTP_400_BAD_REQUEST, "details": f"Invalid File Size Unit: {unit}."})

                        if image_handler.resize_image({"targetSize": targetSize, "unit": unit}, ResizeOptions.BY_FILESIZE):
                                
                            if image_handler.edittedimagestream != []:
                               
                                select_item.edittedimagestream = json.dumps(image_handler.edittedimagestream)
                                select_item.editinghistory = json.dumps(image_handler.editinghistory)
                                select_item.save()
                                return Response(status=status.HTTP_201_CREATED, 
                                                data={"status": status.HTTP_201_CREATED, 
                                                    "details": {
                                                    'editted_imagestream': select_item.edittedimagestream,
                                                    'editing_history': select_item.editinghistory
                                                }})
        
                        print(f"Failed: Image could not be resized.")
                        return Response(status=status.HTTP_412_PRECONDITION_FAILED, data={"status": status.HTTP_412_PRECONDITION_FAILED, "details": f"Image could not be resized."})
            
                    print(f"Failed: Invalid Resize Option: {resizeBy}.")
                    return Response(status=status.HTTP_206_PARTIAL_CONTENT, data={"status": status.HTTP_400_BAD_REQUEST, "details": f"Invalid Resize Option: {resizeBy}."})

                print("Failed: Response could not be obtained.")
                return Response(status=status.HTTP_204_NO_CONTENT, data={"status": status.HTTP_400_BAD_REQUEST, "details": "Response could not be obtained."})
            
            print("Failed: ImageID not found in the database.")
            return Response(status=status.HTTP_404_NOT_FOUND, data={"status": status.HTTP_404_NOT_FOUND, "details": "ImageID not found in the database."})

        except Exception as e:
            print("Exception encountered")
            print("*"*20)
            print(e)

            exception_name = type(e).__name__
            return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": "Exception encountered: " + str(exception_name)})
    
class Rotate_Image(APIView):
    def post(self, request, *args, **kwargs):
        try:
            data = request.data

            imageId = ''
            if 'imageID' in data:
                if data['imageID'] != '':
                    imageId = data['imageID']
                else:
                    return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "imageID".'})
            else:
                return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Key "imageID" is not in the data.'})
            print(f"Image ID: {imageId}")

            orientation = ''
            if 'orientation' in data:
                if data['orientation'] != '':
                    orientation = int(data['orientation'])
                else:
                    return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "orientation".'})
            else:
                return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Key "orientation" is not in the data.'})
            print(f"Orientation: {orientation}")

            if orientation == RotationOrientation.CLOCK_WISE.value or orientation == RotationOrientation.ANTI_CLOCK_WISE.value:
                imageId_list = Image.objects.values_list('imageID', flat=True)
                if imageId in imageId_list:

                    select_item = Image.objects.filter(imageID=imageId).order_by('uploadtime').last()
                    if select_item.originalimagestream != []:

                        image_handler.assign_select_item_details(select_item.imageID, select_item.uploadtime, select_item.originalfolderpath, 
                                                            json.loads(select_item.originalimagename), json.loads(select_item.originalimagetype), 
                                                            json.loads(select_item.originalimagestream), json.loads(select_item.edittedimagetype),
                                                            json.loads(select_item.edittedimagestream), json.loads(select_item.editinghistory))
                        
                        if image_handler.rotate_image(orientation):
                            if image_handler.edittedimagestream != []:
                               
                                select_item.edittedimagestream = json.dumps(image_handler.edittedimagestream)
                                select_item.editinghistory = json.dumps(image_handler.editinghistory)
                                select_item.save()
                                return Response(status=status.HTTP_201_CREATED, 
                                                data={"status": status.HTTP_201_CREATED, 
                                                    "details": {
                                                    'editted_imagestream': select_item.edittedimagestream,
                                                    'editing_history': select_item.editinghistory
                                                }})
                                
                            print("Failed: No changes done. Download cannot be initiated without making any changes.")
                            return Response(status=status.HTTP_205_RESET_CONTENT, data={"status": status.HTTP_205_RESET_CONTENT, "details": "No changes done. Download cannot be initiated without making any changes."})
                        
                        print(f"Failed: Image could not be rotated in {orientation} degrees.")
                        return Response(status=status.HTTP_412_PRECONDITION_FAILED, data={"status": status.HTTP_412_PRECONDITION_FAILED, "details": f"Image could not be rotated in {orientation} degrees."})
                        
                    print("Failed: Response could not be obtained.")
                    return Response(status=status.HTTP_204_NO_CONTENT, data={"status": status.HTTP_400_BAD_REQUEST, "details": "Response could not be obtained."})
                
                print("Failed: ImageID not found in the database.")
                return Response(status=status.HTTP_404_NOT_FOUND, data={"status": status.HTTP_404_NOT_FOUND, "details": "ImageID not found in the database."})

            print(f"Failed: Invalid Orientation: {orientation}.")
            return Response(status=status.HTTP_206_PARTIAL_CONTENT, data={"status": status.HTTP_400_BAD_REQUEST, "details": f"Invalid Orientation: {orientation}."})

        except Exception as e:
            print("Exception encountered")
            print("*"*20)
            print(e)

            exception_name = type(e).__name__
            return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": "Exception encountered: " + str(exception_name)})

class Flip_Image(APIView):
    def post(self, request, *args, **kwargs):
        try:
            data = request.data

            imageId = ''
            if 'imageID' in data:
                if data['imageID'] != '':
                    imageId = data['imageID']
                else:
                    return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "imageID".'})
            else:
                return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Key "imageID" is not in the data.'})
            print(f"Image ID: {imageId}")

            direction = ''
            if 'direction' in data:
                if data['direction'] != '':
                    direction = data['direction']
                else:
                    return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "direction".'})
            else:
                return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Key "direction" is not in the data.'})
            print(f"Direction: {direction}")

            if direction == FlippingDirection.HORIZONTAL.value or direction == FlippingDirection.VERTICAL.value:
                imageId_list = Image.objects.values_list('imageID', flat=True)
                if imageId in imageId_list:

                    select_item = Image.objects.filter(imageID=imageId).order_by('uploadtime').last()
                    if select_item.originalimagestream != []:

                        image_handler.assign_select_item_details(select_item.imageID, select_item.uploadtime, select_item.originalfolderpath, 
                                                            json.loads(select_item.originalimagename), json.loads(select_item.originalimagetype), 
                                                            json.loads(select_item.originalimagestream), json.loads(select_item.edittedimagetype),
                                                            json.loads(select_item.edittedimagestream), json.loads(select_item.editinghistory))
                        
                        if image_handler.flip_image(direction):
                            if image_handler.edittedimagestream != []:
                               
                                select_item.edittedimagestream = json.dumps(image_handler.edittedimagestream)
                                select_item.editinghistory = json.dumps(image_handler.editinghistory)
                                select_item.save()
                                return Response(status=status.HTTP_201_CREATED, 
                                                data={"status": status.HTTP_201_CREATED, 
                                                    "details": {
                                                    'editted_imagestream': select_item.edittedimagestream,
                                                    'editing_history': select_item.editinghistory
                                                }})
                                
                            print("Failed: No changes done. Download cannot be initiated without making any changes.")
                            return Response(status=status.HTTP_205_RESET_CONTENT, data={"status": status.HTTP_205_RESET_CONTENT, "details": "No changes done. Download cannot be initiated without making any changes."})
                        
                        print(f"Failed: Image could not be flipped in {direction} direction.")
                        return Response(status=status.HTTP_412_PRECONDITION_FAILED, data={"status": status.HTTP_412_PRECONDITION_FAILED, "details": f"Image could not be flipped in {direction} direction."})
                        
                    print("Failed: Response could not be obtained.")
                    return Response(status=status.HTTP_204_NO_CONTENT, data={"status": status.HTTP_400_BAD_REQUEST, "details": "Response could not be obtained."})
                
                print("Failed: ImageID not found in the database.")
                return Response(status=status.HTTP_404_NOT_FOUND, data={"status": status.HTTP_404_NOT_FOUND, "details": "ImageID not found in the database."})

            print(f"Failed: Invalid Direction: {direction}.")
            return Response(status=status.HTTP_206_PARTIAL_CONTENT, data={"status": status.HTTP_400_BAD_REQUEST, "details": f"Invalid Direction: {direction}."})

        except Exception as e:
            print("Exception encountered")
            print("*"*20)
            print(e)

            exception_name = type(e).__name__
            return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": "Exception encountered: " + str(exception_name)})
        
class Crop_Image(APIView):
    def post(self, request, *args, **kwargs):
        try:
            data = request.data

            imageId = ''
            if 'imageID' in data:
                if data['imageID'] != '':
                    imageId = data['imageID']
                else:
                    return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "imageID".'})
            else:
                return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Key "imageID" is not in the data.'})
            print(f"Image ID: {imageId}")

            left = ''
            if 'left' in data:
                if data['left'] != '':
                    left = int(data['left'])
                else:
                    return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "left".'})
            else:
                return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Key "left" is not in the data.'})
            print(f"Left: {left}")

            top = ''
            if 'top' in data:
                if data['top'] != '':
                    top = int(data['top'])
                else:
                    return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "top".'})
            else:
                return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Key "top" is not in the data.'})
            print(f"Left: {top}")

            right = ''
            if 'right' in data:
                if data['right'] != '':
                    right = int(data['right'])
                else:
                    return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "right".'})
            else:
                return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Key "right" is not in the data.'})
            print(f"Left: {right}")

            bottom = ''
            if 'bottom' in data:
                if data['bottom'] != '':
                    bottom = int(data['bottom'])
                else:
                    return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "bottom".'})
            else:
                return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Key "bottom" is not in the data.'})
            print(f"Left: {bottom}")

            if left < right and top < bottom:

                imageId_list = Image.objects.values_list('imageID', flat=True)
                if imageId in imageId_list:

                    select_item = Image.objects.filter(imageID=imageId).order_by('uploadtime').last()
                    if select_item.originalimagestream != []:

                        image_handler.assign_select_item_details(select_item.imageID, select_item.uploadtime, select_item.originalfolderpath, 
                                                            json.loads(select_item.originalimagename), json.loads(select_item.originalimagetype), 
                                                            json.loads(select_item.originalimagestream), json.loads(select_item.edittedimagetype),
                                                            json.loads(select_item.edittedimagestream), json.loads(select_item.editinghistory))
                        
                        if image_handler.crop_image(left, top, right, bottom):
                            if image_handler.edittedimagestream != []:
                                
                                select_item.edittedimagestream = json.dumps(image_handler.edittedimagestream)
                                select_item.editinghistory = json.dumps(image_handler.editinghistory)
                                select_item.save()
                                return Response(status=status.HTTP_201_CREATED, 
                                                data={"status": status.HTTP_201_CREATED, 
                                                    "details": {
                                                    'editted_imagestream': select_item.edittedimagestream,
                                                    'editing_history': select_item.editinghistory
                                                }})
                                
                            print("Failed: No changes done. Download cannot be initiated without making any changes.")
                            return Response(status=status.HTTP_205_RESET_CONTENT, data={"status": status.HTTP_205_RESET_CONTENT, "details": "No changes done. Download cannot be initiated without making any changes."})
                        
                        print(f"Failed: Image could not be cropped by {left, top, right, bottom} pixels.")
                        return Response(status=status.HTTP_412_PRECONDITION_FAILED, data={"status": status.HTTP_412_PRECONDITION_FAILED, "details": f"Image could not be cropped by {left, top, right, bottom} pixels."})
                        
                    print("Failed: Response could not be obtained.")
                    return Response(status=status.HTTP_204_NO_CONTENT, data={"status": status.HTTP_400_BAD_REQUEST, "details": "Response could not be obtained."})
                
                print("Failed: ImageID not found in the database.")
                return Response(status=status.HTTP_404_NOT_FOUND, data={"status": status.HTTP_404_NOT_FOUND, "details": "ImageID not found in the database."})

            print(f"Failed: Invalid Pixel Values: {left, top, right, bottom}.")
            return Response(status=status.HTTP_206_PARTIAL_CONTENT, data={"status": status.HTTP_400_BAD_REQUEST, "details": f"Invalid Pixel Values: {left, top, right, bottom}."})

        except Exception as e:
            print("Exception encountered")
            print("*"*20)
            print(e)

            exception_name = type(e).__name__
            return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": "Exception encountered: " + str(exception_name)})
