from rest_framework import generics
from rest_framework import serializers
from rest_framework.response import Response
from rest_framework import status
from xos.apibase import XOSRetrieveUpdateDestroyAPIView, XOSListCreateAPIView
from rest_framework import viewsets
from django.conf.urls import patterns, url
from xos.exceptions import *

if hasattr(serializers, "ReadOnlyField"):
    # rest_framework 3.x
    ReadOnlyField = serializers.ReadOnlyField
else:
    # rest_framework 2.x
    ReadOnlyField = serializers.Field

""" PlusSerializerMixin

    Implements Serializer fields that are common to all OpenCloud objects. For
    example, stuff related to backend fields.
"""

class PlusModelSerializer(serializers.ModelSerializer):
    backendIcon = serializers.SerializerMethodField("getBackendIcon")
    backendHtml = serializers.SerializerMethodField("getBackendHtml")

    # This will cause a descendant class to pull in the methods defined
    # above. See rest_framework/serializers.py: _get_declared_fields().
    base_fields = {"backendIcon": backendIcon, "backendHtml": backendHtml}
    # Rest_framework 3.0 uses _declared_fields instead of base_fields
    _declared_fields = {"backendIcon": backendIcon, "backendHtml": backendHtml}

    def getBackendIcon(self, obj):
        return obj.getBackendIcon()

    def getBackendHtml(self, obj):
        return obj.getBackendHtml()

    def create(self, validated_data):
        property_fields = getattr(self, "property_fields", [])
        create_fields = {}
        for k in validated_data:
            if not k in property_fields:
                create_fields[k] = validated_data[k]
        instance = self.Meta.model(**create_fields)

        if instance and hasattr(instance,"can_update") and self.context.get('request',None):
            user = self.context['request'].user
            if user.__class__.__name__=="AnonymousUser":
                raise XOSPermissionDenied()
            if not instance.can_update(user):
                raise XOSPermissionDenied()

        for k in validated_data:
            if k in property_fields:
                setattr(instance, k, validated_data[k])

        instance.caller = self.context['request'].user
        instance.save()
        return instance

    def update(self, instance, validated_data):
        nested_fields = getattr(self, "nested_fields", [])
        for k in validated_data.keys():
            v = validated_data[k]
            if k in nested_fields:
                d = getattr(instance,k)
                d.update(v)
                setattr(instance,k,d)
            else:
                setattr(instance, k, v)
        instance.caller = self.context['request'].user
        instance.save()
        return instance

class XOSViewSet(viewsets.ModelViewSet):
    api_path=""
    read_only=False

    @classmethod
    def get_api_method_path(self):
        if self.method_name:
            return self.api_path + self.method_name + "/"
        else:
            return self.api_path

    @classmethod
    def detail_url(self, pattern, viewdict, name):
        return url(self.get_api_method_path() + r'(?P<pk>[a-zA-Z0-9\-_]+)/' + pattern,
                   self.as_view(viewdict),
                   name=self.base_name+"_"+name)

    @classmethod
    def list_url(self, pattern, viewdict, name):
        return url(self.get_api_method_path() + pattern,
                   self.as_view(viewdict),
                   name=self.base_name+"_"+name)

    @classmethod
    def get_urlpatterns(self, api_path="^"):
        self.api_path = api_path

        patterns = []

        if self.read_only:
            patterns.append(url(self.get_api_method_path() + '$', self.as_view({'get': 'list'}), name=self.base_name+'_list'))
            patterns.append(url(self.get_api_method_path() + '(?P<pk>[a-zA-Z0-9\-_]+)/$', self.as_view({'get': 'retrieve'}), name=self.base_name+'_detail'))
        else:
            patterns.append(url(self.get_api_method_path() + '$', self.as_view({'get': 'list', 'post': 'create'}), name=self.base_name+'_list'))
            patterns.append(url(self.get_api_method_path() + '(?P<pk>[a-zA-Z0-9\-_]+)/$', self.as_view({'get': 'retrieve', 'put': 'update', 'post': 'update', 'delete': 'destroy', 'patch': 'partial_update'}), name=self.base_name+'_detail'))

        return patterns

    def get_serializer_class(self):
        if hasattr(self, "custom_serializers") and hasattr(self, "action") and (self.action in self.custom_serializers):
            return self.custom_serializers[self.action]
        else:
            return super(XOSViewSet, self).get_serializer_class()

    def get_object(self):
        obj = super(XOSViewSet, self).get_object()

        if self.action=="update" or self.action=="destroy" or self.action.startswith("set_"):
            if obj and hasattr(obj,"can_update"):
                user = self.request.user
                if user.__class__.__name__=="AnonymousUser":
                    raise XOSPermissionDenied()
                if not obj.can_update(user):
                    raise XOSPermissionDenied()

        return obj

class XOSIndexViewSet(viewsets.ViewSet):
    view_urls=[]
    subdirs=[]

    def __init__(self, view_urls, subdirs):
        self.view_urls = view_urls
        self.subdirs = subdirs
        super(XOSIndexViewSet, self).__init__()

    def list(self, request):
        endpoints = []
        for view_url in self.view_urls:
            method_name = view_url[1].split("/")[-1]
            endpoints.append(method_name)

        for subdir in self.subdirs:
            endpoints.append(subdir)

        return Response({"endpoints": endpoints})

