from datetime import *
from dateutil import relativedelta

from django.db import models
from django.db.models import permalink
from django.utils.translation import ugettext_lazy as _
from django.core.urlresolvers import reverse
from django.contrib.auth.models import User
from django.contrib.localflavor.us.models import PhoneNumberField, USStateField

from directory.models import Point, Person, Town, Place


class StandardMetadata(models.Model):
    """
    A basic (abstract) model for metadata.
    
    Included in each model file to maintain application separation.
    
    Subclass new models from 'StandardMetadata' instead of 'models.Model'.
    """

    created = models.DateTimeField(default=datetime.now, editable=False)
    updated = models.DateTimeField(default=datetime.now, editable=False)

    class Meta:
        abstract = True

    def save(self, *args, **kwargs):
        self.updated = datetime.now()
        super(StandardMetadata, self).save(*args, **kwargs)


class Category(models.Model):
    """Place categories model."""

    title = models.CharField(_("title"), max_length=100, unique=True)
    slug = models.SlugField(_("slug"), unique=True)

    class Meta:
        verbose_name = _("category")
        verbose_name_plural = _("categories")
        ordering = ("title",)

    def __unicode__(self):
        return u"%s" % self.title

    def get_absolute_url(self):
        return reverse("mk-category-index", args=[self.slug])


class Subcategory(models.Model):
    """Place subcategories model."""

    title = models.CharField(_("title"), max_length=100, unique=True)
    slug = models.SlugField(_("slug"), unique=True)
    category = models.ForeignKey(Category)

    class Meta:
        verbose_name = _("subcategory")
        verbose_name_plural = _("subcategories")
        ordering = (
            "category",
            "title",
        )

    def __unicode__(self):
        return u"%s" % self.title

    def get_absolute_url(self):
        args = [self.category.slug, self.slug]
        return reverse("mk-subcategory-index", args=args)


class Feature(models.Model):
    name = models.CharField(_("name"), max_length=200)
    slug = models.SlugField(_("slug"), unique=True)
    description = models.CharField(
        _("description"), max_length=255, blank=True, null=True
    )

    class Meta:
        verbose_name = _("feature")
        verbose_name_plural = _("features")
        ordering = ("name",)

    def __unicode__(self):
        return u"%s" % self.name


class PaymentMethod(StandardMetadata):
    """Payment methods accepted by businesses."""

    name = models.CharField(_("name"), max_length=50)
    slug = models.SlugField(_("slug"), unique=True)
    icon = models.ImageField(
        _("icon"), upload_to="marketplace/paymenticons/", blank=True, null=True
    )

    class Meta:
        verbose_name = _("payment method")
        verbose_name_plural = _("payment methods")
        ordering = ("name",)

    def __unicode__(self):
        return u"%s" % self.name

    # def get_absolute_url(self):
    #    args=[self.slug]
    #    return reverse ('mk-payment-method-detail', args=args)


class Business(StandardMetadata):
    """Base class for business models for Marketplace application.
        
       A business at it's simplest is a listing.
       It can be piled up with all manner of other things as upsells.
       Upsells are represented by the objects listing status."""

    STATUS_CHOICES = (
        (0, "Inactive"),
        (1, "Basic"),
        (2, "Full"),
        (3, "Hosted"),
    )
    point = models.ForeignKey(Point, blank=True, null=True)
    owner = models.ForeignKey(
        Person, blank=True, null=True
    )  # Eventually we want this to be a UserProfile class
    name = models.CharField(_("name"), max_length=255)
    slug = models.SlugField(_("slug"), unique=True)
    brief_hours = models.CharField(
        _("brief hours"), blank=True, null=True, max_length=255
    )
    logo = models.ImageField(
        _("logo or photo"), upload_to="marketplace/logos/", blank=True
    )
    unit = models.CharField(
        _("unit"), blank=True, max_length=100, help_text="Suite or Apartment #"
    )
    po_box = models.CharField(_("post office box"), blank=True, null=True, max_length=5)
    post_office = models.ForeignKey(
        Place, related_name="post_office", blank=True, null=True
    )
    phone = PhoneNumberField(_("primary phone"), blank=True, null=True)
    phone_title = models.CharField(
        _("phone one title"), blank=True, null=True, max_length=25
    )
    phone_2 = PhoneNumberField(_("phone two"), blank=True, null=True)
    phone_2_title = models.CharField(
        _("phone two title"), blank=True, null=True, max_length=25
    )
    phone_3 = PhoneNumberField(_("phone three"), blank=True, null=True)
    phone_3_title = models.CharField(
        _("phone three title"), blank=True, null=True, max_length=25
    )
    mobile_phone = PhoneNumberField(_("mobile phone"), blank=True, null=True)
    fax = PhoneNumberField(_("fax"), blank=True, null=True)
    url = models.URLField(_("url"), blank=True, verify_exists=False)
    email = models.EmailField(_("email"), blank=True)
    brief_hours = models.CharField(
        _("brief hours"), blank=True, null=True, max_length=255
    )
    directions = models.CharField(
        _("directions"), blank=True, null=True, max_length=255
    )
    twitter = models.CharField(
        _("twitter account"), blank=True, null=True, max_length=255
    )
    facebook = models.CharField(
        _("facebook profile"), blank=True, null=True, max_length=255
    )
    brief = models.CharField(_("brief"), max_length=140, blank=True, null=True)
    description = models.TextField(_("description"), blank=True, null=True)
    payment_accepted = models.ManyToManyField(PaymentMethod, blank=True, null=True)
    status = models.IntegerField(_("listing status"), choices=STATUS_CHOICES, default=1)
    paid_through = models.DateField(_("paid through date"), blank=True, null=True)
    features = models.ManyToManyField(Feature, blank=True, null=True)
    categories = models.ManyToManyField(Category)
    subcategories = models.ManyToManyField(Subcategory)
    with_branches = models.BooleanField(
        _("show with branches"),
        default=True,
        help_text="If this business has branch offices, do we show this listing as the primary office?",
    )
    internal_notes = models.TextField(
        _("Internal notes"),
        blank=True,
        null=True,
        help_text="Does not appear on public site, only for admin notes.",
    )

    class Meta:
        verbose_name = _("business")
        verbose_name_plural = _("businesses")
        ordering = ("point__town", "name")
        get_latest_by = "created"

    def __unicode__(self):
        return u"%s" % self.name

    def get_absolute_url(self):
        return reverse("mk-business-detail", args=[self.slug])


class BusinessPhoto(StandardMetadata):
    business = models.ForeignKey(Business)
    branch = models.ForeignKey("Branch", blank=True, null=True)
    photo = models.ImageField(
        _("photo"), upload_to="marketplace/photos/", blank=True, null=True
    )
    caption = models.CharField(_("caption"), max_length=255, blank=True, null=True)
    credit = models.CharField(_("credit"), blank=True, null=True, max_length=150)
    ordering = models.IntegerField(_("ordering"), max_length=3, blank=True, null=True)

    class Meta:
        ordering = ["ordering"]
        get_latest_by = "created"
        verbose_name = _("business photo")
        verbose_name_plural = _("business photos")

    def __unicode__(self):
        return self.business.name + " photo"

    def __str__(self):
        return self.__unicode__()


class Branch(StandardMetadata):
    """Branch model
    
    A branch is another physical location of a business. For example, banks often have multiple 
    branches. Branches do not exist without an associated business, but most contact information 
    can be unique from the business.
    
    It is assumed at this point that all branches share the same features and payment methods as 
    their central office. Though in the long run, this may not be a desirable way to manage these things.
    """

    business = models.ForeignKey(Business)
    name = models.CharField(_("name"), blank=True, null=True, max_length=150)
    point = models.ForeignKey(Point, blank=True, null=True)
    slug = models.SlugField(_("slug"), unique=True)
    logo = models.ImageField(
        _("logo or photo"), upload_to="marketplace/logos/", blank=True
    )
    unit = models.CharField(
        _("unit"), blank=True, max_length=100, help_text="Suite or Apartment #"
    )
    po_box = models.CharField(_("post office box"), blank=True, null=True, max_length=5)
    brief_hours = models.CharField(
        _("brief hours"), blank=True, null=True, max_length=255
    )
    phone = PhoneNumberField(_("primary phone"), blank=True, null=True)
    tollfree_phone = PhoneNumberField(_("toll-free phone"), blank=True, null=True)
    mobile_phone = PhoneNumberField(_("mobile phone"), blank=True, null=True)
    fax = PhoneNumberField(_("fax"), blank=True, null=True)
    url = models.URLField(_("url"), blank=True, verify_exists=False)
    email = models.EmailField(_("email"), blank=True)
    twitter = models.CharField(
        _("twitter account"), blank=True, null=True, max_length=255
    )
    facebook = models.CharField(
        _("facebook profile"), blank=True, null=True, max_length=255
    )

    class Meta:
        verbose_name = _("branch office")
        verbose_name_plural = _("branch offices")
        ordering = ("business", "point")
        get_latest_by = "created"

    def __unicode__(self):
        return u"%s, %s branch" % (self.business, self.point.town.name)

    def get_absolute_url(self):
        return reverse("mk-branch-detail", args=[self.slug])


class BaseHours(models.Model):
    mon_open = models.TimeField(_("monday opening"), blank=True, null=True)
    mon_close = models.TimeField(_("monday closing"), blank=True, null=True)
    tue_open = models.TimeField(_("tuesday opening"), blank=True, null=True)
    tue_close = models.TimeField(_("tuesday closing"), blank=True, null=True)
    wed_open = models.TimeField(_("wednesday opening"), blank=True, null=True)
    wed_close = models.TimeField(_("wednesday closing"), blank=True, null=True)
    thu_open = models.TimeField(_("thursday opening"), blank=True, null=True)
    thu_close = models.TimeField(_("thursday closing"), blank=True, null=True)
    fri_open = models.TimeField(_("friday opening"), blank=True, null=True)
    fri_close = models.TimeField(_("friday closing"), blank=True, null=True)
    sat_open = models.TimeField(_("saturday opening"), blank=True, null=True)
    sat_close = models.TimeField(_("saturday closing"), blank=True, null=True)
    sun_open = models.TimeField(_("sunday opening"), blank=True, null=True)
    sun_close = models.TimeField(_("sunday closing"), blank=True, null=True)

    class Meta:
        abstract = True


class Hours(BaseHours):
    title = models.CharField(_("title"), blank=True, null=True, max_length=100)
    business = models.ForeignKey(Business)
    branch = models.ForeignKey(Branch, blank=True, null=True)
    mon_by_appt = models.BooleanField(_("monday by appt"), default=False)
    tue_by_appt = models.BooleanField(_("tuesday by appt"), default=False)
    wed_by_appt = models.BooleanField(_("wednesday by appt"), default=False)
    thu_by_appt = models.BooleanField(_("thursday by appt"), default=False)
    fri_by_appt = models.BooleanField(_("friday by appt"), default=False)
    sat_by_appt = models.BooleanField(_("saturday by appt"), default=False)
    sun_by_appt = models.BooleanField(_("sunday by appt"), default=False)
    addtional = models.CharField(
        _("additional info"), blank=True, null=True, max_length=200
    )

    class Meta:
        verbose_name = _("hours")
        verbose_name_plural = _("hours")

    def __unicode__(self):
        return u"%s hours" % (self.business)


class Meal(models.Model):
    name = models.CharField(_("name"), max_length=100)
    slug = models.SlugField(_("slug"), unique=True)

    def __unicode__(self):
        return self.name


class Menu(StandardMetadata):
    business = models.ForeignKey(Business)
    file = models.FileField(
        _("file"), upload_to="marketplace/menus/", blank=True, null=True
    )
    menu_text = models.TextField(_("menu text"), blank=True, null=True)
    expire_date = models.DateField(_("valid until"), blank=True, null=True)
    meal = models.ForeignKey(Meal)
    sample = models.BooleanField(
        _("sample"),
        default=False,
        help_text="Use this if your menu is to be used only as a sample of the sorts of food served.",
    )

    def __unicode__(self):
        return u"%s %s menu" % (self.business, self.meal)


class DiningHours(BaseHours):
    business = models.ForeignKey(Business)
    branch = models.ForeignKey(Branch, blank=True, null=True)
    meal = models.ForeignKey(Meal)
    additional = models.CharField(
        _("additional info"), blank=True, null=True, max_length=200
    )

    class Meta:
        verbose_name = _("dining hours")
        verbose_name_plural = _("dining hours")

    def __unicode__(self):
        return u"%s - %s hours" % (self.business, self.meal)


class Link(StandardMetadata):
    business = models.ForeignKey(Business)
    url = models.URLField("URL", verify_exists=False)
    title = models.CharField(_("title"), max_length=255)
    description = models.CharField(
        _("description"), max_length=200, blank=True, null=True
    )

    class Meta:
        verbose_name = _("link")
        verbose_name_plural = _("links")
        ordering = ("created", "updated")
        get_latest_by = "created"

    def __unicode__(self):
        return self.title


class Reference(StandardMetadata):
    business = models.ForeignKey(Business)
    source = models.CharField(_("source"), max_length=255)
    slug = models.SlugField(_("slug"))
    body = models.CharField(_("description"), max_length=255)

    class Meta:
        verbose_name = _("reference")
        verbose_name_plural = _("references")
        ordering = ("created", "updated")
        get_latest_by = "created"

    def __unicode__(self):
        return u"%s reference from %s" % (self.business, self.source)


class Ad(StandardMetadata):
    business = models.ForeignKey(Business)
    title = models.CharField(_("title"), max_length=255)
    slug = models.SlugField(_("slug"))
    start_date = models.DateField(_("start date"), blank=True, null=True)
    expire_date = models.DateField(_("expiration date"), blank=True, null=True)
    body = models.CharField(_("description"), max_length=200, blank=True, null=True)
    file = models.FileField(_("file"), upload_to="marketplace/flyers/")

    class Meta:
        verbose_name = _("advert")
        verbose_name_plural = _("adverts")
        ordering = ("created", "updated")
        get_latest_by = "created"

    def __unicode__(self):
        return u"%s ad - %s" % (self.business, self.title)

    def get_absolute_url(self):
        args = [self.business.slug, self.slug]
        return reverse("mk-ad-detail", args=args)


class Guide(StandardMetadata):
    title = models.CharField(_("title"), max_length=255)
    slug = models.SlugField(_("slug"))
    published = models.BooleanField(_("published"), default=False)
    pub_date = models.DateField(_("publish date"))
    featured = models.BooleanField(_("featured"), default=False)
    logo = models.ImageField(
        _("logo or photo"), upload_to="marketplace/guides/logos/", blank=True
    )
    logo_thumbnail = models.ImageField(
        _("Thumbnail of logo (optionl)"),
        upload_to="marketplace/section/logos/thumbnails/",
        blank=True,
        null=True,
        help_text="An optional thumbnail of the logo. If not used, a thumbnail will be generated from the logo.",
    )
    tag_line = models.CharField(_("Tag line"), max_length=255, blank=True, null=True)
    brief_description = models.CharField(
        _("Brief description"), max_length=255, blank=True, null=True
    )
    description = models.TextField(_("description"), blank=True, null=True)
    categories = models.ManyToManyField(Category, blank=True, null=True)
    subcategories = models.ManyToManyField(Subcategory, blank=True, null=True)
    businesses = models.ManyToManyField(Business, blank=True, null=True)
    template_name = models.CharField(
        _("template name"),
        max_length=70,
        blank=True,
        help_text=_(
            "Example: 'marketplace/guides/seasonal_guide.html'. If this isn't provided, the system will use 'marketplace/guides/default.html'."
        ),
    )

    class Meta:
        verbose_name = _("Guide")
        verbose_name_plural = _("Guides")
        ordering = ("pub_date", "updated")
        get_latest_by = "pub_date"

    def __unicode__(self):
        return u"%s" % (self.title)

    def get_absolute_url(self):
        args = [self.slug]
        return reverse("mk-guide-detail", args=args)
