from collections import namedtuple, OrderedDict

import logging

from django.shortcuts import render, get_object_or_404
from django.contrib import messages
from django.http import HttpResponseBadRequest, Http404, HttpResponse

from django_q.tasks import async, result, Task
from django_q.models import OrmQ
from django_q.humanhash import humanize
from django.views.decorators.http import require_GET
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger

logger = logging.getLogger(__name__)


@require_GET
def view_task(request, id):
    task = get_object_or_404(Task, id=id)
    result = task.result
    if task.func == 'nimbus.tasks.order_fruit':
        return render(request, 'nimbus/task_detail.html', {
           'result': result,
        })
    if task.func == 'nimbus.tasks.crawler_job':
        return render(request, 'nimbus/task_c_detail.html', {
            'result': result,
        })
    if task.func == 'nimbus.tasks.crawler_matrix_job':
        if type(result) is type(OrderedDict()): 
            return render(request, 'nimbus/task_matrix_detail.html', {
                'ret': result['ret'],
                'status': result['status'],
                'version': result['version'],
                'result': result['crawler_matrix_job'],
            })
        else:
            return render(request, 'nimbus/task_matrix_detail.html', {
                'result': result,
            })
    return Http404(
        'Given task of type %s does not have the result template '
        'to be rendered yet.'
        % task.func
    )


def matrix(request):
    queue_matrix = OrmQ.objects.all().order_by('lock')
    complete_matrix = Task.objects.all().filter(
        func__exact='nimbus.tasks.crawler_matrix_job',
    )
    paginator = Paginator(complete_matrix, 6) # Show 6 contacts per page
    page = request.GET.get('page')
    try:
        complete_matrix = paginator.page(page)
    except PageNotAnInteger:
        # If page is not an integer, deliver first page.
        complete_matrix = paginator.page(1)
    except EmptyPage:
        # If page is out of range (e.g. 9999), deliver last page of results.
        complete_matrix = paginator.page(paginator.num_pages)

    return render(request, 'nimbus/task_matrix_list.html', {
            'queue_matrix': queue_matrix,
            'complete_matrix': complete_matrix
    })


def crawler(request):
    # Select crawler in queue
    queue_crawler = OrmQ.objects.all().order_by('lock')

    # Select finidhed crawler
    complete_crawler = Task.objects.all().filter(
        func__exact='nimbus.tasks.crawler_job',
    )
    return render(request, 'nimbus/task_crawler.html', {
            'queue_crawler': queue_crawler,
            'complete_crawler': complete_crawler
    })


def order(request):
    if request.method == 'POST':
        # Parse the form params
        try:
            fruit = request.POST.get('fruit_type', '')
            num_fruit = int(request.POST.get('num_fruit', '1'))
        except ValueError:
            return HttpResponseBadRequest('Invalid fruit request!')
        # Create async task
        task_id = async(
            'nimbus.tasks.order_fruit',
            fruit=fruit, num_fruit=num_fruit
        )
        messages.info(
            request,
            'You ordered {fruit:s} x {num_fruit:d} (task: {task})'
            .format(fruit=fruit, num_fruit=num_fruit, task=humanize(task_id))
        )

    # Select orders in queue
    queue_orders = OrmQ.objects.all().order_by('lock')

    # Select finished orders
    complete_orders = Task.objects.all().filter(
        func__exact='nimbus.tasks.order_fruit',
    )
    return render(request, 'nimbus/task_list.html', {
            'queue_orders': queue_orders,
            'complete_orders': complete_orders
    })



