# -*- coding: utf-8 -*-
import sys

from django.apps import apps
from django.conf import settings
from django.core.files import File
from django.utils.encoding import force_str

from events.avatars_extra.models import AvatarImageField
from events.avatars_extra.storage import AvatarsStorage
from events.common_app.utils import requests_session


class AvatarsExporter(object):
    """
    Usage:
        AvatarsExporter(
            from_read_base_uri='http://avatars.pd.yandex.net/',
            from_namespace='forms',
            to_read_base_uri='http://avatars.yandex.net/',
            to_write_base_uri='http://avatars-int.yandex.net:12000',
            to_namespace='forms'
        ).run()
    """

    def __init__(self,
                 from_read_base_uri,
                 from_namespace,
                 to_read_base_uri,
                 to_write_base_uri,
                 to_namespace,
                 stdout=None):
        self.from_storage = AvatarsStorage(
            host=from_read_base_uri,
            namespace=from_namespace
        )
        self.to_storage = AvatarsStorage(
            host=to_read_base_uri,
            host_for_write=to_write_base_uri,
            namespace=from_namespace
        )
        self.stdout = stdout or sys.stdout

    def run(self, verbosity='1'):
        self.log(
            msg='[START] Start export from "{from_host}" to "{to_host}". Writing to "{to_host_for_write}"'.format(
                from_host=self.from_storage.host,
                to_host=self.to_storage.host,
                to_host_for_write=self.to_storage.host_for_write
            ),
            verbosity=verbosity
        )
        exported_count = 0
        for image_name, export_image_full_uri in self.get_export_images_full_uris(verbosity=verbosity):
            destination_expected_location = self.get_destination_expected_location(image_name)
            if self.perform_export_if_needed(
                image_name,
                export_image_full_uri,
                destination_expected_location,
                verbosity=verbosity
            ):
                exported_count += 1
        self.log(
            msg='[FINISH] Finished export from "{from_host}" to "{to_host}". Exported {exported_count} avatars'.format(
                from_host=self.from_storage.host,
                to_host=self.to_storage.host,
                exported_count=exported_count
            ),
            verbosity=verbosity
        )
        return exported_count

    def get_export_images_full_uris(self, verbosity=None):
        for model, avatar_fields in self.get_models_with_avatars_fields():
            self.log(
                '[EXPORT INFO] Model: {model_name}; Fields: {fields}'.format(
                    model_name=model.__name__,
                    fields=', '.join(avatar_fields)
                ),
                verbosity=verbosity
            )
            for model_instance in model.objects.all():
                for avatar_field in avatar_fields:
                    field_value = getattr(model_instance, avatar_field)
                    if field_value:
                        image_name = force_str(field_value)
                        yield image_name, self.from_storage._get_thumb_url(name=image_name, alias='orig')

    def get_models_with_avatars_fields(self):
        result = []
        for model in apps.get_models():
            avatar_fields = []
            for field in model._meta.fields:
                if isinstance(field, AvatarImageField):
                    avatar_fields.append(field.name)
            if avatar_fields:
                result.append((model, avatar_fields))
        return result

    def get_destination_expected_location(self, image_name):
        return self.to_storage._get_thumb_url(name=image_name, alias='orig')

    def perform_export_if_needed(self, name, export_image_full_uri, destination_expected_location, verbosity):
        response = requests_session.get(destination_expected_location, timeout=settings.DEFAULT_TIMEOUT)
        is_image_not_already_exists_in_export_destination = response.status_code == 404
        if is_image_not_already_exists_in_export_destination:
            # импортируем только если не существует такой картинки в пункте назначения
            export_image_file = requests_session.get(export_image_full_uri, timeout=settings.DEFAULT_TIMEOUT)
            export_image_file.name = name
            if 200 <= export_image_file.status_code < 300:
                export_image_django_file = File(export_image_file.content)
                self.to_storage.save(name, export_image_django_file)
                self.log(
                    msg='[SUCCESS] {url} exported to {url_destination}'.format(
                        url=export_image_full_uri,
                        url_destination=destination_expected_location
                    ),
                    verbosity=verbosity
                )
                return True
            else:
                self.log(
                    msg='[ERROR] {url} could not been retrieved from source storage.'.format(
                        url=export_image_full_uri
                    ),
                    verbosity=verbosity
                )
        else:
            self.log(
                msg='[SKIPPED] {url} already exists in destination storage.'.format(
                    url=destination_expected_location
                ),
                verbosity=verbosity
            )

    def log(self, msg, verbosity):
        if verbosity == '1':
            self.stdout.write(msg + '\n')
