from django.contrib.sites.models import Site
from django.core import urlresolvers
from django.db import models
from django.db.models.fields.files import FileField
from django.utils.encoding import smart_str
from django.utils.hashcompat import sha_constructor
from django.utils.translation import ugettext_lazy as _
from livesettings import config_value
from product import signals
from product.models import Product
import product.modules.downloadable.config
from import Order
from satchmo_utils import normalize_dir
import datetime
import os
import random
def get_product_types():
    return ('DownloadableProduct',)
def _protected_dir(instance, filename):
    # if we get a SettingNotSet exception (even though we've already
    # imported/loaded it), that's bad, so let it bubble up.
    raw = config_value('PRODUCT', 'PROTECTED_DIR')
    updir = os.path.normpath(normalize_dir(raw))
    return os.path.join(updir, instance.file.field.get_filename(filename))
class DownloadableProduct(models.Model):
    This type of Product is a file to be downloaded
    product = models.OneToOneField(Product, verbose_name=_("Product"), primary_key=True)
    file = FileField(_("File"), upload_to=_protected_dir)
    num_allowed_downloads = models.IntegerField(
        _("Num allowed downloads"),
        help_text=_("Number of times link can be accessed. Enter 0 for unlimited."),
    expire_minutes = models.IntegerField(
        _("Expire minutes"),
        help_text=_("Number of minutes the link should remain active. Enter 0 for unlimited."),
    active = models.BooleanField(_("Active"), help_text=_("Is this download currently active?"), default=True)
    is_shippable = False
    is_downloadable = True
    def __unicode__(self):
        return self.product.slug
    def _get_subtype(self):
        return 'DownloadableProduct'
    def create_key(self):
        salt = sha_constructor(str(random.random())).hexdigest()[:5]
        download_key = sha_constructor(salt+smart_str(
        return download_key
    def order_success(self, order, order_item):
        signals.subtype_order_success.send(self, product=self, order=order, subtype="download")
    class Meta:
        verbose_name = _("Downloadable Product")
        verbose_name_plural = _("Downloadable Products")
    def save(self, *args, **kwargs):
        if hasattr(self.product,'_sub_types'):
            del self.product._sub_types
        super(DownloadableProduct, self).save(*args, **kwargs)
class DownloadLink(models.Model):
    downloadable_product = models.ForeignKey(DownloadableProduct, verbose_name=_('Downloadable product'))
    order = models.ForeignKey(Order, verbose_name=_('Order'))
    key = models.CharField(_('Key'), max_length=40)
    num_attempts = models.IntegerField(_('Number of attempts'), )
    time_stamp = models.DateTimeField(_('Time stamp'), )
    active = models.BooleanField(_('Active'), default=True)
    def _attempts_left(self):
        return self.downloadable_product.num_allowed_downloads - self.num_attempts
    attempts_left = property(_attempts_left)
    def is_valid(self):
        # Check num attempts and expire_minutes
        if not
            return (False, _("This download is no longer active"))
        maxattempts = self.downloadable_product.num_allowed_downloads
        if maxattempts > 0 and self.num_attempts >= maxattempts:
            return (False, _("You have exceeded the number of allowed downloads."))
        expiremins = self.downloadable_product.expire_minutes
        expire_time = datetime.timedelta(minutes=expiremins) + self.time_stamp
        if expiremins > 0 and > expire_time:
            return (False, _("This download link has expired."))
        return (True, "")
    def get_absolute_url(self):
        return('', (), { 'download_key': self.key})
    get_absolute_url = models.permalink(get_absolute_url)
    def get_full_url(self):
        url = urlresolvers.reverse('satchmo_download_process', kwargs= {'download_key': self.key})
        return('http://%s%s' % (Site.objects.get_current(), url))
    def save(self, **kwargs):
       Set the initial time stamp
        if self.time_stamp is None:
            self.time_stamp =
        super(DownloadLink, self).save(**kwargs)
    def __unicode__(self):
        return u"%s - %s" % (self.downloadable_product.product.slug, self.time_stamp)
    def _product_name(self):
        return u"%s" % (self.downloadable_product.product.translated_name())
    class Meta:
        verbose_name = _("Download Link")
        verbose_name_plural = _("Download Links")
import config
import listeners