from django.shortcuts import render
from django.http import HttpResponse,HttpResponseBadRequest
from django.views.decorators.csrf import ensure_csrf_cookie
from django.views.decorators.http import require_http_methods
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.decorators import permission_required

from infoscreen.models import Rotation, InfoItem, InfoInstance
from infoscreen.models import ABBInfoItem, ExternalImageInfoItem, ImageInfoItem, SossoInfoItem, HslInfoItem
from infoscreen.models import CoffeeInfoItem
from infoscreen.models import ImageUploadForm
from infoscreen.models import HSLDataModel
from infoscreen.hsl_fetcher import HSLFetcher
import sikweb.settings as settings
import json
import logging
import threading


def index(request, idx, *args, **kwargs):
    return render(request, 'infoscreen_index.html', {'rotation': idx})


@permission_required('infoscreen.change_infoinstance', login_url='/login')
def admin(request, *args, **kwargs):
    return render(request, 'infoscreen_admin.html', {})


def default(request,*args,**kwargs):
    try:
        first = Rotation.objects.all()[0].id
    except:
        first = 0
    return index(request,first ,*args, **kwargs)


@require_http_methods(["GET"])
def rotation(request, idx, *args, **kwargs):
    try:
        rotation = Rotation.objects.get(pk=idx)
    except Rotation.DoesNotExist:
        resp = HttpResponse('{"error": "Rotation not found"}')
        resp.status_code = 404
        return resp

    return HttpResponse(json.dumps(rotation.get_dict()))


def create_item_generator(model):
    @ensure_csrf_cookie
    @require_http_methods(["POST"])
    @permission_required('infoscreen.change_infoinstance', login_url='/login')
    def create_item(request, *args, **kwargs):
        try:
            data = json.loads(request.body.decode("utf-8"))
        except ValueError:
            return HttpResponseBadRequest('{"status":"failure","error":"invalid json supplied"}')
        try:
            model.create_from_dict(data)
            return HttpResponse('{"status":"success"}')
        except RuntimeError as e:
            return HttpResponseBadRequest('{"status":"failure","error":"{}"}'.format(str(e)))
    return create_item


def delete_item_generator(model):
    @ensure_csrf_cookie
    @require_http_methods(["DELETE"])
    @permission_required('infoscreen.change_infoinstance', login_url='/login')
    def delete_item(request, *args, **kwargs):
        idx = kwargs.pop("idx", 0)
        try:
            item = model.objects.get(pk=idx)
        except model.DoesNotExist:
            resp = HttpResponse('{"error":"object not found"}')
            resp.status_code = 404
            return resp
        try:
            item.delete()
            return HttpResponse('{"status":"success"}')
        except:
            resp = HttpResponse('{"error" : "could not delete item"}')
            resp.status_code = 500
            return resp
    return delete_item


# due to model structure this is little complicated
@ensure_csrf_cookie
@permission_required('infoscreen.change_infoinstance', login_url='/login')
@require_http_methods(["DELETE"])
def delete_info_item(request, *args, **kwargs):
    type_id = kwargs.pop("type_id", 0)
    idx = kwargs.pop("idx", 0)
    if True:
        ct = ContentType.objects.get_for_id(type_id)
        item = ct.get_object_for_this_type(pk=idx)
    else:
        resp = HttpResponse('{"error":"object not found"}')
        resp.status_code = 404
        return resp
    try:
        item.delete()
        return HttpResponse('{"status":"success"}')
    except:
        resp = HttpResponse('{"error" : "could not delete item"}')
        resp.status_code = 500
        return resp


@require_http_methods(["GET"])
def rotations(request, *args, **kwargs):
    rotations = list(map(lambda r: r.get_list(), Rotation.objects.all()))
    return HttpResponse(json.dumps(rotations))


@require_http_methods(["GET"])
def info_types(request, *args, **kwargs):
    types = []
    classes = InfoItem.get_subclasses()
    for c in classes:
        types.append({
            "name": c.__name__,
            "create_template_url": c.get_create_template_url(),
        })
    return HttpResponse(json.dumps(types))


def info_items(request, *args, **kwargs):
    items = []
    classes = InfoItem.get_subclasses()
    for c in classes:
        for i in c.objects.all():
            items.append(i.get_dict())
    return HttpResponse(json.dumps(items))


@require_http_methods(["POST"])
@ensure_csrf_cookie
@permission_required('infoscreen.change_infoinstance', login_url='/login')
def create_image_item(request, *args, **kwargs):
    form = ImageUploadForm(request.POST,request.FILES)
    if not form.is_valid():
        return HttpResponseBadRequest('{"status": "failure",'
                                      '"error": "invalid data supplied"}')

    img = form.cleaned_data['image']
    name = form.cleaned_data['name']
    ImageInfoItem.objects.create(img=img, name=name)
    return HttpResponse('{"status":"success"}')


@require_http_methods(["POST"])
@ensure_csrf_cookie
@permission_required('infoscreen.add_rotation', login_url='/login')
def create_rotation(request, *args, **kwargs):
    try:
        data = json.loads(request.body.decode("utf-8"))
    except:
        return HttpResponse('{"error": "bad post body!"}', status=400)

    try:
        name = data["name"]
        Rotation.objects.create(name=name)
        resp = HttpResponse(status=200)
    except:
        resp = HttpResponse('{"error" : "could not create rotation!"}', status=400)

    return resp


@require_http_methods(["DELETE"])
@ensure_csrf_cookie
@permission_required('infoscreen.delete_rotation', login_url='/login')
def delete_rotation(request, *args, **kwargs):

    id = kwargs.pop("id", 0)
    logging.warning("Deleting rotation with id={}".format(id))

    try:
        Rotation.objects.filter(id=id).delete()
        resp = HttpResponse(status=200)
    except:
        resp = HttpResponse('{"error" : "could not delete rotation!"}', status=400)

    return resp

@require_http_methods(["GET"])
def hsl_timetable_settings(request, *args, **kwargs):
    d = {"departure_threshold": settings.HSL_DEPARTURE_THRESHOLD,
         "hurry_threshold": settings.HSL_HURRY_THRESHOLD}
    resp = json.dumps(d)
    return HttpResponse(resp, status=200)

@require_http_methods(["GET"])
def CurrentHSLView(request, *args, **kwargs):

    fetcher = HSLFetcher()
    fetcherThread = threading.Thread(target=fetcher.fetch_if_needed, args=[])
    fetcherThread.setDaemon(False)
    fetcherThread.start()

    data = HSLDataModel.objects.all()
    if len(data) < 1:
        return HttpResponse('{"error" : "Could not find timetables from database."}', status=500)

    return HttpResponse(data[len(data) - 1].data, status=200)

createInstance = create_item_generator(InfoInstance)
deleteInstance = delete_item_generator(InfoInstance)
createABBItem = create_item_generator(ABBInfoItem)
createSossoItem = create_item_generator(SossoInfoItem)
createHslItem = create_item_generator(HslInfoItem)
createExternalImageInfoItem = create_item_generator(ExternalImageInfoItem)
createCoffeeItem = create_item_generator(CoffeeInfoItem)
