
from logging import getLogger

from rest_framework import serializers, fields
from rest_framework.metadata import SimpleMetadata
from rest_framework.request import clone_request
from django.utils.encoding import force_str

log = getLogger(__name__)


class ExpandedMetadata(SimpleMetadata):

    def determine_metadata(self, request, view):
        metadata = super().determine_metadata(request, view)

        if hasattr(view, "ordering_fields"):
            metadata["sort"] = view.ordering_fields

        if hasattr(view, "filterset_fields"):
            metadata["filter"] = view.filterset_fields

        return metadata

    def determine_actions(self, request, view):
        """
        For generic class based views we return information about
        the fields that are accepted for 'PUT' and 'POST' methods.
        """
        actions = {}
        for method in {'PUT', 'POST', "GET"} & set(view.allowed_methods):
            view.request = clone_request(request, method)
            try:
                # Test global permissions
                if hasattr(view, 'check_permissions'):
                    view.check_permissions(view.request)
                # Test object permissions
                if method == 'PUT' and hasattr(view, 'get_object'):
                    view.get_object()
            except (exceptions.APIException, PermissionDenied, Http404):
                pass
            else:
                # If user has appropriate permissions for the view, include
                # appropriate metadata about the fields that should be supplied.
                serializer = view.get_serializer()
                actions[method] = self.get_serializer_info(serializer)
            finally:
                view.request = request

        return actions

    def get_field_info(self, field):
        field_info = super().get_field_info(field)
        if hasattr(field, 'default') and field.default is not fields.empty:
            field_info['default'] = field.default

        if hasattr(field, 'initial') and field.initial is not fields.empty:
            field_info['initial'] = field.initial

        return field_info
