from django.http import HttpResponse
from django.views.generic.base import View

from staff.lib.json import dumps

from staff.apicenter.utils import get_fields, xml_serialize


def xml_escape_tag(tag_text):
    return (
        tag_text.replace('&', '&amp;')
        .replace('>', '&gt;')
        .replace('<', '&lt;')
    )


def xml_escape_attr(attr_text):
    return xml_escape_tag(attr_text).replace('"', '&quot;')


class ApiView(View):
    http_method_names = ('get',)
    entities = ('item', )
    datetime_fields = tuple()

    def __init__(self, *args, **kwargs):
        self.data = None
        super(ApiView, self).__init__(*args, **kwargs)

    def __call__(self, request, *args, **kwargs):
        self.request = request
        if 'format' in kwargs:
            self.format = kwargs.get('format', 'json').strip('.')
        else:
            self.format = args[-1].strip('.')

        self.prepare_data(*args, **kwargs)

        if self.format == 'xml' and hasattr(self, 'render_xml'):
            r = self.render_xml()
        elif self.format == 'json' and hasattr(self, 'render_json'):
            r = self.render_json()
        elif self.format == 'jsonp' and (hasattr(self, 'render_jsonp') or hasattr(self, 'render_json')):
            if hasattr(self, 'render_jsonp'):
                r = self.render_jsonp()
            else:
                r = self.render_json()
                cb = self.request.GET.get('callback', self.request.POST.get('callback', 'callback'))
                r._container = ['var data = %s; %s(data);' % (r._container[0], cb)]
        else:
            r = self._render()
        return r

    def _render(self):
        """
        Default render method (uses serialize from api.utils)
        It's called if class doesn't have another _render* method for requested format
        """

        # xml section
        if self.format == 'xml':
            return HttpResponse(
                xml_serialize(self.data, self.entities),
                content_type='text/xml'
            )

        # json/jsonp section
        r = dumps(self.data)
        callback = self.request.GET.get('callback', self.request.POST.get('callback', None))
        if self.format == 'jsonp' and callback:
            return HttpResponse(
                'var data = %s; %s(data);' % (r, callback),
                content_type='text/javascript'
            )

        return HttpResponse(r, content_type='text/javascript')

    def get_fields(self, model, var_name, default_fields, full_fields, required_fields=None):
        r = list([x for x in get_fields(self.request, default_fields, var_name, model) if x in full_fields])
        if required_fields:
            r = list(r)
            for f in required_fields:
                if f not in r:
                    r.append(f)
        return r

    def get_requested_fields(self, var_name, default=None):
        return get_fields(self.request, var_name=var_name, default=default)

    @staticmethod
    def full_fields(model, foreign_fields=None):
        fields = [f.name for f in model._meta.fields]
        if foreign_fields:
            for field, _model in foreign_fields.items():
                fields += [field+'__'+f.name for f in _model._meta.fields]
        return fields

    def dispatch(self, *args, **kwargs):
        return super(ApiView, self).dispatch(*args, **kwargs)

    # compat with django *View classes
    get = __call__
