from rest_framework import negotiation
from django.utils.xmlutils import SimplerXMLGenerator

from rest_framework.compat import StringIO
from rest_framework.compat import six
from rest_framework.compat import smart_text
from rest_framework.renderers import BaseRenderer


class XLSRenderer(BaseRenderer):
    media_type = 'application/vnd.openxmlformats'
    format = 'xls'
    charset = None

    def render(self, data, accepted_media_type=None, renderer_context=None):
        return data


class XLSXRenderer(XLSRenderer):
    format = 'xlsx'


class CSVRenderer(BaseRenderer):
    media_type = 'text/csv'
    format = 'csv'
    charset = 'utf-8'


class CSVZIPRenderer(BaseRenderer):
    media_type = 'application/octet-stream'
    format = 'csvzip'
    charset = None


class SAVZIPRenderer(BaseRenderer):
    media_type = 'application/octet-stream'
    format = 'savzip'
    charset = None


# TODO add KML, ZIP(attachments) support


class SurveyRenderer(BaseRenderer):
    media_type = 'application/xml'
    format = 'xml'
    charset = 'utf-8'

    def render(self, data, accepted_media_type=None, renderer_context=None):
        return data


class MediaFileContentNegotiation(negotiation.DefaultContentNegotiation):
    def filter_renderers(self, renderers, format):
        """
        If there is a '.json' style format suffix, filter the renderers
        so that we only negotiation against those that accept that format.
        If there is no renderer available, we use MediaFileRenderer.
        """
        renderers = [renderer for renderer in renderers
                     if renderer.format == format]
        if not renderers:
            renderers = [MediaFileRenderer()]

        return renderers


class MediaFileRenderer(BaseRenderer):
    media_type = '*/*'
    format = None
    charset = None
    render_style = 'binary'

    def render(self, data, accepted_media_type=None, renderer_context=None):
        return data


class XFormListRenderer(BaseRenderer):
    """
    Renderer which serializes to XML.
    """

    media_type = 'text/xml'
    format = 'xml'
    charset = 'utf-8'

    def render(self, data, accepted_media_type=None, renderer_context=None):
        """
        Renders *obj* into serialized XML.
        """
        if data is None:
            return ''
        elif isinstance(data, six.string_types):
            return data

        stream = StringIO()

        xml = SimplerXMLGenerator(stream, self.charset)
        xml.startDocument()
        xml.startElement("xforms", {
            'xmlns': "http://openrosa.org/xforms/xformsList"
        })

        self._to_xml(xml, data)

        xml.endElement("xforms")
        xml.endDocument()

        return stream.getvalue()

    def _to_xml(self, xml, data):
        if isinstance(data, (list, tuple)):
            for item in data:
                xml.startElement("xform", {})
                self._to_xml(xml, item)
                xml.endElement("xform")

        elif isinstance(data, dict):
            for key, value in six.iteritems(data):
                xml.startElement(key, {})
                self._to_xml(xml, value)
                xml.endElement(key)

        elif data is None:
            # Don't output any value
            pass

        else:
            xml.characters(smart_text(data))

@@ -2099,32 +2099,136 @@
 harset = 'utf-8'
+%0A    root_node = 'xforms'%0A    element_node = 'xform'%0A    xmlns = %22http://openrosa.org/xforms/xformsList%22
 %0A%0A    def render
@@ -2620,89 +2620,44 @@
 ent(
-%22xforms%22, %7B%0A            'xmlns': %22http://openrosa.org/xforms/xformsList%22%0A        
+self.root_node, %7B'xmlns': self.xmlns
 %7D)%0A%0A
@@ -2716,16 +2716,22 @@
 ent(
-%22xforms%22
+self.root_node
 )%0A  
@@ -2930,23 +2930,33 @@
 Element(
-%22xform%22
+self.element_node
 , %7B%7D)%0A  
@@ -3028,15 +3028,25 @@
 ent(
-%22xform%22
+self.element_node
 )%0A%0A 
@@ -3393,8 +3393,172 @@
 (data))%0A
+%0A%0Aclass XFormManifestRenderer(XFormListRenderer):%0A    root_node = %22manifest%22%0A    element_node = %22mediaFile%22%0A    xmlns = %22http://openrosa.org/xforms/xformsManifest%22%0A

add XFormManifestRenderer