from __future__ import absolute_import

# django
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt

# rest framework
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser
from rest_framework import serializers
from rest_framework.decorators import api_view
from rest_framework.response import Response

from django.shortcuts import get_object_or_404

# mongo
#import pymongo
#from pymongo import MongoClient

import json
from bson import json_util
from bson.objectid import ObjectId
from bson.errors import InvalidId

import datetime
import sys
import os
import pprint
import re
import os.path
import shutil

from courses.models import Course
from courses.models import Section
from courses.models import Slide
from courses.models import UserCourse
from courses.models import UserSolution

from runner.tasks import compile_and_run
import json

import random

def local_execute(dic):
  id = random.randint(1,10000000)
  file = "/data/run/jobs/%s/job.json" % (id)
  while os.path.isfile(file):
    id = random.randint(1,10000000)
    file = "/data/run/jobs/%s/job.json" % (id)

  ret = compile_and_run(id, dic)
  print(ret, file=sys.stderr)
  return {"details": "OK", "id" : id, "data": ret}

def local_execute_result(id):
  #return {"status" : 201, "result": {"output" : False, "grade" : "PASS"}}
  if not id.isdigit():
    return {"status" : 0, "result": {"output" : False}}

  dir = "/data/run/jobs/%s/" % (id)
  print("Retrieving: " + dir)
  if os.path.isfile(dir + "job.json"):
    with open(dir + "job.json") as json_data:
        d = json.load(json_data)
    # cleanup of outdated directories
    shutil.rmtree(dir) # remove files directories

    return {"status" : 'SUCCESS', "result": d["response"]}
  else:
    return {"status" : 0, "result": {"output" : False}}

# helpers
class JSONResponse(HttpResponse):
    """
    An HttpResponse that renders its content into JSON.
    """
    def __init__(self, data, **kwargs):
        content = JSONRenderer().render(data)
        kwargs['content_type'] = 'application/json'
        super(JSONResponse, self).__init__(content, **kwargs)

class Entry(object):
    def __init__(self):
        pass

class EntrySerializer(serializers.Serializer):
    def restore_object(self, attrs, instance=None):
        if instance:
            return instance
        return Entry()


# django views
###############################################################################
def course(request, cid):
    #try:
    #    user_course = UserCourse.objects.get(course=course_id)
    #except UserCourse.DoesNotExist:
    #    raise Http404("Question does not exist")
    data = {}
    course = get_object_or_404(Course, pk=cid)
    return render(request, 'courses/course.html', {'course': course, 'data': data})

def section(request, cid, seid):
    data = {}
    course = get_object_or_404(Course, pk=cid)
    return render(request, 'courses/course.html', {'course': course, 'data': data})

def slide(request, cid, seid, slid):
    data = {}
    course = get_object_or_404(Course, pk=cid)
    return render(request, 'courses/course.html', {'course': course, 'data': data})

def slide_check(request, cid, seid, slid):
    data = {}
    course = get_object_or_404(Course, pk=cid)
    return render(request, 'courses/course.html', {'course': course, 'data': data})




###


def index(request):
    return HttpResponse("Usage: /api/rest/..")


#@api_view(['GET','POST'])
@csrf_exempt
def entry_list(request, database_id):
    data =  str({"field1": "value1"})

    if request.method == 'GET':
        json_docs = [json.dumps(doc, default=json_util.default) for doc in cursor]
        return HttpResponse("[%s]" % (",".join(json_docs)))

    elif request.method == 'POST':
        data = JSONParser().parse(request)
        try:
            _id = collection.insert(data)
            data["_id"] = _id
            json_docs = json.dumps(data, default=json_util.default)
            return HttpResponse("%s" % json_docs, status=201)

        except:
            return JSONResponse("""{"error": "insert failed."}""", status=400)




# Event Stream API
###############################################################################
@api_view(['POST'])
@csrf_exempt
def event(request):
    #event_db = mongo["events"]
    #event_col = event_db["events"]
    return JSONResponse({"details": "OK"}, status=201)

    #if request.method == 'POST':

    #    # populate additional fields
    #    request.data["timestamp"] = datetime.datetime.now()
    #    request.data["referrer"] = request.META.get('HTTP_REFERER') # sic
    #    request.data["user_id"] = request.user.id
    #    #print(request.data, file=sys.stderr)

    #    try:
    #        _id = event_col.insert(request.data)
    #        print(request.data['type'], _id, file=sys.stderr)
    #        #json_docs = json.dumps(data, default=json_util.default)
    #        return JSONResponse({"details": "OK", "id": str(_id)}, status=201)

    #    except:
    #        return JSONResponse({"details": "insert failed."}, status=400)
    #else:
    #    return JSONResponse("""{"error": "HTTP request type not allowed."}""", status=400)




# Job API
###############################################################################
#@api_view(['GET','POST'])
@csrf_exempt
def job_status(request, jid):
    #print("Job-status " + jid)
    data =  str({"field1": "value1"})

    #job_db = mongo["jobs"]
    #job_col = job_db["jobs"]

    #return HttpResponse(status=404)

    if request.method == 'GET':
        #task = celery_task_compile_and_run.AsyncResult(jid)
        task = local_execute_result(jid)
        #print("results")
        data = {"status": task["status"], "data": task["result"]}
        #print("DONE!")

        #json_docs = json.dumps(data, default=json_util.default)
        #data = JSONParser().parse(json_docs)
        return JSONResponse(data)

    return HttpResponse("huh", status=401)


@api_view(['POST'])
@csrf_exempt
def job_new(request):
    #job_db = mongo["jobs"]
    #job_col = job_db["jobs"]
    # Snipped in-case we would like to force the referrer to match the slide.
    #slid = None
    #referrer = request.META.get('HTTP_REFERER')
    #result = re.findall(r'/courses/(?P<cid>[0-9]+)/(?P<seid>[0-9]+)/(?P<slid>[0-9]+)/$', referrer)
    #print(result, file=sys.stderr)

    #try:
    #    slid = Slide.objects.get(pk=result[0][2])
    #except Comment.DoesNotExist:
    #    slid = None
    #
    #print(slid, file=sys.stderr)

    if request.method == 'POST':
        #print(datetime.datetime.now(), file=sys.stderr)
        #print(request.data, file=sys.stderr)

        slide = get_object_or_404(Slide, pk=request.data['slide'])
        #print("Solution from: ", slide.title, file=sys.stderr)

        job_dic = {}
        #job_dic['timestamp'] = datetime.datetime.now()
        job_dic['solution'] = request.data['solution']
        job_dic['action'] = request.data['action']
        job_dic['source_path'] = slide.source_path
        job_dic['type'] = slide.slide_type
        job_dic['data'] = json.loads(slide.data)
        job_dic['user_id'] = request.user.id
        #print('job_dic:', file=sys.stderr)

        # Also create/update the user solution.
        user_solution = None
        if request.user.is_authenticated:
            try:
                item, created = UserSolution.objects.get_or_create(slide=slide, user=request.user)
                user_solution = item
            except UserSolution.DoesNotExist:
                pass

        #print(user_solution, file=sys.stderr)

        if user_solution != None:
            user_solution.data = json.dumps(request.data)
            user_solution.save()

        #pprint.pprint(job_dic, sys.stderr)

        try:
            #task = celery_task_compile_and_run.delay(job_dic)
            data = local_execute(job_dic)
            #_id = job_col.insert(request.data)
            #print(_id, file=sys.stderr)
            #json_docs = json.dumps(data, default=json_util.default)
            return JSONResponse(data, status=201)
        except:
            print(sys.exc_info()[0])
            return JSONResponse({"details": "Job submission failed."}, status=400)




    #else:
    #    return JSONResponse("""{"error": "HTTP request type not allowed."}""", status=400)
    #else:
    #    return JSONResponse("""{"error": "HTTP request type not allowed."}""", status=400)

#    return HttpResponse("huh")
#
#    if request.method == 'GET':
#        data = collection.find_one({"_id": _id})
#        json_docs = json.dumps(data, default=json_util.default)
#        return HttpResponse("%s" % json_docs)
#
#    elif request.method == 'PUT':
#        data = JSONParser().parse(request)
#        data.pop("_id", None)     # remove _id key from data for pymongo
#        print >>sys.stdout, data
#        try:
#            collection.update({"_id": _id}, data)
#            data["_id"] = _id
#            json_docs = json.dumps(data, default=json_util.default)
#            return HttpResponse("%s" % json_docs)
#        except:
#            return JSONResponse("""{"error": "update failed."}""", status=400)
#
#    elif request.method == 'DELETE':
#        collection.remove({"_id": _id})
#        return HttpResponse(status=204)
#
