# -*- coding: utf-8 -*-
'''
Created on Jul 01, 2014

@author: tc
'''
from datetime import datetime
import json
import logging
import uuid

from django.db import transaction
from django.core.urlresolvers import reverse
from django.http import Http404
from django.http.response import HttpResponse, HttpResponseBadRequest
from django.shortcuts import get_object_or_404, redirect
from django.views.generic import View
from django.conf import settings
from renkanmanager.models import Renkan, Revision, Workspace
from renkanmanager.serializers import RenkanSerializer, RevisionSerializer, WorkspaceSerializer
from rest_framework import permissions, status
from rest_framework.response import Response
from rest_framework.views import APIView

logger = logging.getLogger(__name__)
           
class RenkanList(APIView):
    """
        View for listing renkans or posting new renkan
    """
    
    queryset = Renkan.objects
    
    def get(self, request, workspace_guid='', format=None):
        if workspace_guid == '':
            renkans = self.queryset.all()
        else:
            renkans = self.queryset.filter(workspace__workspace_guid=workspace_guid)
        serializer = RenkanSerializer(renkans, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK, content_type='application/json')    
    
    def post(self, request, workspace_guid='', format=None):
        create_data = {key:request.data[key] for key in request.data.keys()}
        source_renkan_guid = request.GET.get("source_renkan_id", request.data.get("source_renkan_id", None))
        source_revision_guid = request.GET.get("source_revision_id", request.data.get("source_revision_id", None))
        if source_renkan_guid is not None:
            try:
                source_renkan=Renkan.objects.get(renkan_guid=source_renkan_guid)
            except Renkan.DoesNotExist:
                return Response({'detail': 'Source renkan '+source_renkan_guid+' does not exist'}, status=status.HTTP_404_NOT_FOUND)
            source_revision_guid = source_renkan.current_revision.revision_guid
        if source_revision_guid is not None:
            try:
                source_revision=Revision.objects.get(revision_guid=source_revision_guid)
            except Revision.DoesNotExist:
                return Response({'detail': 'Source revision '+source_revision_guid+' does not exist'}, status=status.HTTP_404_NOT_FOUND)
            create_data["source_revision_id"] = source_revision.revision_guid
            create_data["title"] = request.data.get("title", source_revision.title)
            create_data["content"] = source_revision.content
        if workspace_guid:
            try:
                workspace = Workspace.objects.get(workspace_guid=workspace_guid)
            except Workspace.DoesNotExist:
                return Response({'detail': 'Workspace '+workspace_guid+' does not exist'}, status=status.HTTP_404_NOT_FOUND)
            create_data["workspace_id"] = workspace_guid
        serializer = RenkanSerializer(data=create_data)
        if serializer.is_valid():
            serializer.save(creator=request.user)     
            return Response(serializer.data, status=status.HTTP_201_CREATED, content_type='application/json')
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        

class RenkanDetail(APIView):
    """
        View for retrieving, updating or deleting a single renkan
    """
    lookup_field = "renkan_guid"
    queryset = Renkan.objects
    
    def get_object(self, renkan_guid):
        return self.queryset.get(renkan_guid=renkan_guid)
    
    def dispatch(self, *args, **kwargs):
        return super(RenkanDetail, self).dispatch(*args, **kwargs)
    
    def get(self, request, renkan_guid, format=None):
        try:
            renkan = self.get_object(renkan_guid=renkan_guid)
        except Renkan.DoesNotExist:
            return Response({'detail': 'Renkan project '+renkan_guid+' does not exist'}, status=status.HTTP_404_NOT_FOUND)
        self.check_object_permissions(request, renkan)
        serializer = RenkanSerializer(renkan)
        if {'true': True, 'false': False, "0": False, "1": True}.get(request.GET.get("content_only", "false").lower()):
            return Response(json.loads(serializer.data["content"]), status=status.HTTP_200_OK, content_type='application/json')
        return Response(serializer.data, status=status.HTTP_200_OK, content_type='application/json')

    def put(self, request, renkan_guid, format=None):
        try:
            renkan = self.get_object(renkan_guid=renkan_guid)
        except Renkan.DoesNotExist:
            return Response({'detail': 'Renkan project '+renkan_guid+' does not exist'}, status=status.HTTP_404_NOT_FOUND)
        logger.debug("RENKAN PUT %r : CHECKING OBJECT PERMISSION", renkan_guid)
        logger.debug("RENKAN PUT: permission? %r", request.user.has_perm("change_renkan", renkan))
        self.check_object_permissions(request, renkan)
        logger.debug("RENKAN PUT: PERMISSION GRANTED")
        if {'true': True, 'false': False, "0": False, "1": True}.get(request.GET.get("content_only", "false").lower()):
            put_data = {}
            put_data["content"] = json.dumps(request.data)
            put_data["title"] = request.data.get("title", "")
        else:
            put_data = request.data
        if put_data.get("validation_timestamp", None) is None and put_data.get("content", None) is not None:
            put_data["validation_timestamp"] = json.loads(put_data["content"]).get("updated", "")
        serializer = RenkanSerializer(renkan, data=put_data)
        if serializer.is_valid():
            serializer.save(updator=request.user)
            if {'true': True, 'false': False, "0": False, "1": True}.get(request.GET.get("content_only", "false").lower()):
                return Response(json.loads(serializer.data["content"]), status=status.HTTP_200_OK, content_type='application/json')
            return Response(serializer.data, status=status.HTTP_200_OK, content_type='application/json')
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    @transaction.atomic
    def delete(self, request, renkan_guid, format=None):
        try:
            to_delete_renkan = self.get_object(renkan_guid=renkan_guid)
        except Renkan.DoesNotExist:
            return Response({'detail': 'Renkan project '+renkan_guid+' does not exist'}, status=status.HTTP_404_NOT_FOUND)
        self.check_object_permissions(request, to_delete_renkan)
        to_delete_renkan.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

class WorkspaceList(APIView):
    """
        View for listing workspaces or creating new workspace
    """
    
    queryset = Workspace.objects
    
    def get(self, request, format=None):
        workspaces = self.queryset.all()
        serializer = WorkspaceSerializer(workspaces, many=True)
        return Response(serializer.data)

    def post(self, request, format=None):
        serializer = WorkspaceSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save(creator=request.user)
            return Response(serializer.data, status=status.HTTP_201_CREATED, content_type='application/json')
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

class WorkspaceDetail(APIView):
    """
        View for retrieving, updating or deleting a single workspace
    """
    
    lookup_field = "workspace_guid"
    queryset = Workspace.objects
    
    def get_object(self, workspace_guid):
        return self.queryset.get(workspace_guid=workspace_guid)
    
    def get(self, request, workspace_guid, format=None):
        try:
            workspace = self.get_object(workspace_guid=workspace_guid)
        except Workspace.DoesNotExist:
            return Response({'detail': 'Workspace '+workspace_guid+' does not exist.'}, status=status.HTTP_404_NOT_FOUND)
        self.check_object_permissions(request, workspace)
        serializer = WorkspaceSerializer(workspace)
        return Response(serializer.data, status=status.HTTP_200_OK, content_type='application/json')

    def put(self, request, workspace_guid, format=None):
        try:
            workspace = self.get_object(workspace_guid=workspace_guid)
        except Workspace.DoesNotExist:
            return Response({'detail': 'Workspace '+workspace_guid+' does not exist.'}, status=status.HTTP_404_NOT_FOUND)
        self.check_object_permissions(request, workspace)
        serializer = WorkspaceSerializer(workspace, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_200_OK, content_type='application/json')
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, workspace_guid, format=None):
        try:
            to_delete_workspace = self.get_object(workspace_guid=workspace_guid)
        except Workspace.DoesNotExist:
            return Response({'detail': 'Workspace '+workspace_guid+' does not exist'}, status=status.HTTP_404_NOT_FOUND)
        self.check_object_permissions(request, to_delete_workspace)
        if to_delete_workspace.renkan_count != 0:
            return Response({'detail': 'Workspace '+workspace_guid+' cannot be deleted because it is not empty'}, status=status.HTTP_400_BAD_REQUEST)
        to_delete_workspace.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

class RevisionList(APIView):
    """
        View for listing revisions from a given renkan
    """
    
    def get_queryset(self, renkan_guid=""):
        if renkan_guid:
            return Revision.objects.filter(parent_renkan__renkan_guid=renkan_guid)
        else:
            return Revision.objects
    
    def get(self, request, renkan_guid, format=None):
        revisions = self.get_queryset(renkan_guid)
        if not revisions:
            return Response({'detail': 'Renkan project '+renkan_guid+' does not exist'}, status=status.HTTP_404_NOT_FOUND)
        serializer = RevisionSerializer(revisions.all(), many=True)
        return Response(serializer.data, status=status.HTTP_200_OK, content_type='application/json')

class RevisionDetail(APIView):
    """
        View for retrieving or deleting a single revision from a given renkan
    """
    
    lookup_field = "revision_guid"
    
    def get_queryset(self, renkan_guid=""):
        if renkan_guid:
            return Revision.objects.filter(parent_renkan__renkan_guid=renkan_guid)
        else:
            return Revision.objects
    
    def get(self, request, renkan_guid, revision_guid, format=None):
        revisions = self.get_queryset(renkan_guid)
        if not revisions:
            return Response({'detail': 'Renkan project '+renkan_guid+' does not exist'}, status=status.HTTP_404_NOT_FOUND)
        try:
            revision = revisions.get(revision_guid=revision_guid)
        except Revision.DoesNotExist:
            return Response({'detail': 'Revision '+revision_guid+' does not exist'}, status=status.HTTP_404_NOT_FOUND)
        self.check_object_permissions(request, revision)
        serializer = RevisionSerializer(revision)
        return Response(serializer.data, status=status.HTTP_200_OK, content_type='application/json')

    def delete(self, request, renkan_guid, revision_guid, format=None):
        revisions = self.get_queryset(renkan_guid)
        if not revisions:
            return Response({'detail': 'Renkan project '+renkan_guid+' does not exist'}, status=status.HTTP_404_NOT_FOUND)
        try:
            revision = revisions.get(revision_guid=revision_guid)
        except Revision.DoesNotExist:
            return Response({'detail': 'Revision '+revision_guid+' does not exist'}, status=status.HTTP_404_NOT_FOUND)
        self.check_object_permissions(request, revision)
        if revisions.count() == 1:
            return Response({'detail': 'You cannot delete the last remaining revision of a renkan from the Revision API. Try deleting the parent Renkan with the Renkan API'}, status=status.HTTP_400_BAD_REQUEST)
        if revision.is_current_revision:
            return Response({'detail': 'You cannot delete the current revision of a renkan from the Revision API.'}, status=status.HTTP_400_BAD_REQUEST)
        revision.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)
