""" puttin' books on shelves """
import re
from django.db import models

from bookwyrm import activitypub
from .activitypub_mixin import CollectionItemMixin, OrderedCollectionMixin
from .base_model import BookWyrmModel
from . import fields


class Shelf(OrderedCollectionMixin, BookWyrmModel):
    """a list of books owned by a user"""

    TO_READ = "to-read"
    READING = "reading"
    READ_FINISHED = "read"

    READ_STATUS_IDENTIFIERS = (TO_READ, READING, READ_FINISHED)

    name = fields.CharField(max_length=100)
    identifier = models.CharField(max_length=100)
    user = fields.ForeignKey(
        "User", on_delete=models.PROTECT, activitypub_field="owner"
    )
    editable = models.BooleanField(default=True)
    privacy = fields.PrivacyField()
    books = models.ManyToManyField(
        "Edition",
        symmetrical=False,
        through="ShelfBook",
        through_fields=("shelf", "book"),
    )

    activity_serializer = activitypub.Shelf

    def save(self, *args, **kwargs):
        """set the identifier"""
        super().save(*args, **kwargs)
        if not self.identifier:
            self.identifier = self.get_identifier()
            super().save(*args, **kwargs, broadcast=False)

    def get_identifier(self):
        """custom-shelf-123 for the url"""
        slug = re.sub(r"[^\w]", "", self.name).lower()
        return "{:s}-{:d}".format(slug, self.id)

    @property
    def collection_queryset(self):
        """list of books for this shelf, overrides OrderedCollectionMixin"""
        return self.books.order_by("shelfbook")

    def get_remote_id(self):
        """shelf identifier instead of id"""
        base_path = self.user.remote_id
        identifier = self.identifier or self.get_identifier()
        return "%s/books/%s" % (base_path, identifier)

    class Meta:
        """user/shelf unqiueness"""

        unique_together = ("user", "identifier")


class ShelfBook(CollectionItemMixin, BookWyrmModel):
    """many to many join table for books and shelves"""

    book = fields.ForeignKey(
        "Edition", on_delete=models.PROTECT, activitypub_field="book"
    )
    shelf = models.ForeignKey("Shelf", on_delete=models.PROTECT)
    user = fields.ForeignKey(
        "User", on_delete=models.PROTECT, activitypub_field="actor"
    )

    activity_serializer = activitypub.ShelfItem
    collection_field = "shelf"

    def save(self, *args, **kwargs):
        if not self.user:
            self.user = self.shelf.user
        super().save(*args, **kwargs)

    class Meta:
        """an opinionated constraint!
        you can't put a book on shelf twice"""

        unique_together = ("book", "shelf")
        ordering = ("-created_date",)