""" Catalog models """
from django.conf import settings
from django.db import models
from django.core.urlresolvers import reverse
from django.utils.text import Truncator

from sorl import thumbnail

from catalog.constants import SHIPPING_TYPES, INSTATE, REGULAR, SHIPPING_METHODS
from catalog.managers import (
    ItemManager,
    PersonManager,
    SubscriptionManager,
    ZipCodeManager,
)
from pbp_core.models import OperationalTable
from pbp_core.slugify import unique_slugify

MEDIA_DIRECTORY = settings.MEDIA_ROOT


class Item(OperationalTable):
    """ Item model """

    title = models.CharField(max_length=50)
    long_description = models.TextField(blank=True, null=True)
    synopsis = models.CharField(max_length=200, blank=True, null=True)
    image = thumbnail.ImageField(upload_to="images/sorl", blank=True, null=True)
    price = models.DecimalField(max_digits=7, decimal_places=2)
    # shipping cost for one item
    shipping_cost = models.DecimalField(max_digits=7, decimal_places=2)
    # shipping cost for each item after 1.
    shipping_cost_multiple = models.DecimalField(max_digits=7, decimal_places=2)
    subclass_type = models.CharField(max_length=200, editable=False)
    sku = models.SlugField(max_length=20, unique=True)
    # logical delete Might cause confusion if they want to reuse
    # the SKU again since that is required to be unique.
    deleted = models.BooleanField(default=False)
    featured = models.BooleanField(default=False)
    tax_free = models.BooleanField(default=False)

    objects = ItemManager()

    def __unicode__(self):
        """ unicode repr of class """
        return unicode(self.title)

    def save(self, *args, **kwargs):
        """ save the model """
        # save what kind we are.
        self.subclass_type = self.__class__.__name__.lower()
        super(Item, self).save(*args, **kwargs)

    def child(self):
        """ get the child """
        return getattr(self, self.subclass_type)

    @property
    def is_book(self):
        """ are we a book """
        return self.subclass_type == Book.__name__.lower()

    @property
    def is_movie(self):
        """ are we a movie """
        return self.subclass_type == Movie.__name__.lower()

    @property
    def is_map(self):
        """ is it a map """
        return self.subclass_type == Map.__name__.lower()

    @property
    def is_subscription(self):
        """ is subscription """
        return self.subclass_type == Subscription.__name__.lower()

    @property
    def category(self):
        """ Return a string name for the category the item is in."""
        if self.is_book():
            return "book"
        elif self.is_movie():
            return "movie"
        elif self.is_map():
            return "map"
        elif self.is_subscription():
            return "subscription"
        else:
            return None

    @property
    def edit_link(self):
        """ get the edit link """
        return self.child().edit_link

    def get_absolute_url(self):
        """ get absolute url """
        return reverse("item_detail", kwargs={"sku": self.sku})

    @property
    def short_description(self):
        return Truncator(self.long_description).words(25, truncate=" ...")

    @property
    def description(self):
        return self.long_description


class Person(OperationalTable):
    """ Person Model """

    name = models.CharField(max_length=60)
    slug = models.SlugField(max_length=60, unique=True)
    title = models.CharField(max_length=60, null=True, blank=True, default="")
    image = thumbnail.ImageField(upload_to="images/sorl", blank=True, null=True)
    description = models.TextField(null=True, blank=True, default="")

    # logical delete Might cause confusion if they want to reuse
    # the SKU again since that is required to be unique.
    deleted = models.BooleanField(default=False)

    objects = PersonManager()

    def __repr__(self):
        return u"{0}(name={1}".format(self.__class__, self.name)

    def __str__(self):
        return (
            u"{0}".format(self.name)
            if not self.title
            else u"{0}, {1}".format(self.name, self.title)
        )

    @property
    def edit_link(self):
        """ get the edit link """
        try:
            return reverse("person_edit", kwargs={"person_slug": self.slug})
        except Exception, e:
            print e

    def save(self, *args, **kwargs):
        if not self.slug:
            unique_slugify(self, self.name)
        super(Person, self).save(*args, **kwargs)


class Book(Item):
    """ Book model """

    subtitle = models.CharField(max_length=100, blank=True, null=True)
    authors = models.ManyToManyField(Person, blank=True, null=True)
    editors = models.CharField(max_length=200, blank=True, null=True)
    illustrator = models.CharField(max_length=200, blank=True, null=True)
    publisher = models.CharField(max_length=200, blank=True, null=True)
    printer = models.CharField(max_length=200, blank=True, null=True)
    publish_date = models.CharField(max_length=20, blank=True, null=True)
    edition = models.CharField(max_length=50, blank=True, null=True)
    features = models.CharField(max_length=100, blank=True, null=True)
    dimensions = models.CharField(max_length=20, blank=True, null=True)
    pages = models.IntegerField(blank=True, null=True)
    isbn = models.CharField(max_length=20, blank=True, null=True)
    library_of_congress_number = models.CharField(max_length=20, blank=True, null=True)
    genre = models.CharField(max_length=100, blank=True, null=True)

    objects = ItemManager()

    @property
    def edit_link(self):
        """ get the edit link """
        return reverse("catalog_edit_book", kwargs={"sku": self.sku})


class Movie(Item):
    """ Movie model """

    producer = models.CharField(max_length=200, blank=True, null=True)
    music = models.CharField(max_length=200, blank=True, null=True)
    runtime_minutes = models.IntegerField(blank=True, null=True)
    format = models.CharField(max_length=20, blank=True, null=True)
    region = models.CharField(max_length=50, blank=True, null=True)
    sound = models.CharField(max_length=50, blank=True, null=True)
    language = models.CharField(max_length=50, blank=True, null=True)
    captioning = models.CharField(max_length=50, blank=True, null=True)
    genre = models.CharField(max_length=100, blank=True, null=True)

    objects = ItemManager()

    @property
    def edit_link(self):
        """ get the edit link """
        return reverse("catalog_edit_movie", kwargs={"sku": self.sku})


class Map(Item):
    """ Map model"""

    dimensions = models.CharField(max_length=20, blank=True, null=True)

    objects = ItemManager()

    @property
    def edit_link(self):
        """ get Edit link """
        return reverse("catalog_edit_map", kwargs={"sku": self.sku})


class Subscription(Item):
    """ Subscriptions are items and are operational tables (created by,
    time, ect).
    """

    shipping_type = models.CharField(
        max_length=10, choices=SHIPPING_TYPES, default=INSTATE
    )
    shipping_method = models.CharField(
        max_length=20, choices=SHIPPING_METHODS, default=REGULAR
    )
    duration = models.IntegerField()
    renewal = models.BooleanField(default=False)

    objects = SubscriptionManager()

    @property
    def edit_link(self):
        """ get the edit link"""
        return reverse("catalog_edit_subscription", kwargs={"sku": self.sku})


class ZipCode(OperationalTable):
    """ Zip code model """

    zipcode = models.CharField(max_length=9, unique=True)
    city = models.CharField(max_length=64, blank=True, null=True)
    state = models.CharField(max_length=2, blank=True, null=True)
    county = models.CharField(max_length=64, blank=True, null=True)
    deleted = models.BooleanField(default=False)

    objects = ZipCodeManager()

    def __unicode__(self):
        """ unicode repr of class """
        return unicode(self.zipcode)
