# Copyright (C) 2018-2019  The Software Heritage developers
# See the AUTHORS file at the top-level directory of this distribution
# License: GNU Affero General Public License version 3, or any later version
# See top-level LICENSE file for more information

import json

from django.conf.urls import url
from django.core.paginator import Paginator
from django.http import (
    HttpResponse, HttpResponseForbidden, HttpResponseServerError
)
from django.shortcuts import render

from rest_framework.decorators import api_view, authentication_classes

from swh.web.common.exc import ForbiddenExc
from swh.web.common.models import SaveOriginRequest
from swh.web.common.origin_save import (
    create_save_origin_request, get_savable_visit_types,
    get_save_origin_requests_from_queryset
)
from swh.web.common.throttling import throttle_scope
from swh.web.common.utils import EnforceCSRFAuthentication


def _origin_save_view(request):
    return render(request, 'misc/origin-save.html',
                  {'heading': ('Request the saving of a software origin into '
                               'the archive')})


@api_view(['POST'])
@authentication_classes((EnforceCSRFAuthentication, ))
@throttle_scope('swh_save_origin')
def _origin_save_request(request, visit_type, origin_url):
    """
    This view is called through AJAX from the save code now form of swh-web.
    We use DRF here as we want to rate limit the number of submitted requests
    per user to avoid being possibly flooded by bots.
    """
    try:
        response = json.dumps(create_save_origin_request(visit_type,
                                                         origin_url),
                              separators=(',', ': '))
        return HttpResponse(response, content_type='application/json')
    except ForbiddenExc as exc:
        return HttpResponseForbidden(json.dumps({'detail': str(exc)}),
                                     content_type='application/json')
    except Exception as exc:
        return HttpResponseServerError(json.dumps({'detail': str(exc)}),
                                       content_type='application/json')


def _visit_save_types_list(request):
    visit_types = json.dumps(get_savable_visit_types(),
                             separators=(',', ': '))
    return HttpResponse(visit_types, content_type='application/json')


def _origin_save_requests_list(request, status):

    if status != 'all':
        save_requests = SaveOriginRequest.objects.filter(status=status)
    else:
        save_requests = SaveOriginRequest.objects.all()

    table_data = {}
    table_data['recordsTotal'] = save_requests.count()
    table_data['draw'] = int(request.GET['draw'])

    search_value = request.GET['search[value]']

    column_order = request.GET['order[0][column]']
    field_order = request.GET['columns[%s][name]' % column_order]
    order_dir = request.GET['order[0][dir]']
    if order_dir == 'desc':
        field_order = '-' + field_order

    save_requests = save_requests.order_by(field_order)

    length = int(request.GET['length'])
    page = int(request.GET['start']) / length + 1
    save_requests = get_save_origin_requests_from_queryset(save_requests)
    if search_value:
        save_requests = \
            [sr for sr in save_requests
             if search_value.lower() in sr['save_request_status'].lower()
             or search_value.lower() in sr['save_task_status'].lower()
             or search_value.lower() in sr['visit_type'].lower()
             or search_value.lower() in sr['origin_url'].lower()]

    table_data['recordsFiltered'] = len(save_requests)
    paginator = Paginator(save_requests, length)
    table_data['data'] = paginator.page(page).object_list
    table_data_json = json.dumps(table_data, separators=(',', ': '))
    return HttpResponse(table_data_json, content_type='application/json')


urlpatterns = [
    url(r'^save/$', _origin_save_view, name='origin-save'),
    url(r'^save/(?P<visit_type>.+)/url/(?P<origin_url>.+)/$',
        _origin_save_request, name='origin-save-request'),
    url(r'^save/types/list/$', _visit_save_types_list,
        name='origin-save-types-list'),
    url(r'^save/requests/list/(?P<status>.+)/$', _origin_save_requests_list,
        name='origin-save-requests-list'),
]
