class LoginForm(AuthenticationForm):

    def clean_username(self):
        email = self.cleaned_data['username']
        user = User.objects.filter(email=email)
        if not user:
            raise forms.ValidationError('Email is not registered.')
        elif not user[0].is_active:
            raise forms.ValidationError('Your account is not activated yet!')
        return email class ForumCategory(models.Model):
    created_by = models.ForeignKey(User)
    title = models.CharField(max_length=1000)
    is_active = models.BooleanField(default=False)
    color = models.CharField(max_length=20, default="#999999")
    is_votable = models.BooleanField(default=False)
    created_on = models.DateTimeField(auto_now_add=True)
    slug = models.SlugField(max_length=1000)
    description = models.TextField()
    parent = models.ForeignKey('self', blank=True, null=True)

    def get_topics(self):
        topics = Topic.objects.filter(category=self, status='Published')
        return topics

    def __str__(self):
        return self.title STATUS = (
    ('Draft', 'Draft'),
    ('Published', 'Published'),
    ('Disabled', 'Disabled'),
) class Badge(models.Model):
    title = models.CharField(max_length=50, unique=True)
    slug = models.CharField(max_length=50, unique=True)

    def get_users(self):
        user_profile = UserProfile.objects.filter(badges__in=[self])
        return user_profile class Topic(models.Model):
    title = models.CharField(max_length=2000)
    description = models.TextField()
    created_by = models.ForeignKey(User)
    status = models.CharField(choices=STATUS, max_length=10)
    category = models.ForeignKey(ForumCategory)
    created_on = models.DateTimeField(auto_now=True)
    updated_on = models.DateTimeField(auto_now=True)
    no_of_views = models.IntegerField(default='0')
    slug = models.SlugField(max_length=1000)
    tags = models.ManyToManyField(Tags)
    no_of_likes = models.IntegerField(default='0')
    votes = models.ManyToManyField(Vote)

    def get_comments(self):
        comments = Comment.objects.filter(topic=self, parent=None)
        return comments

    def get_all_comments(self):
        comments = Comment.objects.filter(topic=self)
        return comments

    def get_last_comment(self):
        comments = Comment.objects.filter(topic=self).order_by('-updated_on').first()
        return comments

    def get_topic_users(self):
        comment_user_ids = Comment.objects.filter(topic=self).values_list('commented_by', flat=True)
        liked_users_ids = UserTopics.objects.filter(topic=self, is_like=True).values_list('user', flat=True)
        followed_users = UserTopics.objects.filter(topic=self, is_followed=True).values_list('user', flat=True)
        all_users = list(comment_user_ids) + list(liked_users_ids) + list(followed_users) + [self.created_by.id]
        users = UserProfile.objects.filter(user_id__in=set(all_users))
        return users

    # def get_total_of_votes(self):
    #     no_of_votes = self.no_of_votes + self.no_of_down_votes
    #     return no_of_votes

    def up_votes_count(self):
        return self.votes.filter(type="U").count()

    def down_votes_count(self):
        return self.votes.filter(type="D").count()  

    def __str__(self):
        return self.title       class Tags(models.Model):
    title = models.CharField(max_length=50, unique=True)
    slug = models.CharField(max_length=50, unique=True)

    def get_topics(self):
        topics = Topic.objects.filter(tags__in=[self], status='Published')
        return topics class UserProfile(models.Model):
    file_prepend = "forum_user/profilepics/"
    
    user = models.ForeignKey(User)
    used_votes = models.IntegerField(default='0')
    user_roles = models.CharField(choices=USER_ROLES, max_length=10)
    badges = models.ManyToManyField(Badge)
    profile_pic = models.FileField(
        max_length=500, null=True, blank=True, upload_to=img_url)
    send_mailnotifications = models.BooleanField(default=False)

    # need to add social details for a user if we implement socail login

    def get_no_of_up_votes(self):
        user_topics = UserTopics.objects.filter(user=self.user)
        votes = 0
        for topic in user_topics:
            votes += topic.no_of_votes
        return votes

    def get_no_of_down_votes(self):
        user_topics = UserTopics.objects.filter(user=self.user)
        votes = 0
        for topic in user_topics:
            votes += topic.no_of_down_votes
        return votes

    def get_topics(self):
        topics = Topic.objects.filter(created_by=self.user)
        return topics

    def get_followed_topics(self):
        topics = UserTopics.objects.filter(user=self.user, is_followed=True)
        topics = Topic.objects.filter(id__in=topics.values_list('topic', flat=True))
        return topics

    def get_liked_topics(self):
        topics = UserTopics.objects.filter(user=self.user, is_like=True)
        topics = Topic.objects.filter(id__in=topics.values_list('topic', flat=True))
        return topics

    def get_timeline(self):
        timeline = Timeline.objects.filter(user=self.user).order_by('-created_on')
        return timeline

    def get_user_topic_tags(self):
        tags = Tags.objects.filter(id__in=self.get_topics().values_list('tags', flat=True))
        return tags

    def get_user_topic_categories(self):
        categories = ForumCategory.objects.filter(id__in=self.get_topics().values_list('category', flat=True))
        return categories
        # return []

    def get_user_suggested_topics(self):
        categories = ForumCategory.objects.filter(id__in=self.get_topics().values_list('category', flat=True))
        topics = Topic.objects.filter(category__id__in=categories.values_list('id', flat=True))
        return topics
        # return [] class UserTopics(models.Model):
    user = models.ForeignKey(User)
    topic = models.ForeignKey(Topic)
    is_followed = models.BooleanField(default=False)
    followed_on = models.DateField(null=True, blank=True)
    no_of_votes = models.IntegerField(default='0')
    no_of_down_votes = models.IntegerField(default='0')
    is_like = models.BooleanField(default=False) class Timeline(models.Model):
    content_type = models.ForeignKey(ContentType, related_name="content_type_timelines")
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey("content_type", "object_id")
    namespace = models.CharField(max_length=250, default="default", db_index=True)
    event_type = models.CharField(max_length=250, db_index=True)
    user = models.ForeignKey(User, null=True)
    data = models.TextField(null=True, blank=True)
    created_on = models.DateTimeField(auto_now_add=True)
    is_read = models.BooleanField(default=False)

    class Meta:
        index_together = [("content_type", "object_id", "namespace"), ]
        ordering = ['-created_on'] class Facebook(models.Model):
    user = models.ForeignKey(User, related_name='user_facebook')
    facebook_id = models.CharField(max_length=100)
    facebook_url = models.CharField(max_length=200, default='')
    first_name = models.CharField(max_length=200, default='')
    last_name = models.CharField(max_length=200, default='')
    verified = models.CharField(max_length=200, default='')
    name = models.CharField(max_length=200, default='')
    language = models.CharField(max_length=200, default='')
    hometown = models.CharField(max_length=200, default='')
    email = models.CharField(max_length=200, default='', db_index=True)
    gender = models.CharField(max_length=200, default='')
    dob = models.DateField(null=True, blank=True)
    location = models.CharField(max_length=200, default='')
    timezone = models.CharField(max_length=200, default='')
    accesstoken = models.CharField(max_length=2000, default='') class Google(models.Model):
    user = models.ForeignKey(User, related_name='user_google')
    google_id = models.CharField(max_length=200, default='')
    google_url = models.CharField(max_length=1000, default='')
    verified_email = models.CharField(max_length=200, default='')
    family_name = models.CharField(max_length=200, default='')
    name = models.CharField(max_length=200, default='')
    picture = models.CharField(max_length=200, default='')
    gender = models.CharField(max_length=10, default='')
    dob = models.CharField(max_length=50, default='')
    given_name = models.CharField(max_length=200, default='')
    email = models.CharField(max_length=200, default='', db_index=True) class Comment(models.Model):
    comment = models.TextField(null=True, blank=True)
    commented_by = models.ForeignKey(User, related_name="commented_by")
    topic = models.ForeignKey(Topic, related_name="topic_comments")
    created_on = models.DateTimeField(auto_now_add=True)
    updated_on = models.DateTimeField(auto_now_add=True)
    parent = models.ForeignKey("self", blank=True, null=True, related_name="comment_parent")
    mentioned = models.ManyToManyField(User, related_name="mentioned_users")
    votes = models.ManyToManyField(Vote)

    def get_comments(self):
        comments = self.comment_parent.all()
        return comments

    def up_votes_count(self):
        return self.votes.filter(type="U").count()

    def down_votes_count(self):
        return self.votes.filter(type="D").count() class Vote(models.Model):
    TYPES = (
        ("U", "Up"),
        ("D", "Down"),
    )
    user = models.ForeignKey(User)
    type = models.CharField(choices=TYPES, max_length=1)
    created_on = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.user class AdminMixin(object):

    def dispatch(self, request, *args, **kwargs):
        user = self.request.user
        if not user.is_superuser:
            return redirect(reverse('django_simple_forum:topic_list'))
        return super(AdminMixin, self).dispatch(request, *args, **kwargs) class LoginRequiredMixin(object):

    def dispatch(self, request, *args, **kwargs):
        user = self.request.user
        if user.is_authenticated():
            if user.is_active:
                return super(LoginRequiredMixin, self).dispatch(request, *args, **kwargs)
            else:
                logout(self.request)
        return redirect(reverse('django_simple_forum:topic_list')) class CanUpdateTopicMixin(object):

    def dispatch(self, request, *args, **kwargs):
        user = self.request.user
        if user.is_anonymous():
            return redirect(reverse("django_simple_forum:topic_list"))
        pk = kwargs.get("slug")
        self.object = get_object_or_404(Topic, slug=pk)
        if request.user != self.object.created_by and not request.user.is_staff:
            return redirect(reverse("django_simple_forum:topic_list"))
        return super(CanUpdateTopicMixin, self).dispatch(request, *args, **kwargs) class CategoryForm(forms.ModelForm):
    class Meta:
        model = ForumCategory
        exclude = ('slug', 'created_by')

    def clean_title(self):
        if ForumCategory.objects.filter(slug=slugify(self.cleaned_data['title'])).exclude(id=self.instance.id):
            raise forms.ValidationError('Category with this Name already exists.')

        return self.cleaned_data['title']

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

    def save(self, commit=True):
        instance = super(CategoryForm, self).save(commit=False)
        instance.created_by = self.user
        instance.title = self.cleaned_data['title']
        if str(self.cleaned_data['is_votable']) == 'True':
            instance.is_votable = True
        else:
            instance.is_votable = False
        if str(self.cleaned_data['is_active']) == 'True':
            instance.is_active = True
        else:
            instance.is_active = False
        if not self.instance.id:
            instance.slug = slugify(self.cleaned_data['title'])

        if commit:
            instance.save()
        return instance class BadgeForm(forms.ModelForm):
    class Meta:
        model = Badge
        exclude = ('slug',)

    def clean_title(self):
        if Badge.objects.filter(slug=slugify(self.cleaned_data['title'])).exclude(id=self.instance.id):
            raise forms.ValidationError('Badge with this Name already exists.')

        return self.cleaned_data['title']

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

    def save(self, commit=True):
        instance = super(BadgeForm, self).save(commit=False)
        instance.title = self.cleaned_data['title']
        if not self.instance.id:
            instance.slug = slugify(self.cleaned_data['title'])
        if commit:
            instance.save()
        return instance class RegisterForm(forms.ModelForm):

    class Meta:
        model = User
        fields = ['email', 'first_name', 'username', 'password'] class TopicForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        self.user = kwargs.pop('user', None)
        super(TopicForm, self).__init__(*args, **kwargs)
        self.fields["category"].widget.attrs = {"class": "form-control select2"}
        self.fields["title"].widget.attrs = {"class": "form-control"}
        self.fields["tags"].widget.attrs = {"class": "form-control tags"}

    tags = forms.CharField(required=False)

    class Meta:
        model = Topic
        fields = ("title", "category", "description", "tags")
    
    def clean_title(self):
        if Topic.objects.filter(slug=slugify(self.cleaned_data['title'])).exclude(id=self.instance.id):
            raise forms.ValidationError('Topic with this Name already exists.')

        return self.cleaned_data['title']


    def save(self, commit=True):
        instance = super(TopicForm, self).save(commit=False)
        instance.title = self.cleaned_data['title']
        instance.description = self.cleaned_data['description']
        instance.category = self.cleaned_data['category']
        if not self.instance.id:
            instance.slug = slugify(self.cleaned_data['title'])
            instance.created_by = self.user
            instance.status = 'Draft'
        if commit:
            instance.save()
        return instance class CommentForm(forms.ModelForm):

    class Meta:
        model = Comment
        fields = ('comment', 'topic')

    def clean_comment(self):
        if self.cleaned_data['comment']:
            return self.cleaned_data['comment']
        raise forms.ValidationError('This field is required')

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

    def save(self, commit=True):
        instance = super(CommentForm, self).save(commit=False)
        instance.comment = self.cleaned_data['comment']
        instance.topic = self.cleaned_data['topic']
        if not self.instance.id:
            instance.commented_by = self.user
            if 'parent' in self.cleaned_data.keys() and self.cleaned_data['parent']:
                instance.parent = self.cleaned_data['parent']
        if commit:
            instance.save()
        return instance class UserProfileForm(forms.ModelForm):

    class Meta:
        model = UserProfile
        fields = ['badges'] class ChangePasswordForm(forms.Form):
    oldpassword = forms.CharField(max_length=50)
    newpassword = forms.CharField(max_length=50)
    retypepassword = forms.CharField(max_length=50) class UserChangePasswordForm(forms.Form):
    newpassword = forms.CharField(max_length=50)
    retypepassword = forms.CharField(max_length=50) class ForgotPasswordForm(forms.Form):
    email = forms.CharField(max_length=200)

    def clean_username(self):
        user = UserProfile.objects.filter(user__email=self.data.get("email"))
        if user:
            return self.data.get("email")
        else:
            raise forms.ValidationError(
                "User with this email ID doesn't exists.") def Memail(mto, mfrom, msubject, mbody, email_template_name, context):
    if settings.MAIL_SENDER == 'AMAZON':
        sending_mail(msubject, email_template_name, context, mfrom, mto)
    elif settings.MAIL_SENDER == 'MAILGUN':
        requests.post(
            settings.MGUN_API_URL,
            auth=('api', settings.MGUN_API_KEY),
            data={
                'from': mfrom,
                'to': mto,
                'subject': msubject,
                'html': mbody
            })
    elif settings.MAIL_SENDER == 'SENDGRID':
        sg = sendgrid.SendGridClient(settings.SG_USER, settings.SG_PWD)
        sending_msg = sendgrid.Mail()
        sending_msg.set_subject(msubject)
        sending_msg.set_html(mbody)
        sending_msg.set_text(msubject)
        sending_msg.set_from(mfrom)
        sending_msg.add_to(mto)
        reposne = sg.send(sending_msg)
        print (reposne)
    else:
        text_content = msubject
        msg = EmailMultiAlternatives(msubject, mbody, mfrom, mto)
        msg.attach_alternative(mbody, "text/html")
        msg.send()
import urllib
import requests
    from urllib.parse import urlparse
    from urlparse import urlparse
from datetime import datetime
from django.contrib.auth import logout, login, load_backend
from django.core.urlresolvers import reverse, reverse_lazy
from django.core.files import File
from django.conf import settings
from django.contrib.auth.hashers import check_password
from django.db.models import Q
from django.http import JsonResponse
from django.http.response import HttpResponseRedirect, HttpResponse
from django.views.generic import TemplateView, UpdateView, ListView, CreateView, DetailView,\
    DeleteView, View
from django.views.generic.edit import FormView
from django.views.generic.detail import SingleObjectMixin
from django.shortcuts import redirect, render, get_object_or_404
from django.template import Context,loader
from django.template.defaultfilters import slugify
from django.utils.crypto import get_random_string
    from django.contrib.auth import get_user_model
    from django.contrib.auth.models import User
from microurl import google_mini
from .forms import LoginForm
from .models import ForumCategory, STATUS, Badge, Topic, Tags, UserProfile, UserTopics, Timeline,\
    Facebook, Google, Comment, Vote
from .mixins import AdminMixin, LoginRequiredMixin, CanUpdateTopicMixin
from .forms import CategoryForm, BadgeForm, RegisterForm, TopicForm, CommentForm, UserProfileForm,\
    ChangePasswordForm, UserChangePasswordForm, ForgotPasswordForm
from .sending_mail import Memail
    def get_context_data(self, **kwargs):
        context = super(BadgeAdd, self).get_context_data(**kwargs)
        form = BadgeForm(self.request.GET)
        context['form'] = form
        return context


class BadgeDelete(AdminMixin, DeleteView):
    model = Badge
    slug_field = 'slug'
    template_name = "dashboard/badges.html"
    success_url = '/forum/dashboard/badges/'

    def get_object(self):
        return get_object_or_404(Badge, slug=self.kwargs['slug'])

    def get_success_url(self):
        return redirect(reverse('django_simple_forum:badges'))

    def post(self, request, *args, **kwargs):
        badge = self.get_object()
        badge.delete()
        return JsonResponse({'error': False, 'response': 'Successfully Deleted Badge'})


class BadgeEdit(AdminMixin, UpdateView):
    model = Badge
    template_name = "dashboard/badge_add.html"
    form_class = BadgeForm
    context_object_name = 'badge'

    def get_object(self):
        return get_object_or_404(Badge, slug=self.kwargs['slug'])

    def get_form_kwargs(self):
        kwargs = super(BadgeEdit, self).get_form_kwargs()
        kwargs.update({'user': self.request.user})
        return kwargs

    def form_valid(self, form):
        form.save()
        data = {'error': False, 'response': 'Successfully Edited Badge'}
        return JsonResponse(data)

    def get_success_url(self):
        return redirect(reverse('django_simple_forum:badges'))

    def form_invalid(self, form):
        return JsonResponse({'error': True, 'response': form.errors})

    def get_context_data(self, **kwargs):
        context = super(BadgeEdit, self).get_context_data(**kwargs)
        form = BadgeForm(self.request.GET)
        context['form'] = form
        return context


class UserList(AdminMixin, ListView):
    model = UserProfile
    template_name = 'dashboard/users.html'
    context_object_name = 'users_list'
    queryset = UserProfile.objects.filter()

    def get_context_data(self, **kwargs):
        context = super(UserList, self).get_context_data(**kwargs)
        return context

    def post(self, request, *args, **kwargs):
        users_list = self.model.objects.all()
        if request.POST.get('search_text', ''):
            users_list = list(set(users_list.filter(
                user__email__icontains=request.POST.get('search_text')
            ) | users_list.filter(
                user__username__icontains=request.POST.get('search_text')
            )))
        per_page = request.POST.get("filter_per_page") if request.POST.get(
            "filter_per_page") else 10
        return render(request, self.template_name, {'users_list': users_list,
                                                    "per_page": per_page})


class DashboardUserEdit(AdminMixin, UpdateView):
    model = UserProfile
    template_name = "dashboard/edit_user.html"
    form_class = UserProfileForm
    context_object_name = 'user_profile'

    def get_object(self):
        return get_object_or_404(UserProfile, user_id=self.kwargs['user_id'])

    # def get_form_kwargs(self):
    #     kwargs = super(DashboardUserEdit, self).get_form_kwargs()
    #     kwargs.update({'user': self.request.user})
    #     return kwargs

    def form_valid(self, form):
        user_profile = form.save()
        user_profile.badges.clear()
        user_profile.badges.add(*form.cleaned_data['badges'])
        data = {'error': False, 'response': 'Successfully Edited User'}
        return JsonResponse(data)

    def get_success_url(self):
        return redirect(reverse('django_simple_forum:users'))

    def form_invalid(self, form):
        return JsonResponse({'error': True, 'response': form.errors})

    def get_context_data(self, **kwargs):
        context = super(DashboardUserEdit, self).get_context_data(**kwargs)
        form = UserProfileForm(self.request.GET)
        badges = Badge.objects.filter()
        context['form'] = form
        context['badges'] = badges
        context['user_profile'] = self.get_object()
        return context


class IndexView(FormView):
    template_name = 'forum/topic_list.html'

    form_class = RegisterForm