"""UserProfile extension for the Django Auth User system.

The UserProfile is edited as part of the base User interface.
"""
from django.db import models
from django.conf import settings
from django.core.cache import cache
from django.contrib.auth.models import User
from django.core.exceptions import ObjectDoesNotExist
from django.utils.html import escape
from pycon.core import *

############################################################################
##
## Constants
##

## RED_FLAG: turn these into tables and foreign relations (pun intended)
HONORIFIC = Choices([
    ('', ''),
    ('Mr.', 'Mr.'),
    ('Ms.', 'Ms.'),
    ('Mrs.', 'Mrs.'),
    ('Miss', 'Miss'),
    ('Dr.', 'Dr.'),
])

SUFFIX = Choices([
    ('', ''),
    ('Sr.', 'Sr.'),
    ('Jr.', 'Jr.'),
    ('KBE', 'KBE'),
    ('Esq.', 'Esq.'),
    ('I', 'I'),
    ('II', 'II'),
    ('III', 'III'),
    ('IV', 'IV'),
    ('V', 'V'),
    ('1st', '1st'),
    ('2nd', '2nd'),
    ('3rd', '3rd'),
    ('4th', '4th'),
    ('5th', '5th'),
])


@bind_prop_to_class(User, 'html_name')
def __html_name(user):
    prof = None
    try:
        prof = user.get_profile()
    except:
        pass
    if not prof:
        return user.username
    return prof.html_name

@bind_meth_to_class(User, '__str__')
def __extended_user_str(user):
    cache_name = 'user_str_' + repr(user.id)
    res = cache.get(cache_name)
    if res is not None: return res
    prof = None
    try:
        prof = user.get_profile()
    except:
        pass
    if not prof:
        return user.username
    res = prof.long_name
    cache.set(cache_name, res, 60 * 60)
    return res

class UserProfile(models.Model):
    hack = models.BooleanField("Enable Profile", default=True, core=True)
    user = models.ForeignKey(User, unique=True, edit_inline=models.STACKED,
                             num_in_admin=1,min_num_in_admin=1,
                             max_num_in_admin=1,num_extra_on_change=0)
    honorific = models.CharField(maxlength=10, blank=True, null=True,
                                 choices=HONORIFIC,
                                 default=HONORIFIC.default)
    middle = models.CharField(maxlength=30, blank=True, null=True)
    suffix = models.CharField(maxlength=10, blank=True, null=True,
                              choices=SUFFIX,
                              default=SUFFIX.default)
    url = models.URLField(blank=True, null=True)
    affiliation = models.CharField(maxlength=200, blank=True, null=True)
    bio = models.TextField(blank=True)
    code = models.CharField(maxlength=40, editable=False,
                            null=True, blank=True)
    
    def __init__(self, *args, **kwdargs):
        super(UserProfile, self).__init__(*args, **kwdargs)
        self.hack = True
    
    def activate(self, code):
        if self.code.upper() == code.upper():
            self.code = ''
            self.user.is_active=True
            self.user.save()
            self.save()
            return True
        return False
    
    @property
    def html_name(self):
        base = escape(self.long_name)
        url_fmt = r'%s'
        if self.url:
            url_fmt = '<a href="' + self.url + '">%s</a>'
        if self.affiliation:
            return base + " (" + url_fmt%escape(self.affiliation) + ")"
        return url_fmt % base
    
    @property
    def long_name(self):
        parts = []
        if self.honorific:
            parts.append(self.honorific)
        user = self.user
        if user.first_name:
            parts.append(user.first_name)
        if self.middle:
            parts.append(self.middle)
        if user.last_name:
            parts.append(user.last_name)
        if self.suffix:
            parts.append(self.suffix)
        name = " ".join(parts)
        if not name.strip():
            name = user.username
        return name
    
    @property
    def short_name(self):
        return ' '.join([self.user.first_name, self.user.last_name])

    @property
    def last_first(self):
        return ', '.join([self.user.last_name, self.user.first_name])
    
    def __str__(self):
        username = '(' + self.user.username + ')'
        return ' '.join([self.long_name, username])
