
from copy import deepcopy
from datetime import datetime
import json

from django.conf import settings
from django.contrib.auth import get_user_model
from django.core.urlresolvers import reverse
from django.http import HttpResponse
from django.shortcuts import render
from django.utils.dateparse import parse_datetime
from django.views.generic import View
import jwt
import requests
from rest_framework import status
from rest_framework.authentication import TokenAuthentication
from rest_framework.authtoken.models import Token
from rest_framework.decorators import api_view
from rest_framework.permissions import IsAuthenticated, AllowAny
from rest_framework.response import Response
from rest_framework.views import APIView

from ammicosrv.ammico.models import Book, Slide, Exposition
from ammicosrv.ammico.serializers.ammico import BookSerializer, SlideSerializer


#from django.contrib.auth import login, logout
User = get_user_model()

def populateVisit(user, idExpo):
    # send request with usermail to get the visits of this user and add it to the database 
    #r = requests.get('http://fui-ammico.jamespot.pro/api/api.php?&k=6c8bfcea247e8a5841288269887d88f0&d=2016-01-31&m=EXT-IRI&v=2.0&f=get&o=article&idArticle=169')

    #simulate the request
    url_request = Exposition.objects.get(id=idExpo).url_jamespot
    params = {'o': 'article', 'f': 'list', 'idUser': user.id_user} 
    r = requests.get(url_request, params=params)
    visits = json.loads(r.content.decode('utf-8'))
    
    for visit in visits['VAL']:
        params = {'o' : 'article', 'f' : 'get', 'idArticle' : visit['idArticle']}
        r = requests.get(url_request, params=params)
        visitInfo = json.loads(r.content.decode('utf-8'))['VAL']
        
        
        if (not Book.objects.filter(id_article=visit['idArticle'], user=user).exists()):
            book = Book.objects.create(
                user=user,
                exposition = Exposition.objects.get(id=idExpo),
                id_article=visitInfo['idArticle'],
                title = visitInfo['title'],
                description = visitInfo['description'],
                image = visitInfo['image'],
                date = parse_datetime(visitInfo['dateCreation']),
            )
            populateSlide(json.loads(visitInfo['steps']), book)

def populateSlide(steps, book):
    for step in steps:
        if (step['stop'] != None and step['stop'] != ''):
            
            if 'comment' in step:
                description = step['comment']
            else:
                description = ""
            
            Slide.objects.update_or_create(
                book=book,
                id_stop=step['stop'],
                defaults={
                    'description' : description,
                    'date' : parse_datetime(str(datetime.strptime(step['DATE'] + " " + step['TIME'], "%d/%m/%Y %H:%M:%S")))
                }
            )
            
@api_view(('GET',))
def api_root(request):
    return Response({
        'books': reverse('books', request=request),
        'slides': reverse('slides', request=request)
    })

class AmmicoView(View):
    def get(self, request, idExpo):
        if (idExpo and Exposition.objects.filter(id=idExpo).exists()):
            key = ''
            if ('k' in request.GET):
                payload = jwt.decode(request.GET['k'], settings.AUTH_JAMESPOT, algorithms=['HS256'])
                if (('email' and 'idUser') in payload):
                    user, _ = User.objects.get_or_create(email = payload['email'], id_user = payload['idUser'])
                    populateVisit(user, idExpo)
                    token, _ = Token.objects.get_or_create(user=user)
                    key = str(token.key)
            context = {
                'token': key,
                'idExpo': idExpo,
                'ammicoUrl': request.build_absolute_uri(reverse('ammico:api-root')),
                'searchUrl': Exposition.objects.get(id=idExpo).url_exalead_search
            }
            return render(request, 'indexAmmico.html', {'context': context})
        else:
            expositions = Exposition.objects.all()
            return render(request, 'index.html', {'expositions' : expositions})
        
            
class PublicBooks(APIView):
    """
    Send back published books
    """
    
    authentication_classes = (TokenAuthentication,)
    permission_classes = (AllowAny,)

    def get(self, request):
        """
        Return a list of all Books.
        """
        books = Book.objects.filter(public=True)
        if 'idExpo' in request.GET:
            books = books.filter(exposition = request.GET['idExpo'])
        serializer = BookSerializer(books, many=True)
        return Response(serializer.data)
            
class ListBooks(APIView):
    """
    Views to list all books.
    """
    
    authentication_classes = (TokenAuthentication,)
    permission_classes = (IsAuthenticated,)

    def get(self, request):
        """
        Return a list of all Books.
        """
        books = Book.objects.filter(user = request.user.id)
        if 'idExpo' in request.GET:
            books = books.filter(exposition = request.GET['idExpo'])
        if 'type' in request.GET:
            books = books.filter(id_article__isnull = True if (request.GET['type'] == 'book') else False)
        
        serializer = BookSerializer(books, many=True)
        return Response(serializer.data)
    
    def post(self, request):
        """
        Add a Book
        """
        
        if ('idExpo' not in request.GET):
            return Response("please specify a correct idExpo as a get parameter", status=status.HTTP_400_BAD_REQUEST)
        
        DEFAULTS = {
            "user":request.user.id,
            "exposition": request.GET['idExpo']
        }
        
        if ('idParent' in request.data):
            try:
                book = Book.objects.get(user = request.user.id, id=request.data['idParent'])
            except Book.DoesNotExist:
                return Response(status=status.HTTP_400_BAD_REQUEST)
            new_book = deepcopy(book)
            new_book.title = request.data['title']
            new_book.id_article = None
            new_book.parent_visit = book
            new_book.id = None
            new_book.save()
            for i in book.slides.all():
                new_slide = deepcopy(i)
                new_slide.id = None
                new_slide.book = new_book
                new_slide.save()
            serializer = BookSerializer(new_book)
            return Response(serializer.data)
        else:
            request.data.update(DEFAULTS)
            serializer = BookSerializer(data=request.data)
            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data, status=status.HTTP_201_CREATED)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        

class InfoBook(APIView):
    """
    View relative to a book
    """
    
    authentication_classes = (TokenAuthentication,)
    permission_classes = (IsAuthenticated,)

    def get(self, request, idBook):
        """
        Get information from a book
        """
        try:
            book = Book.objects.get(user = request.user.id, id=idBook)
        except Book.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)
        
        serializer = BookSerializer(book)
        return Response(serializer.data)
    
    def put(self, request, idBook):
        """
        update a Book
        """
        try:
            book = Book.objects.get(user = request.user.id, id=idBook)
        except Book.DoesNotExist:
            return Response(status=status.HTTP_204_NO_CONTENT)
        
        if (book.id_article):
            return Response(status=status.HTTP_403_FORBIDDEN)
        
        serializer = BookSerializer(book, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_200_OK)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    
    def delete(self, request, idBook):
        """
        delete a book
        """
        try:
            book = Book.objects.get(user = request.user.id, id = idBook)
        except Book.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)
        
        if (book.id_article):
            return Response(status=status.HTTP_403_FORBIDDEN)
        
        book.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)
    

class SlidesOrder(APIView):
    """
    Manage Slides order
    """
    
    authentication_classes = (TokenAuthentication,)
    permission_classes = (IsAuthenticated,)

    def get(self, request, idBook):
        """
        Get slides order
        """
        try:
            book = Book.objects.get(user = request.user.id, id=idBook)
        except Book.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)
        response = {}
        response["order"] = book.get_slide_order()
        return Response(response)
    
    def post(self, request, idBook):
        """
        Set Slides order
        """
        try:
            book = Book.objects.get(user = request.user.id, id=idBook)
        except Book.DoesNotExist:
            return Response(status=status.HTTP_204_NO_CONTENT)
        
        if (book.id_article):
            return Response(status=status.HTTP_403_FORBIDDEN)
        
        book.set_slide_order(request.data['order'])
        return Response(status=status.HTTP_200_OK)

class ListSlides(APIView):
    """
    Views to list all slides.
    """
    
    authentication_classes = (TokenAuthentication,)
    permission_classes = (IsAuthenticated,)

    def get(self, request):
        """
        Return a list of slide
        """
        if 'idBook' in request.GET:
            if 'limit' in request.GET:
                limit = int(request.GET['limit'])
            else:
                limit= None;
            slides = Slide.objects.filter(book__user = request.user.id, book = request.GET['idBook'])[:limit]
        else:
            slides = Slide.objects.filter(book__user = request.user.id)
    
        serializer = SlideSerializer(slides, many=True)
        return Response(serializer.data)
    
    def post(self, request):
        """
        Add a slide
        """
        if 'book' in request.data:
            try:
                book = Book.objects.get(user = request.user.id, id=request.data['book'])
            except Book.DoesNotExist:
                return Response(status=status.HTTP_204_NO_CONTENT)
            if (book.id_article):
                return Response(status=status.HTTP_403_FORBIDDEN)
            
        serializer = SlideSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

class InfoSlide(APIView):
    """
    View to get slide detailed informations.
    """
    
    authentication_classes = (TokenAuthentication,)
    permission_classes = (IsAuthenticated,)

    def get(self, request, idSlide):
        """
        Get information from a slide
        """
        try:
            slide = Slide.objects.get(book__user = request.user.id, id=idSlide)
        except Slide.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)
        
        serializer = SlideSerializer(slide)
        return Response(serializer.data)
    
    def put(self, request, idSlide):
        """
        Update slide information
        """
        try:
            slide = Slide.objects.get(book__user = request.user.id, id=idSlide)
        except Slide.DoesNotExist:
            return HttpResponse(status=status.HTTP_204_NO_CONTENT)
        
        if (slide.book.id_article):
            slide.favorite=request.data['favorite']
            return Response(status=status.HTTP_200_OK)
        serializer = SlideSerializer(slide, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_200_OK)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    
    def delete(self, request, idSlide):
        """
        Delete a slide
        """
        try:
            slide = Slide.objects.get(book__user = request.user.id, id = idSlide)
        except Slide.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)
        
        if (slide.book.id_article):
            return Response(status=status.HTTP_403_FORBIDDEN)
        
        slide.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)