import json
import math
import os
import shutil

from django.conf import settings
from django.core.management.base import BaseCommand, CommandError
from django.db import transaction
from django.utils import text
from PIL import Image as ImagePIL
from sorl.thumbnail import get_thumbnail

from iconolab.models import Image, ImageStats, Item, ItemMetadata


class BaseImportImagesCommand(BaseCommand):

    def handle(self, *args, **options):
        raise NotImplementedError

    def get_valid_filename(self, natural_key):
        return text.get_valid_filename(natural_key.replace('|', '__'))

    def get_image_dir(self, natural_key, collection):
        return os.path.join(
            collection.name,
            self.get_valid_filename(natural_key)
        )

    ##
    def create_item_and_metadata(
            self,
            natural_key,
            collection,
            metadata_dict,
            image_files,
            options
    ):

        target_dir = os.path.join(settings.MEDIA_ROOT, Image.media.field.upload_to)
        if not os.path.isdir(target_dir):
            raise CommandError("Image target dir does not exists : %s" % target_dir)

        # TODO: Make it fully transactional. if there is a problem on the image creation, some data
        # files can persists.
        with transaction.atomic():
            print('#### Creating item '+natural_key+' (natural key) in database')
            item_object = Item.objects.create(
                collection=collection
            )

            ItemMetadata.objects.create(
                item=item_object,
                metadata=json.dumps(metadata_dict),
                natural_key=natural_key
            )

            print('#### preparing image folder for item ' + natural_key)
            item_image_dir = self.get_image_dir(natural_key, collection)
            target_item_image_dir = os.path.join(target_dir, item_image_dir)
            os.makedirs(target_item_image_dir, exist_ok=True)
            print('-->' + target_item_image_dir, "directory created")

            print('#### Computing item image(s)')
            image_file_name_fill = int(math.log10(len(image_files)))+1
            for i, image in enumerate(image_files):
                (_, ext) = os.path.splitext(image)
                dest_image_name = "{0}_{1:0{2}d}.jpg".format(
                    self.get_valid_filename(natural_key),
                    i+1,
                    image_file_name_fill)
                image_path = os.path.join(target_item_image_dir, dest_image_name)
                if options.get('no-jpg-conversion') or ext in settings.NO_IMG_CONVERSION_EXTS:
                    print('##### Copying file %s to %s without converting'%(str(image), image_path))
                    shutil.copy(image, image_path)
                else:
                    if os.path.isfile(image_path):
                        print('##### A jpeg file already exists in target dir for %s' % image)
                    else:
                        im = ImagePIL.open(image)
                        print('##### Generating or copying jpeg for %s to %s' % (image, image_path))
                        im.thumbnail(im.size)
                        im.save(image_path, 'JPEG', quality=options.get(
                            'jpeg_quality', settings.IMG_JPG_DEFAULT_QUALITY))

                new_image = Image.objects.create(
                    item=item_object,
                    media=os.path.join(Image.media.field.upload_to, item_image_dir, dest_image_name),
                    name=os.path.join(item_image_dir, dest_image_name)
                )
                ImageStats.objects.create(
                    image=new_image
                )

            print('### Generating thumbnails for item '+natural_key)
            for image in item_object.images.all():
                for size in settings.PREGENERATE_THUMBNAILS_SIZES:
                    print('#### Thumbnail for size '+size)
                    get_thumbnail(image.media, size, crop=False)
