class Team(models.Model):
    """
    A team of participants that will work on a project and compete for fabulous
    prizes, fame, and glory.

    Upon creation, a team needs:

        * a name--hopefully an awesome one
        * a slug, to be used for the URL of the team's page
        * a project description
        * a project type, so that we can differentiate "real" hacks vs. thought
          experiments (aka "code vs. ppt")
        * a creator
        * a captain
        * team members
        * a judged category
        * a charity that the team is supporting

    The creator and captain may have management powers above and beyond
    those of a mere member.
    """

    name = models.CharField('name of team', max_length=255, db_index=True,
            unique=True)
    slug = models.SlugField('slugified team name', db_index=True, unique=True,
            editable=False)

    project = models.TextField('description of project')
    logo = models.ImageField('team logo image', blank=True,
            upload_to=create_unique_team_filename)

    project_type = models.CharField('type of project', max_length=1,
            db_index=True, choices=PROJECT_TYPE.CHOICES)
    status = models.CharField(max_length=1, db_index=True,
            choices=STATUS.CHOICES)

    creator = models.ForeignKey(User,
            related_name="%(app_label)s_%(class)s_creator")
    captain = models.ForeignKey(User,
            related_name="%(app_label)s_%(class)s_captain")
    members = models.ManyToManyField(User,
            related_name="%(app_label)s_%(class)s_members")

    attachments = models.ManyToManyField(Attachment, blank=True,
            related_name="%(app_label)s_%(class)s_attachments")
    images = models.ManyToManyField(ImageAttachment, blank=True,
            related_name="%(app_label)s_%(class)s_images")
    links = models.ManyToManyField(Link, blank=True,
            related_name="%(app_label)s_%(class)s_links")

    category = models.ForeignKey(Category)
    charity = models.ForeignKey(Charity)

    create_date = models.DateTimeField('date created', auto_now_add=True)
    mod_date = models.DateTimeField('date modified', auto_now=True)

    @property
    def is_concept(self):
        return self.project_type == PROJECT_TYPE.CONCEPT

    @property
    def is_implemented(self):
        return self.project_type == PROJECT_TYPE.IMPLEMENTED

    def save(self, *args, **kwargs):
        self.slug = slugify(self.name)  #TODO: check if slug exists in DB
        return super(Team, self).save()

    def add_captain_as_member(self):
        if not self.is_member(self.captain):
            self.members.add(self.captain)
            self.save()

    def is_member(self, user):
        return user in self.members.all()

    def __unicode__(self):
        return self.name

    class Meta:
        ordering = ['name'] class STATUS(object):
    """
    Status of the team
    """
    ACTIVE = 'A'
    DISQUALIFIED = 'D'
    DELETED = 'X'

    CHOICES = (
        (ACTIVE, 'Active'),
        (DISQUALIFIED, 'Disqualified'),
        (DELETED, 'Deleted'),
    ) def delete(request, slug):
    try:
        team = Team.objects.get(slug=slug)
        if team.is_member(request.user):
            team.status = STATUS.DELETED
            team.save()
            return HttpResponseRedirect(reverse('teams-list'))
        else:
            return HttpResponseRedirect(reverse('teams-detail',
                kwargs={'slug': slug}))
    except:
        return HttpResponseRedirect(reverse('teams-detail',
            kwargs={'slug': slug})) def upload_attachment(request, slug):
    env = {}

    team = Team.objects.get(slug=slug)
    if not team.is_member(request.user):
        return HttpResponseRedirect(reverse('teams-detail',
            kwargs={'slug': slug}))

    if request.method == 'POST':
        form = AttachmentForm(request.POST, request.FILES)
        if form.is_valid():
            attachment = Attachment(attached_file = form.cleaned_data['attached_file'],
                                   title = form.cleaned_data['title'],
                                   alt_text = form.cleaned_data['alt_text'])
            attachment.save()
            team.attachments.add(attachment)
            return HttpResponseRedirect(reverse('teams-detail',
                kwargs={'slug': slug}))
    else:
        form = AttachmentForm()

    env['form'] = form
    return render(request, 'teams/upload.html', env) def remove_attachment(request, slug, attachment_id):
    team = Team.objects.get(slug=slug)
    if team.is_member(request.user):
        attachment = Attachment.objects.get(id=attachment_id)
        team.attachments.remove(attachment)

    return HttpResponseRedirect(reverse('teams-detail',
        kwargs={'slug': slug})) def upload_image(request, slug):
    env = {}

    team = Team.objects.get(slug=slug)
    if not team.is_member(request.user):
        return HttpResponseRedirect(reverse('teams-detail',
            kwargs={'slug': slug}))

    if request.method == 'POST':
        form = ImageAttachmentForm(request.POST, request.FILES)
        if form.is_valid():
            image = ImageAttachment(attached_file = form.cleaned_data['attached_file'],
                                    title = form.cleaned_data['title'],
                                    alt_text = form.cleaned_data['alt_text'])
            image.save()
            team.images.add(image)
            return HttpResponseRedirect(reverse('teams-detail',
                kwargs={'slug': slug}))
    else:
        form = ImageAttachmentForm()

    env['form'] = form
    return render(request, 'teams/upload.html', env) def remove_image(request, slug, attachment_id):
    team = Team.objects.get(slug=slug)
    if team.is_member(request.user):
        image = ImageAttachment.objects.get(id=attachment_id)
        team.images.remove(image)

    return HttpResponseRedirect(reverse('teams-detail',
        kwargs={'slug': slug})) def add_link(request, slug):
    env = {}

    team = Team.objects.get(slug=slug)
    if not team.is_member(request.user):
        return HttpResponseRedirect(reverse('teams-detail',
            kwargs={'slug': slug}))

    if request.method == 'POST':
        form = LinkAttachmentForm(request.POST)
        if form.is_valid():
            link = Link(url = form.cleaned_data['url'],
                        title = form.cleaned_data['title'],
                        text = form.cleaned_data['text'])
            link.save()
            team.links.add(link)
            return HttpResponseRedirect(reverse('teams-detail',
                kwargs={'slug': slug}))
    else:
        form = LinkAttachmentForm()

    env['form'] = form
    return render(request, 'teams/upload.html', env) def remove_link(request, slug, attachment_id):
    team = Team.objects.get(slug=slug)
    if team.is_member(request.user):
        link = Link.objects.get(id=attachment_id)
        team.links.remove(link)

    return HttpResponseRedirect(reverse('teams-detail',
        kwargs={'slug': slug})) class TeamCreateView(CreateView):
    model = Team
    form_class = CreateTeamForm

    @method_decorator(login_required)
    def dispatch(self, *args, **kwargs):
        """ If team creation is disabled (via admin), redirect.
        """
        try:
            online = TeamCreateStatus.objects.all()[0].online
        except:
            online = True

        if online:
            return super(CreateView, self).dispatch(*args, **kwargs)
        else:
            return render(args[0], 'teams/create_offline.html');

    def form_valid(self, form):
        """ Because team doesn't exist in DB yet, and creator is required,
            we need to first save the form, add creator, and THEN save to DB
        """
        team = form.save(commit=False)
        team.status = STATUS.ACTIVE
        team.creator = self.request.user
        team.save()
        form.save_m2m()
        team.add_captain_as_member()

        return HttpResponseRedirect(reverse('teams-detail',
            kwargs={'slug': team.slug})) class TeamDetailView(DetailView):
    model = Team
    queryset = Team.objects.filter(status=STATUS.ACTIVE)

    def get_context_data(self, **kwargs):
        context = super(TeamDetailView, self).get_context_data(**kwargs)
        try:
            online = TeamCreateStatus.objects.all()[0].online
        except:
            online = True
        context["create_status"] = online
        return context class TeamListView(ListView):
    model = Team
    queryset = Team.objects.filter(status=STATUS.ACTIVE)

    def get_context_data(self, **kwargs):
        context = super(TeamListView, self).get_context_data(**kwargs)
        try:
            online = TeamCreateStatus.objects.all()[0].online
        except:
            online = True
        context["create_status"] = online
        return context class TeamUpdateView(UpdateView):
    model = Team
    form_class = UpdateTeamForm
    queryset = Team.objects.filter(status=STATUS.ACTIVE)

    @method_decorator(login_required)
    def dispatch(self, *args, **kwargs):
        """ If user isn't a team member (or team isn't active),
            redirect to team listing.
        """
        try:
            response = super(TeamUpdateView, self).dispatch(*args, **kwargs)
        except:
            return HttpResponseRedirect(reverse('teams-list'))
        if not self.object.is_member(self.request.user):
            return HttpResponseRedirect(reverse('teams-list'))
        return response

    def form_valid(self, form):
        """ In case the user forgets, add the captain as a team member.
        """
        team = form.save()
        team.add_captain_as_member()

        return HttpResponseRedirect(reverse('teams-detail',
            kwargs={'slug': team.slug}))
from django.conf.urls.defaults import patterns, url
from hackday.teams.models import Team, STATUS
from hackday.teams.views import delete
from hackday.teams.views import upload_attachment, remove_attachment
from hackday.teams.views import upload_image, remove_image
from hackday.teams.views import add_link, remove_link
from hackday.teams.views import TeamCreateView
from hackday.teams.views import TeamDetailView
from hackday.teams.views import TeamListView
from hackday.teams.views import TeamUpdateView



urlpatterns = patterns('hackday.teams.views',
    url(r'^/?$', TeamListView.as_view(), name='teams-list'),
    url(r'^create/?$', TeamCreateView.as_view(), name='teams-create'),
    url(r'^edit/(?P<slug>[\w-]+)/*$', TeamUpdateView.as_view(),
        name='teams-edit'),
    url(r'^(?P<slug>[\w-]+)/*$', TeamDetailView.as_view(),
        name='teams-detail'),
    url(r'^delete/(?P<slug>[\w-]+)/*$', delete, name='teams-delete'),
    url(r'^upload-attachment/(?P<slug>[\w-]+)$',
        upload_attachment,
        name='teams-upload-attachment'),
    url(r'^delete-attachment/(?P<slug>[\w-]+)/(?P<attachment_id>[\d]+)$',
        remove_attachment,
        name='teams-remove-attachment'),
    url(r'^upload-image/(?P<slug>[\w-]+)$',
        upload_image,
        name='teams-upload-image'),
    url(r'^delete-image/(?P<slug>[\w-]+)/(?P<attachment_id>[\d]+)$',
        remove_image,
        name='teams-remove-image'),
    url(r'^add-link/(?P<slug>[\w-]+)$',
        add_link,
        name='teams-add-link'),
    url(r'^delete-link/(?P<slug>[\w-]+)/(?P<attachment_id>[\d]+)$',

        remove_link,