# coding: utf-8
from __future__ import unicode_literals

import datetime
import urllib2
import os

from django.conf import settings
from django.core.files.base import ContentFile
from django.db import models
from django.db.models import Max
from django.db.models.signals import post_delete, post_save
from django.forms import fields
from libra.books.storage import EllipticsMDSStorage

from libra.books.MailManager import MailRenderer
from libra.rfid import Rfid
from django_intranet_stuff.models import Staff, Office, City
from south.modelsinspector import add_introspection_rules
from libra.tagging.models import Tag

# from_staff_id office identifiers here
MOROZOV_OFFICE_ID = 34
MAMONTOV_OFFICE_ID = 61
STROGANOV_OFFICE_ID = 62
# near-Moscow data centers
DC_VAV_OFFICE_ID = 2
DC_NIZ_OFFICE_ID = 23
DC_UGR_OFFICE_ID = 38
DC_IVA_OFFICE_ID = 39
DC_MYT_OFFICE_ID = 42
DC_FOL_OFFICE_ID = 59
# Симферополь
SIMFEROPOL_ID = 4
BENUA_ID = 14
# Надомники
HOME_OFFICE_ID = 7

OFFICE_TO_LIBRARY = {
    MAMONTOV_OFFICE_ID: MOROZOV_OFFICE_ID,
    STROGANOV_OFFICE_ID: MOROZOV_OFFICE_ID,

    DC_VAV_OFFICE_ID: MOROZOV_OFFICE_ID,
    DC_NIZ_OFFICE_ID: MOROZOV_OFFICE_ID,
    DC_UGR_OFFICE_ID: MOROZOV_OFFICE_ID,
    DC_IVA_OFFICE_ID: MOROZOV_OFFICE_ID,
    DC_MYT_OFFICE_ID: MOROZOV_OFFICE_ID,
    DC_FOL_OFFICE_ID: MOROZOV_OFFICE_ID,

    HOME_OFFICE_ID: MOROZOV_OFFICE_ID,
    SIMFEROPOL_ID: SIMFEROPOL_ID,
    BENUA_ID: BENUA_ID,
}

MOSCOW_OFFICES = (MOROZOV_OFFICE_ID, MAMONTOV_OFFICE_ID, STROGANOV_OFFICE_ID)
SIMFEROPOL_OFFICES = (SIMFEROPOL_ID,)


class ContainOfficeId(object):
    def __init__(self, id):
        self._id = id

    def get_data(self):
        return list(City.objects.get(id=self._id).office_set
                    .filter(intranet_status=1).values_list('id', flat=True))

    def __contains__(self, key):
        return key in self.get_data()

    def __getitem__(self, key):
        return self.get_data()[key]

    def __iter__(self):
        return iter(self.get_data())


# настоящие современные айдишники
MOSCOW_OFFICES_IDS = ContainOfficeId(1)
SPB_OFFICES_IDS = ContainOfficeId(2)


fs = EllipticsMDSStorage()

class Publisher(models.Model):
    u" Модель издательства "
    name = models.CharField(
        max_length=250, unique=True, verbose_name=u'название'
    )

    class Meta:
        verbose_name = u'издательство'
        verbose_name_plural = u'издательства'

    def __unicode__(self):
        return self.name


FORMAT = u'Не могу скачать и сохранить обложку книги с ID=%d'


class BookCover(models.Model):
    ' Обложка книги '

    class Meta:
        verbose_name = 'обложка'
        verbose_name_plural = 'обложки'


    img_large = models.ImageField(upload_to='covers/large', storage=fs)

    def download(self, img_url, book_id):
        u' скачивает картинку обложки по заданному URL '
        if os.path.isfile(img_url):
            _buffer = open(img_url).read()
        else:
            try:
                _buffer = urllib2.urlopen(img_url).read()
            except Exception:
                print FORMAT % book_id
                return

        filename = u'book-%d.jpg' % book_id
        self.img_large.save(filename, ContentFile(_buffer))


    def __unicode__(self):
        return 'Обложка №%d' % self.id

    def image_tag(self):
        return '<img  style="width:70px" src="%s"/>' % self.img_large.url

    image_tag.short_description = 'Cover'
    image_tag.allow_tags = True


class Book(models.Model):
    u" Модель мета-книги "
    title = models.CharField(max_length=255, verbose_name=u'название')
    authors_string = models.CharField(
        max_length=255, verbose_name=u'авторы (одной строкой)', blank=True
    )
    publisher = models.ForeignKey(
        Publisher, verbose_name=u'издательство', blank=True, null=True
    )
    # Строка, хранящая список годов изданий книги
    # (по тем экземплярам, которые у нас в базе)
    years = models.CharField(
        max_length=255, verbose_name=u'Годы изданий', blank=True, default=''
    )
    reg_date = models.DateTimeField(blank=True, null=True)

    main_cover = models.ForeignKey(
        BookCover, blank=True, null=True, verbose_name='основная обложка'
    )

    def image_tag(self):
        return '<img  style="width:70px" src="%s"/>' % self.main_cover.img_large.url
    image_tag.short_description = 'Обложка'
    image_tag.allow_tags = True

    shelf = models.IntegerField(verbose_name=u'полка', blank=True, null=True)
    case = models.IntegerField(verbose_name=u'шкаф', blank=True, null=True)
    mulca_file = models.FileField(
        max_length=255, storage=fs, verbose_name=u'Файл эл.книги (pdf)',
        blank=True, upload_to=lambda x, y: True
    )
    remove_the_file = models.BooleanField(
        verbose_name=u'показать файл эл.книги?', default=True
    )
    at_id = models.IntegerField(null=True)

    class Meta:
        verbose_name = u'книга'
        verbose_name_plural = u'книги'

    def get_items(self):
        return self.bookitem_set.filter(
            is_active=True
        ).order_by('location_staff')

    def _get_tags(self):
        return Tag.objects.get_for_object(self)

    def _set_tags(self, tag_list):
        Tag.objects.update_tags(self, tag_list)

    tags = property(_get_tags, _set_tags)

    def __unicode__(self):
        return self.title

    def update_related_fields(self):
        ' Обновляет зависимые поля Книги по следам Экземпляров этой книги '

        # Узнаем дату регистрации последнего экземпляра
        # и запоминаем его для Книги.
        self.reg_date = (
            self.bookitem_set.filter(is_active=True)
                .aggregate(Max('reg_date'))['reg_date__max']
        )

        # Выстявляем обложку по обложке последнего экземпляра TODO!
        # Пока мы не храним обложки в экземплярах - не удаляем обложку книги
        #try:
        #    self.main_cover = self.bookitem_set.filter(cover__isnull=False)
        # .order_by('-reg_date')[0]
        #except IndexError:
        #    self.main_cover = None

        # так сделано потому что книга может издаваться в разные года,
        # и у нас могут быть экземпляры разных лет.
        years_list = (
            self.bookitem_set.filter(is_active=True).order_by('year')
                .values_list('year', flat=True).distinct()
        )
        years = ', '.join(['%d' % y for y in years_list if y])
        self.years = years

        self.save()

    @models.permalink
    def get_absolute_url(self):
        return ('view_book', [self.id])


class RfidFormField(fields.CharField):
    u''' Кастомная форма ввода/вывода номера RFID. Принимает в себя decimal,
        либо human-readable номер, автоматически преобразует его в decimal '''

    def clean(self, value):
        # заменим все потенциальные опечатки-разделители на запятую:
        value = reduce(
            lambda subj, repl: subj.replace(repl, ','),
             [value, '.', '-', '/', u'б', u'ю', u'Б', u'Ю', '?', '<', '>']
        )
        return super(RfidFormField, self).clean(
            Rfid.smart_float2decimal(value)
        )


class RfidField(models.CharField):
    u' Кастомный класс поля модели для представления RFID-метки '
    def __init__(self, *args, **kwargs):
        super(RfidField, self).__init__(*args, **kwargs)

    def formfield(self, **kwargs):
        defaults = {'form_class': RfidFormField}
        defaults.update(kwargs)
        return super(RfidField, self).formfield(**defaults)

add_introspection_rules([], ["^libra\.books\.models\.RfidField"])


class ActiveManager(models.Manager):
    u' общий менеджер активных объектов '
    def get_query_set(self):
        return (
            super(ActiveManager, self).get_query_set().filter(is_active=True)
        )


class BookItem(models.Model):
    u"""
        Модель экземпляра книги.
        В библиотеке может быть 0 или больше экземпляров определенной книги.
    """
    OWNERSHIP_CHOICES = (
        ('YA', u'компании'),      # книга принадлежит компании
        ('PR', u'личная'),        # личная книга
        ('UN', u'неизвестно'),    # владелец книги неизвестен
    )

    SRC_CHOICES = (
        (1, u'wiki'),       # Книги импортированы из вики-страниц
        (2, u'revisions'),  # Список книг получен из инвентаризации книг
        (3, u'user'),       # Книги, занесенные пользователями
    )

    objects = models.Manager()  # базовый менеджер объектов

    # менеджер объектов, возвращающий активные экземпляры книг
    active = ActiveManager()

    # Ссылка на книгу
    book = models.ForeignKey(Book, verbose_name=u'книга')
    year = models.IntegerField(
        verbose_name=u'год издания', blank=True, null=True
    )
    isbn = models.DecimalField(
        max_digits=13, decimal_places=0,
        blank=True, null=True, verbose_name='ISBN'
    )
    ownership_choices = models.CharField(
        max_length=2, choices=OWNERSHIP_CHOICES, verbose_name=u'принадлежность'
    )
    # ссылка на сотрудника-владельца книги
    owner = models.ForeignKey(
        Staff, blank=True, null=True, related_name="ownedbookitems"
    )
    office = models.ForeignKey(
        Office, blank=True, null=True, verbose_name=u'офис'
    )
    # У кого из сотрудников сейчас экземпляр книги?
    location_staff = models.ForeignKey(
        Staff, verbose_name=u'у кого', related_name='holdingbookitems',
        blank=True, null=True
    )
    # Является ли экземпляр бумажной книгой или файлом
    # (эл. копия, аудиокнига и т.п.)
    is_paper = models.BooleanField(
        verbose_name=u'бумажная копия', default=True
    )
    # Дополнительный коммент к экземпляру книги
    comment = models.CharField(
        max_length=255, verbose_name=u'примечание', blank=True
    )
    # Стоимость книги в рублях
    cost = models.DecimalField(
        max_digits=7, decimal_places=2, blank=True,
        null=True, verbose_name=u'стоимость'
    )
    reg_date = models.DateTimeField(
        auto_now_add=True, verbose_name=u'дата добавления книги'
    )
    # Кто добавил книгу в каталог (обязательное поле)
    registrator_staff = models.ForeignKey(
        Staff, related_name='registersbook', verbose_name=u'книгу добавил',
        blank=True, null=True
    )
    # Флаг доступности книги
    # (если false - то книга утеряна или в собственности уволенного сотрудника)
    is_active = models.BooleanField(
        verbose_name=u'экземпляр доступен', default=True
    )
    src_choices = models.IntegerField(
        verbose_name=u'Источник информации', choices=SRC_CHOICES, default=3
    )

    cover = models.ForeignKey(
        BookCover, blank=True, null=True, verbose_name='обложка'
    )

    def image_tag(self):
        cover = self.cover if self.cover else self.book.main_cover
        return '<img  style="width:70px" src="%s"/>' % cover.img_large.url

    image_tag.short_description = 'Обложка'
    image_tag.allow_tags = True


    rfid = RfidField(
        max_length=12, blank=True, null=True, verbose_name=u'RFID'
    )
    shelf = models.IntegerField(
        verbose_name=u'полка', blank=True, null=True
    )
    case = models.IntegerField(
        verbose_name=u'шкаф', blank=True, null=True
    )
    # Флаг настольной книги
    is_tablebook = models.BooleanField(
        verbose_name=u"настольная книга", default=False
    )

    class Meta:
        verbose_name = u'экземпляр книги'
        verbose_name_plural = u'экземпляры книг'

    @property
    def current_reader(self):
        return self.location_staff

    @property
    def location_text(self):
        u''' Текстовое значение "где / у кого книга" '''
        if not self.current_reader:
            if self.office:
                return u'{0}, библиотека'.format(
                    self.office.short_name
                )
            else:
                return u'(не указано)'
        else:
            return self.current_reader

    @property
    def owner_text(self):
        u''' Текстовое значение полей группы "Владелец" '''
        if self.ownership_choices == 'YA':
            return u'Яндекс'
        elif self.ownership_choices == 'PR':
            return self.owner or u'(не указан)'
        elif self.ownership_choices in ('UN', None):
            return u'(не известен)'

    @property
    def human_rfid(self):
        if self.rfid:
            return Rfid.decimal2float(self.rfid)
        else:
            return None

    # TODO: Сделать наследование полки от книги
    @property
    def bookshelf(self):
        return self.shelf

    # TODO: Сделать наследование шкафа от книги
    @property
    def bookcase(self):
        return self.case

    @property
    def from_date(self):
        u'''
        Возвращает дату последнего взятия экзампляра книги
        указанным сотрудником
        '''
        if self.current_reader:
            last_rh = self.readhistory_set.filter(
                return_date=None, reader=self.current_reader
            ).order_by('-id')
            if last_rh:
                return last_rh[0].get_date
        return None

    @property
    def is_lost(self):
        if not self.current_reader and \
            self.office.from_staff_id == MOROZOV_OFFICE_ID and \
            not (self.shelf and self.case):
            return True
        return False

    def save(self, force_insert=False, force_update=False):
        # u'''
        # перегружаем метод сохранения, чтобы автоматически определять офис,
        # в котором находится экземпляр книги
        # '''
        # if self.current_reader:  # Если книга сейчас на руках
        #     self.office = self.current_reader.office
        # elif self.owner:    # Если книга у владельца и владелец указан
        #     self.office = self.owner.office
        # # если офис не удается определить по внешним признакам - не трогаем его
        super(BookItem, self).save(force_insert, force_update)

    def __unicode__(self):
        return "%s (%s) [%d]" % (
            self.book.title, self.book.authors_string, self.id
        )

    def move_to_library(self, office, staff):
        u' перемещает книгу в библиотеку '
        if self.current_reader != None and self.current_reader != staff:
            # если книга числится у кого-то на руках, но не у возвращающего
            # запишем ему в историю возврат книги
            self.log_return(self.current_reader, auto=True)

        if office.from_staff_id in OFFICE_TO_LIBRARY:
            office = Office.objects.get(from_staff_id=OFFICE_TO_LIBRARY[office.from_staff_id])
        self.log_return(staff)  # запишем в историю ему взятие книги
        self.location_staff = None
        self.office = office
        self.save()

    def move_to_user(self, staff):
        u' фиксирует взятие книги сотрудником '
        if self.current_reader is not None and self.current_reader != staff:
            # если книга числится у кого-то на руках, но не у берущего
            # запишем ему в историю возврат книги
            self.log_return(self.current_reader, auto=True)

        self.log_getting(staff)  # запишем в историю ему взятие книги
        self.location_staff = staff
        self.save()

    def log_getting(self, reader):
        u' Записывает в историю факт взятия книги '
        now = datetime.datetime.now()
        rh = ReadHistory(
            reader=reader, get_date=now, book=self.book, book_item=self
        )
        rh.save()

    def log_return(self, reader, auto=False):
        u' Записывает в историю факт возврата книги '
        now = datetime.datetime.now()
        last_rh = self.readhistory_set.filter(
            return_date=None, reader=reader
        ).order_by('-id')

        if len(last_rh) == 0:
            rh = ReadHistory(
                reader=reader, return_date=now, book=self.book, book_item=self
            )
        else:
            rh = last_rh[0]
            rh.return_date = now
            rh.book = self.book
        rh.save()

    @property
    def is_overheld(self):
        now = datetime.datetime.now()
        interval = now + settings.BOOK_HOLD_PERIOD
        taken = self.from_date
        if taken:
            return taken < interval
        else:
            return False

"""
class BookFile(models.Model):
    u'Файл книги'
    bookitem = models.ForeignKey(Book, related_name='bookfiles')
    label = models.CharField(
        max_length=250, blank=True, verbose_name=u'Подпись к файлу', default=''
    )
    file = models.FileField(upload_to='book_files')

    class Meta:
        verbose_name = u'файл для книги'
        verbose_name_plural = u'файлы для книг'

    def __unicode__(self):
        return self.email
"""


class TagCategory(models.Model):
    u' Категория тегов '
    name = models.CharField(max_length=20, verbose_name=u'Категория тегов')
    tags = models.ManyToManyField(Tag, related_name='tagcategory')

    class Meta:
        verbose_name = u'категория тегов'
        verbose_name_plural = u'категории тегов'

    def __unicode__(self):
        return self.name


class Opinion(models.Model):
    u"""
        Модель отзыва о книге
    """
    book = models.ForeignKey(Book)
    text = models.TextField(blank=True, verbose_name=u'отзыв')
    reader = models.ForeignKey(Staff, verbose_name=u'читатель')
    date = models.DateTimeField(auto_now_add=True, verbose_name=u'Дата отзыва')

    class Meta:
        verbose_name = u'отзыв'
        verbose_name_plural = u'отзывы'

    def __unicode__(self):
        return u"%s / %s" % (self.reader, self.book.title)


class ReadHistory(models.Model):
    u"""
        Модель историй чтений.
    """
    reader = models.ForeignKey(Staff)
    book_item = models.ForeignKey(BookItem, blank=True, null=True)
    book = models.ForeignKey(Book)
    get_date = models.DateTimeField(
        blank=True, null=True, verbose_name=u'когда взяли почитать'
    )
    return_date = models.DateTimeField(
        blank=True, null=True, verbose_name=u'дата возврата'
    )

    class Meta:
        verbose_name = u'история прочтения'
        verbose_name_plural = u'истории прочтения'

    def __unicode__(self):
        return u"%s : %s [%d]" % (
            self.reader, self.book.title, self.book_item_id or 0
        )

    @classmethod
    def taken_long_ago(cls):
        now_day = datetime.date.today()
        interval = now_day + settings.BOOK_HOLD_PERIOD
        return cls.objects.filter(
            reader__is_dismissed=False,
            get_date__lte=interval,
            get_date__gte=settings.DATE_BUGFIX_RELEASE,
            return_date__isnull=True,
            book_item__is_active=True,
            book_item__ownership_choices='YA',
            book_item__owner__isnull=True,
            book_item__is_tablebook=False)\
                          .distinct()


class ReportEmail(models.Model):
    u' Кому слать отчеты о просроченных книгах'
    email = models.CharField(max_length=100, null=True, db_index=True)

    class Meta:
        verbose_name = u'адрес для отчетов'
        verbose_name_plural = u'адреса для отчетов'

    def __unicode__(self):
        return self.email


class Shop(models.Model):
    u' Интернет-магазин '
    url_part = models.CharField(
        max_length=50, verbose_name=u'Адрес интернет-магазина',
        unique=True, help_text=u'Например, amazon.com или books.ru (без http)'
    )
    name = models.CharField(
        max_length=50, verbose_name=u'Название магазина', unique=True
    )

    def __unicode__(self):
        return self.name


class RequestExecutor(models.Model):
    u'''
        Исполнитель заявки (сотрудник компании,
        который будет заказывать книгу в магазине)
    '''
    staff = models.ForeignKey(Staff, verbose_name=u'Сотрудник')
    office = models.ForeignKey(
        Office, blank=True, null=True,
        verbose_name=u'Офис, для которого этот сотрудник будет делать заявки'
    )

    def __unicode__(self):
        return u'%s / %s' % (self.staff, self.office)


class RequestFlow(models.Model):
    u'История изменения статусов заявок'

    STATE_NEW, STATE_TOAPPROVE, STATE_APPROVED = 'NEW', 'TOAPPROVE', 'APPROVED'
    STATE_ORDERED, STATE_DELIVERED, STATE_DISCARDED = (
        'ORDERED', 'DELIVERED', 'DISCARDED'
    )
    STATE_CANTORDER, STATE_PAID = 'CANTORDER', 'PAID'

    STATE_CHOICES = (
        (STATE_NEW, u'Новая'), (STATE_TOAPPROVE, u'На согласовании'),
        (STATE_APPROVED, u'Согласована'), (STATE_ORDERED, u'Заказана'),
        (STATE_DELIVERED, u'Доставлено'), (STATE_DISCARDED, u'Не утверждена'),
        (STATE_CANTORDER, u'Невозможно заказать'), (STATE_PAID, u'Оплачена'),
    )

    datetime = models.DateTimeField(
        auto_now_add=True, verbose_name=u'Дата перехода в статус'
    )
    request = models.ForeignKey('PurchaseRequest')
    state = models.CharField(
        max_length=15, choices=STATE_CHOICES, verbose_name=u'Статус заявки'
    )
    changer = models.ForeignKey(
        Staff, verbose_name=u'Кто поменял статус заявки'
    )

    def __unicode__(self):
        return u'%s %s / %s' % (
            self.datetime, self.request.title, self.state
        )


class PurchaseRequest(models.Model):
    u'Заявка на покупку книги'
    state = models.CharField(
        max_length=10, choices=RequestFlow.STATE_CHOICES, default='NEW',
        verbose_name=u'Статус'
    )
    delivery_office = models.ForeignKey(
        Office, verbose_name=u'В какой офис доставлять'
    )
    approve_man = models.ForeignKey(
        Staff, blank=True, null=True, related_name='approve_requests',
        verbose_name=u'У кого утвердить заявку'
    )
    executor = models.ForeignKey(
        RequestExecutor, verbose_name=u'Исполнитель заявки',
        blank=True, null=True
    )
    customer = models.ForeignKey(
        Staff, related_name='made_requests', editable=False,
        verbose_name=u'Заказчик книги'
    )
    created_at = models.DateTimeField(
        auto_now_add=True, verbose_name=u'Дата создания заявки'
    )
    modified_at = models.DateTimeField(
        auto_now=True, verbose_name=u'Дата изменения заявки'
    )

    class Meta:
        verbose_name = u'Заявка на покупку книг'
        verbose_name_plural = u'Заявки на покупку книг'

    def __unicode__(self):
        return u'%d [%s] %s' % (self.id, self.customer, self.delivery_office)

    def render_msg_pack(self):
        u'''
            рендерит заявку в набор полей для отправки почтой (возвращает dict)
        '''
        return MailRenderer.render_purchase_request(self)


class PurchaseRequestOneBook(models.Model):
    u'Запись о заказе одной книги'
    request = models.ForeignKey(
        PurchaseRequest, verbose_name=u'Заявка на покупку',
        related_name='requested_books'
    )
    title = models.CharField(
        max_length=255, verbose_name=u'Название книги'
    )
    url = models.URLField(
        verify_exists=False, verbose_name=u'Адрес страницы покупки книги'
    )
    count = models.IntegerField(
        default=1, verbose_name=u'Количество книг'
    )
    shop = models.ForeignKey(
        Shop, verbose_name=u'Магазин', blank=True, null=True
    )
    cost1 = models.DecimalField(
        max_digits=10, decimal_places=2, blank=True, default=0,
        verbose_name=u'Стоимость 1 экземпляра'
    )
    comment = models.TextField(
        blank=False, verbose_name=u'Комментарий', default=u''
    )
    approved = models.BooleanField(
        blank=False, default=True, verbose_name=u'Подтверждена?'
    )


class PurchaseOrder(models.Model):
    u'Заказы во внешних магазинах'

    number = models.CharField(
        max_length=30, blank=True, default='', verbose_name=u'Номер заказа'
    )
    shop = models.ForeignKey(Shop)
    executor = models.ForeignKey(RequestExecutor, blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)

    def __unicode__(self):
        return u'%s / %s' % (self.number, self.shop.name)


class VariantBookInfo(models.Model):
    u'''
        Вариант дополнительной информации о книге
        из внешних источников (магазинов)
    '''

    book = models.ForeignKey(Book)
    current = models.BooleanField(
        verbose_name=u'текущий вариант', default=False
    )
    title = models.CharField(max_length=255)
    authors = models.CharField(max_length=255)
    description = models.TextField(blank=True, null=True)
    # Ссылка на карточку книги во внешнем магазине
    shop_url = models.URLField(blank=True, default='', verify_exists=False)
    # внешняя ссылка на маленькую обложку
    image_s_url = models.URLField(blank=True, default='', verify_exists=False)
    # внешняя ссылка на среднюю обложку
    image_m_url = models.URLField(blank=True, default='', verify_exists=False)
    # внешняя ссылка на большую обложку
    image_l_url = models.URLField(blank=True, default='', verify_exists=False)
    # ИД объекта на Amazon.com
    asin = models.CharField(max_length=15, blank=True, null=True)

    class Meta:
        verbose_name = u'доп. информация'
        verbose_name_plural = u'доп. информация'

    def __unicode__(self):
        return u"%s (%s) [%d] %s (%s)" % (
            self.book.title, self.book.authors_string, self.current,
            self.title, self.authors
        )

    def save(self, force_insert=False, force_update=False):
        u' при сохранении доп.информации обновляем основную обложку у книг '
        # Если текущий вариант обложки выбран и у книги нет основной обложки,
        # зададим её.
        if self.current and not self.book.main_cover:
            #TODO: надо ли проверять BookItem на наличие такой обложки?
            new_cover = BookCover()
            new_cover.download(self.image_l_url, self.book.id)
            self.book.main_cover = new_cover
            self.book.save()

        super(VariantBookInfo, self).save(force_insert, force_update)


class BookQueue(models.Model):
    book = models.ForeignKey(Book)
    user = models.ForeignKey(Staff)
    created_at = models.DateTimeField(auto_now_add=True)
    finished_at = models.DateTimeField(null=True, blank=True)
    finished = models.BooleanField(default=False)


#===== Обработка сигналов =====

# Вешаем на сигналы "сохранение" и "удаление" экземпляра книги
# обновление поля years у книги:
def update_Book_related_fields(sender, instance, **kwargs):
    instance.book.update_related_fields()

post_save.connect(update_Book_related_fields, BookItem)
post_delete.connect(update_Book_related_fields, BookItem)
#TODO: Подумать над оптимизацией при bulk-изменениях (удалении/добавлении)
