from django.shortcuts import render, get_object_or_404
from django.db.models import Q
from django.conf import settings
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.contrib import messages
from django.core.mail import EmailMessage
from django.contrib.auth import authenticate, login
from django.contrib.auth.models import User

from datetime import date

# Models
from models import UserProfile
from modules.members.models import Member
from modules.pages.models import Page, PageSection
from modules.blocks.models import HomepageSettings, HomepageSearch
from modules.mediacentre.models import MediaSection, MediaArticle
from modules.resources.models import Resource

from functions import random_string_unique

from forms import LoginForm, ForgotPasswordForm, ChangePasswordForm


def home(request):

    try:
        homepage_settings = HomepageSettings.objects.get(id=1)
        block_layout = homepage_settings.block_layout
    except HomepageSettings.DoesNotExist:
        homepage_settings = False
        block_layout = False

    today = date.today()

    try:
        news_cat = MediaSection.objects.get(slug='news')
        news_articles = MediaArticle.objects.filter(Q(archive_date__gt=today) | Q(archive_date__isnull=True), section=news_cat, published=True).order_by('-sticky', news_cat.order)[:4]
    except MediaSection.DoesNotExist:
        news_cat = False
        news_articles = False

    try:
        events_cat = MediaSection.objects.get(slug='events')
        event_articles = MediaArticle.objects.filter(section=events_cat, published=True, event_date_end__gt=today).order_by('-sticky', events_cat.order)[:4]
    except MediaSection.DoesNotExist:
        events_cat = False
        event_articles = False

    return render(request, 'public/home.html', {
        'homepage_settings': homepage_settings, 'block_layout': block_layout, 'news_cat': news_cat, 'news_articles': news_articles, 'events_cat': events_cat, 'event_articles': event_articles
    })


def search(request):

    today = date.today()

    if request.POST:

        if request.POST.get('query'):

            search_results = False

            query = request.POST.get('query')

            pages = Page.objects.filter(Q(title__icontains=query) | Q(content__icontains=query) | Q(keywords__icontains=query))
            page_sections = PageSection.objects.filter(Q(title__icontains=query) | Q(content__icontains=query))

            final_pages = []
            for page in pages:
                if page.get_permission(request) == 'allowed':
                    final_pages.append(page)

            for section in page_sections:
                if section.page.get_permission(request) == 'allowed' and section.page not in final_pages:
                    final_pages.append(section.page)

            final_resources = []
            resources = Resource.objects.filter(Q(name__contains=query) | Q(description__contains=query)).order_by('name')
            for resource in resources:
                if resource.get_permission(request) == 'allowed':
                    final_resources.append(resource)

            # articles
            news_cat = MediaSection.objects.get(slug='news')
            final_news = []
            news = MediaArticle.objects.filter(
                Q(title__icontains=query) | Q(content__icontains=query) | Q(keywords__icontains=query),
                Q(archive_date__isnull=True) | Q(archive_date__gte=today),
                section=news_cat
            ).order_by('section__name', 'title')

            for news in news:
                if news.get_permission(request) == 'allowed':
                    final_news.append(news)

            events_cat = MediaSection.objects.get(slug='events')
            final_events = []
            events = MediaArticle.objects.filter(
                Q(title__icontains=query) | Q(content__icontains=query) | Q(keywords__icontains=query),
                published=True, event_date_start__gte=today, section=events_cat
            ).order_by('section__name', 'title')
            for event in events:
                if event.get_permission(request) == 'allowed':
                    final_events.append(event)

            return render(request, 'public/search/search-results.html', {
                'pages': final_pages, 'resources': final_resources, 'search_term': query, 'news': final_news, 'events': final_events, 'search_results': search_results
            })

    return render(request, 'public/search/search.html', {})


def audience_search(request):

    audience_search = HomepageSearch.objects.filter(type='audience')
    content_type_search = HomepageSearch.objects.filter(type='content-type')

    today = date.today()

    if request.POST:

        if request.POST['content_type'] != '':
            content_type = get_object_or_404(HomepageSearch, slug=request.POST['content_type'])
        else:
            content_type = False
        if request.POST['audience'] != '':
            audience = get_object_or_404(HomepageSearch, slug=request.POST['audience'])
        else:
            audience = False

        pages = Page.objects.all().order_by('title')
        matching_pages = pages

        matching_content_type_pages = []
        matching_audience_pages = []

        if content_type:
            matching_pages = matching_pages.filter(search_terms=content_type)
            matching_content_type_pages = pages.filter(search_terms=content_type)
        if audience:
            matching_pages = matching_pages.filter(search_terms=audience)
            matching_audience_pages = pages.filter(search_terms=audience)

        final_pages = []
        for page in matching_pages:
            if page.get_permission(request) == 'allowed':
                final_pages.append(page)

        final_audience_pages = []
        for page in matching_audience_pages:
            if page.get_permission(request) == 'allowed' and page not in final_pages:
                final_audience_pages.append(page)

        final_content_type_pages = []
        for page in matching_content_type_pages:
            if page.get_permission(request) == 'allowed' and page not in final_pages:
                final_content_type_pages.append(page)

        news_cat = MediaSection.objects.get(slug='news')
        news = MediaArticle.objects.filter(Q(archive_date__isnull=True) | Q(archive_date__gte=today), published=True, section=news_cat).order_by('section__name', 'title')

        matching_news = news
        matching_content_type_news = []
        matching_audience_news = []

        if content_type:
            matching_news = news.filter(search_terms=content_type)
            matching_content_type_news = news.filter(search_terms=content_type)
        if audience:
            matching_news = matching_news.filter(search_terms=audience)
            matching_audience_news = news.filter(search_terms=audience)

        final_news = []
        for news in matching_news:
            if news.get_permission(request) == 'allowed':
                final_news.append(news)

        final_audience_news = []
        for news in matching_audience_news:
            if news.get_permission(request) == 'allowed' and news not in final_news:
                final_audience_news.append(news)

        final_content_type_news = []
        for news in matching_content_type_news:
            if news.get_permission(request) == 'allowed' and news not in final_news:
                final_content_type_news.append(news)

        events_cat = MediaSection.objects.get(slug='events')
        events = MediaArticle.objects.filter(published=True, event_date_start__gte=today, section=events_cat).order_by('section__name', 'title')

        matching_events = events
        matching_content_type_events = []
        matching_audience_events = []

        if content_type:
            matching_events = events.filter(search_terms=content_type)
            matching_content_type_events = events.filter(search_terms=content_type)
        if audience:
            matching_events = matching_events.filter(search_terms=audience)
            matching_audience_events = events.filter(search_terms=audience)

        final_events = []
        for event in matching_events:
            if event.get_permission(request) == 'allowed':
                final_events.append(event)

        final_audience_events = []
        for event in matching_audience_events:
            if event.get_permission(request) == 'allowed' and event not in final_events:
                final_audience_events.append(event)

        final_content_type_events = []
        for event in matching_content_type_events:
            if event.get_permission(request) == 'allowed' and event not in final_events:
                final_content_type_events.append(event)

        return render(request, 'public/search/audience-search-results.html', {
            'content_type': content_type, 'audience': audience, 'audience_search': audience_search, 'content_type_search': content_type_search, 'pages': final_pages,
            'content_type_pages': final_content_type_pages, 'audience_pages': final_audience_pages, 'news': final_news, 'content_type_news': final_content_type_news,
            'audience_news': final_audience_news, 'events': final_events, 'content_type_events': final_content_type_events, 'audience_events': final_audience_events
        })

    return render(request, 'public/search/audience-search.html', {'audience_search': audience_search, 'content_type_search': content_type_search})


def sitemap(request):

    top_level_pages = Page.objects.filter(parent__isnull=True)
    mediacentre_categories = MediaSection.objects.all().order_by('name')

    return render(request, 'public/sitemap.html', {'top_level_pages': top_level_pages, 'mediacentre_categories': mediacentre_categories})


def sitemap_xml(request):

    pages = Page.objects.all().order_by('order')
    mediacentre_categories = MediaSection.objects.all().order_by('name')

    return render(request, 'public/sitemap.xml', {'pages': pages, 'mediacentre_categories': mediacentre_categories}, content_type="application/xhtml+xml")


def login_view(request):

    login_form = LoginForm()

    if request.POST:
        login_form = LoginForm(request.POST)

        if login_form.is_valid():

            email_address = login_form.cleaned_data['email_address']
            password = login_form.cleaned_data['password']

            try:
                user = User.objects.get(email=email_address)
                user = authenticate(username=user.username, password=password)
                # raise Exception(user.username)
                if user is not None:
                    if user.is_active:
                        try:
                            member = Member.objects.get(user=user)

                            if member.user_type == 'delegate':
                                login(request, user)
                                if request.GET.get('next'):
                                    return HttpResponseRedirect(request.GET['next'])
                                else:
                                    return HttpResponseRedirect(reverse('account_home'))
                            else:
                                if member.approved and (member.member_status == 'current' or member.member_status == 'lapsed'):
                                    login(request, user)

                                    if member.first_login:
                                        member.first_login = False
                                        member.save()

                                        return HttpResponseRedirect('/your-membership/')

                                    if request.GET.get('next'):
                                        return HttpResponseRedirect(request.GET['next'])
                                    else:
                                        return HttpResponseRedirect(reverse('account_home'))
                                else:
                                    if member.member_status == 'archived':
                                        messages.error(request, 'Sorry, this member has been archived from our systems.')
                                    elif member.member_status == 'lapsed':
                                        messages.error(request, 'Sorry your membership has been lapsed, please contact us for further information.')
                                    else:
                                        messages.error(request, 'Sorry, this member has not been approved yet. Please await confirmation from the council before trying to login.')
                        except Member.DoesNotExist:
                            if user.is_staff:
                                login(request, user)
                                return HttpResponseRedirect(reverse('admin'))
                    else:
                        messages.error(request, "Your account is disabled.")
                else:
                    messages.error(request, "Your username or password is incorrect")
            except Exception:
                messages.error(request, "Sorry, your username or password is incorrect - please try again.")

    return render(request, 'public/login/login.html', {'form': login_form})


def member_required(request):

    return render(request, 'public/login/member-required.html', {})


def member_expired(request):

    return render(request, 'public/login/member-expired.html', {})


def member_disabled(request):

    return render(request, 'public/login/member-disabled.html', {})


def member_notapproved(request):

    return render(request, 'public/login/member-not-approved.html', {})


def forgot_password(request):

    form = ForgotPasswordForm()

    if request.POST:
        form = ForgotPasswordForm(request.POST)

        try:
            user = User.objects.get(email=request.POST['email'], is_active=True)
        except User.DoesNotExist:
            user = False
            messages.error(request, 'Sorry a user with that email address could not be found.')

        if user:

            forgot_key = random_string_unique(20, UserProfile, 'forgot_key')
            user_profile = user.userprofile
            user_profile.forgot_key = forgot_key
            user_profile.save()

            message = """
<p>A password reset form has been filled in for your account</p>

<p>Please click the following link to reset your password: -

<p><a href="http://%s/forgot-password/%s/">Reset your password</a></p>

<p>This is an automatic email generated by the %s website.</p>""" % (request.META['HTTP_HOST'], forgot_key, settings.WEBSITE_NAME)

            msg = EmailMessage('%s - Forgot Password' % (settings.WEBSITE_NAME), message, settings.CONTACT_EMAIL, [user.email])
            msg.content_subtype = "html"
            msg.send()

            return render(request, 'public/forgot/forgot-confirm.html', {'email_reset': user.email})

    return render(request, 'public/forgot/forgot-password.html', {'form': form})


def forgot_password_confirm(request, forgot_key):

    try:
        user_profile = UserProfile.objects.get(forgot_key=forgot_key)
        user = user_profile.user
    except UserProfile.DoesNotExist:
        return render(request, 'public/forgot/forgot-not-found.html', {})

    form = ChangePasswordForm()

    error = False

    if request.POST:
        form = ChangePasswordForm(request.POST)

        if form.is_valid():

            user.set_password(form.cleaned_data['password1'])
            user.save()

            user_profile.forgot_key = ''
            user_profile.save()

            message = """
<p>Your password for the %s website has been reset.</p>

<p>You can log on at: -</p>

<p><a href="http://%s/login/">http://%s/login/</a></p>

<p>This is an automatic email generated by the %s.</p>""" % (settings.WEBSITE_NAME, request.META['HTTP_HOST'], request.META['HTTP_HOST'], settings.WEBSITE_NAME)

            msg = EmailMessage('%s - Forgot Password' % (settings.WEBSITE_NAME), message, settings.CONTACT_EMAIL, [user.email])
            msg.content_subtype = "html"

            msg.send()

            return render(request, 'public/forgot/forgot-reset.html', {})

    return render(request, 'public/forgot/forgot-reset-form.html', {'user': user, 'form': form, 'error': error})
