from random import choice

from django import forms
from django.conf import settings
from django.contrib.auth.models import User
from django.template.defaultfilters import slugify
from django.template.loader import render_to_string
from django.utils.translation import ugettext_lazy as _
from django.utils.safestring import mark_safe

from guardian.shortcuts import assign

from readthedocs.core.utils import trigger_build
from readthedocs.redirects.models import Redirect
from readthedocs.projects import constants
from readthedocs.projects.models import Project, EmailHook, WebHook
from readthedocs.privacy.loader import AdminPermission


class ProjectForm(forms.ModelForm):
    required_css_class = "required"

    def __init__(self, *args, **kwargs):
        self.user = kwargs.pop('user', None)
        super(ProjectForm, self).__init__(*args, **kwargs)

    def save(self, commit=True):
        project = super(ProjectForm, self).save(commit)
        if commit:
            if self.user and not project.users.filter(pk=self.user.pk).exists():
                project.users.add(self.user)
        return project


class ProjectTriggerBuildMixin(object):
    '''Mixin to trigger build on form save

    This should be replaced with signals instead of calling trigger_build
    explicitly.
    '''

    def save(self, commit=True):
        '''Trigger build on commit save'''
        project = super(ProjectTriggerBuildMixin, self).save(commit)
        if commit:
            trigger_build(project=project)
        return project


class ProjectBackendForm(forms.Form):
    '''Get the import backend'''
    backend = forms.CharField()


class ProjectBasicsForm(ProjectForm):
    '''Form for basic project fields'''

    class Meta:
        model = Project
        fields = ('name', 'repo', 'repo_type')

    def __init__(self, *args, **kwargs):
        show_advanced = kwargs.pop('show_advanced', False)
        super(ProjectBasicsForm, self).__init__(*args, **kwargs)
        if show_advanced:
            self.fields['advanced'] = forms.BooleanField(
                required=False,
                label=_('Edit advanced project options')
            )
        self.fields['repo'].widget.attrs['placeholder'] = self.placehold_repo()
        self.fields['repo'].widget.attrs['required'] = True

    def clean_name(self):
        name = self.cleaned_data.get('name', '')
        if not self.instance.pk:
            potential_slug = slugify(name)
            if Project.objects.filter(slug=potential_slug).exists():
                raise forms.ValidationError(
                    _('Invalid project name, a project already exists with that name'))
        return name

    def clean_repo(self):
        repo = self.cleaned_data.get('repo', '').strip()
        pvt_repos = getattr(settings, 'ALLOW_PRIVATE_REPOS', False)
        if '&&' in repo or '|' in repo:
            raise forms.ValidationError(_(u'Invalid character in repo name'))
        elif '@' in repo and not pvt_repos:
            raise forms.ValidationError(
                _(u'It looks like you entered a private repo - please use the '
                  u'public (http:// or git://) clone url'))
        return repo

    def placehold_repo(self):
        return choice([
            'https://bitbucket.org/cherrypy/cherrypy',
            'https://bitbucket.org/birkenfeld/sphinx',
            'https://bitbucket.org/hpk42/tox',
            'https://github.com/zzzeek/sqlalchemy.git',
            'https://github.com/django/django.git',
            'https://github.com/fabric/fabric.git',
            'https://github.com/ericholscher/django-kong.git',
        ])


class ProjectExtraForm(ProjectForm):

    class Meta:
        model = Project
        fields = (
            'description',
            'documentation_type',
            'language', 'programming_language',
            'project_url',
            'canonical_url',
            'tags',
        )

    def __init__(self, *args, **kwargs):
        super(ProjectExtraForm, self).__init__(*args, **kwargs)
        self.fields['canonical_url'].widget.attrs['placeholder'] = self.placehold_canonical_url()

    def placehold_canonical_url(self):
        return choice([
            'http://docs.fabfile.org',
            'http://example.readthedocs.org',
        ])


class ProjectAdvancedForm(ProjectTriggerBuildMixin, ProjectForm):
    python_interpreter = forms.ChoiceField(
        choices=constants.PYTHON_CHOICES, initial='python',
        help_text=_("(Beta) The Python interpreter used to create the virtual "
                    "environment."))

    class Meta:
        model = Project