from django.views.generic import UpdateView, DetailView, ListView, CreateView, DeleteView, RedirectView
from django.views.generic.base import TemplateView
from django.urls import reverse, reverse_lazy
from django.db.models import Q

from .models import (
    GTDNote,
    GTDProject,
    GTDOutcome,
    WiredNote,
    WiredPost,
    NoteType
)

from .forms import (
    GTDNoteCreateForm,
    GTDNoteEditForm,
    GTDProjectCreateForm,
    GTDProjectUpdateForm,
    WiredNoteEditForm,
    WiredPostUpdateForm
)


class GTDNoteCreateView(CreateView):
    model = GTDNote
    form_class = GTDNoteCreateForm
    template_name = "gtd/note_form.html"

    def get_success_url(self):
        if 'add_new' in self.request.POST:
            return reverse('gtd:note-create')
        else:
            if self.object.project:
                return reverse('gtd:project-detail', kwargs={"pk": self.object.project.pk})
            else:
                return reverse('gtd:note-create')


class GTDNoteUpdateView(UpdateView):
    model = GTDNote
    form_class = GTDNoteEditForm
    template_name = "gtd/note_form.html"

    def get_context_data(self, **kwargs):
        context = super(GTDNoteUpdateView, self).get_context_data(**kwargs)
        context['is_update'] = True
        return context

    def get_success_url(self):
        if self.object.project:
            return reverse('gtd:project-detail', kwargs={"pk": self.object.project.pk})
        else:
            return reverse('gtd:note-list', kwargs={"pk": self.object.project.pk})


class GTDNoteListView(ListView):
    model = GTDNote
    template_name = "gtd/note_list.html"

    def get_queryset(self):
        project = self.request.GET.get("project", False)
        if self.kwargs['note_type']:
            note_type = NoteType.string_to_int(self.kwargs['note_type'].title())
            if project:
                return GTDNote.objects.filter(note_type=note_type, project__title=project, status__in=[0,1])
            return GTDNote.objects.filter(note_type=note_type, status__in=[0,1])
        else:
            if project:
                return GTDNote.objects.filter(project__title=project, status__in=[0,1])
        return GTDNote.objects.filter(status__in=[0,1])

    def get_context_data(self, **kwargs):
        context = super(GTDNoteListView, self).get_context_data(**kwargs)
        context['note_types'] = NoteType
        context['projects'] = GTDProject.objects.all()
        context['project'] = self.request.GET.get("project", False)
        return context


class GTDNoteTODOView(ListView):
    model = GTDNote
    template_name = "gtd/note_list.html"

    def get_queryset(self):
        project = self.request.GET.get("project", False)
        # need to get wired notes and gtd notes and blend them by
        # date created maybe?
        if project:
            return GTDNote.objects.filter(status__in=[0, 1], note_type__in=[NoteType.REMINDER, NoteType.ACTION],project__title=project)
        return GTDNote.objects.filter(status__in=[0, 1], note_type__in=[NoteType.REMINDER, NoteType.ACTION])

    def get_context_data(self, **kwargs):
        context = super(GTDNoteTODOView, self).get_context_data(**kwargs)
        context['projects'] = GTDProject.objects.all()
        context['project'] = self.request.GET.get("project", False)
        return context


class GTDProjectCreateView(CreateView):
    model = GTDProject
    form_class = GTDProjectCreateForm
    template_name = "gtd/project_form.html"

    def get_success_url(self):
        if 'add_new' in self.request.POST:
            return reverse('gtd:project-create')
        else:
            return reverse('gtd:project-detail', kwargs={"pk": self.object.pk})


class GTDProjectUpdateView(UpdateView):
    model = GTDProject
    form_class = GTDProjectUpdateForm
    template_name = "gtd/project_form.html"

    def get_context_data(self, **kwargs):
        context = super(GTDProjectUpdateView, self).get_context_data(**kwargs)
        context['is_update'] = True
        return context


class GTDProjectDetailView(DetailView):
    model = GTDProject
    template_name = "gtd/project_detail.html"

    def get_context_data(self, **kwargs):
        context = super(GTDProjectDetailView, self).get_context_data(**kwargs)
        context['note_set'] = GTDNote.objects.filter(project=self.object).order_by('note_type')
        context['projects'] = GTDProject.objects.all()
        return context


class GTDProjectListView(ListView):
    model = GTDProject
    template_name = "gtd/project_list.html"

    def get_queryset(self, *args, **kwargs):
        if self.kwargs['project_type']:
            project_type_reverse = dict((v, k) for k, v in GTDProject.PROJECT_TYPE)
            project_type = project_type_reverse[self.kwargs['project_type']]
            return GTDProject.objects.filter(project_type=project_type)
        return GTDProject.objects.all()

    def get_context_data(self, **kwargs):
        context = super(GTDProjectListView, self).get_context_data(**kwargs)
        context['project_types'] = GTDProject.PROJECT_TYPE
        return context


class GTDProjectDeleteView(DeleteView):
    # specify the model you want to use
    model = GTDProject
    success_url = "/gtd/projects"
    template_name = "gtd/confirm_delete.html"


class WiredNoteCreateView(CreateView):
    model = WiredNote
    fields = ['title', 'url', 'body_markdown', 'post']
    template_name = "gtd/wirednote_form.html"

    def get_success_url(self):
        if 'add_new' in self.request.POST:
            return reverse('gtd:wirednotes-create')
        else:
            if self.object.post:
                return reverse('gtd:wiredpost-detail', kwargs={"pk": self.object.post.pk})
            else:
                return reverse('gtd:wirednotes-list')


class WiredNoteUpdateView(UpdateView):
    model = WiredNote
    form_class = WiredNoteEditForm
    template_name = "gtd/wirednote_form.html"

    def get_context_data(self, **kwargs):
        context = super(WiredNoteUpdateView, self).get_context_data(**kwargs)
        context['is_update'] = True
        return context

    def get_success_url(self):
        if self.object.post:
            return reverse('gtd:wiredpost-detail', kwargs={"pk": self.object.post.pk})
        else:
            return reverse('gtd:wirednote-list', kwargs={"pk": self.object.project.pk})


class WiredNoteListView(ListView):
    model = WiredNote
    template_name = "gtd/wirednote_list.html"

    def get_queryset(self):
        wiredpost = self.request.GET.get("post", False)
        if self.kwargs['status']:
            status_reverse = dict((v, k) for k, v in WiredNote.STATUS)
            status = status_reverse[self.kwargs['status'].title()]
            if wiredpost:
                return WiredNote.objects.filter(status=status, post__title=wiredpost)
            return WiredNote.objects.filter(status=status)
        else:
            if wiredpost:
                return WiredNote.objects.filter(post__title=wiredpost)
        return WiredNote.objects.all()

    def get_context_data(self, **kwargs):
        context = super(WiredNoteListView, self).get_context_data(**kwargs)
        context['note_statuses'] = WiredNote.STATUS
        context['posts'] = WiredPost.objects.all()
        context['post'] = self.request.GET.get("post", False)
        return context


class WiredNoteDeleteView(DeleteView):
    model = WiredNote
    success_url = "/gtd/wirednote"
    template_name = "gtd/confirm_delete.html"


class WiredPostListView(ListView):
    model = WiredPost
    template_name = 'gtd/wiredpost_table.html'

    def get_queryset(self):
        return WiredPost.objects.all().order_by("-needs_update")


class WiredPostUpdateOverdueView(RedirectView):
    permanent = False
    url = "/gtd/wiredposts"
    query_string = True

    def get_redirect_url(self, *args, **kwargs):
        for post in WiredPost.objects.all():
            post.set_needs_update()
        return super().get_redirect_url(*args, **kwargs)


class WiredPostNewView(ListView):
    template_name = 'gtd/wiredpost_list.html'

    def get_queryset(self):
        return WiredPost.objects.filter(is_live=0)

    def get_context_data(self, **kwargs):
        context = super(WiredPostNewView, self).get_context_data(**kwargs)
        context['reviews'] = WiredNote.objects.filter(plan__in=[1, 2], status__in=[0, 1, 2, 3])
        return context


class WiredPostCreateView(CreateView):
    model = WiredPost
    fields = ['title', 'post_status', 'url', 'template_type', 'update_frequency', 'edit_url', 'date_last_pub']
    template_name = "gtd/wiredpost_form.html"


class WiredPostTodoView(ListView):
    template_name = 'gtd/wiredpost_table.html'

    def get_queryset(self):
        qs = WiredPost.objects.filter(Q(needs_update=True) | Q(is_live=0)).exclude(post_status=1)
        unsorted_results = qs.all()
        return sorted(unsorted_results, key=lambda a: a.days_overdue(), reverse=True)

    def get_context_data(self, **kwargs):
        context = super(WiredPostTodoView, self).get_context_data(**kwargs)
        context['reviews'] = WiredNote.objects.filter(plan__in=[1, 2, 3]).exclude(status__in=[4, 5])
        return context


class WiredPostNotesView(DetailView):
    model = WiredPost
    template_name = "gtd/wiredpost_detail.html"

    def get_context_data(self, **kwargs):
        context = super(WiredPostNotesView, self).get_context_data(**kwargs)
        context['notes'] = self.get_object().wirednote_set.all().order_by("status")
        context['posts'] = WiredPost.objects.all()
        return context


class WiredPostUpdateView(UpdateView):
    model = WiredPost
    form_class = WiredPostUpdateForm
    template_name = "gtd/wiredpost_form.html"

    def get_success_url(self):
        if 'add_new' in self.request.POST:
            return reverse('gtd:posts-create')
        else:
            return reverse('gtd:wiredpost-list')


class WiredGenerateDealCodeView(TemplateView):
    template_name = "gtd/deal_code.html"


class GTDNoteDeleteView(DeleteView):
    # specify the model you want to use
    model = GTDNote
    success_url = "/gtd/notes"
    template_name = "gtd/confirm_delete.html"


class GTDOutcomeCreateView(CreateView):
    model = GTDOutcome
    template_name = "gtd/outcome_form.html"
    fields = ['title', 'body_markdown', 'date_goal', 'date_ended']
    success_url = reverse_lazy("gtd:outcome-list")


class GTDOutcomeUpdateView(UpdateView):
    model = GTDOutcome
    template_name = "gtd/outcome_form.html"
    fields = ['title', 'body_markdown', 'date_goal', 'date_ended']
    success_url = reverse_lazy("gtd:outcome-list")

    def get_context_data(self, **kwargs):
        context = super(GTDOutcomeUpdateView, self).get_context_data(**kwargs)
        context['is_update'] = True
        return context


class GTDOutcomeListView(ListView):
    model = GTDOutcome
    template_name = "gtd/outcome_list.html"


class GTDOutcomeDeleteView(DeleteView):
    # specify the model you want to use
    model = GTDOutcome
    success_url = "/gtd/outcomes"
    template_name = "gtd/confirm_delete.html"