import json
from xml.etree import ElementTree
from corehq import toggles
from corehq.apps.userreports.reports.factory import ReportFactory
from corehq.apps.userreports.reports.specs import MultibarChartSpec
from .models import ReportConfiguration


class ReportFixturesProvider(object):
    id = 'commcare:reports'

    def __call__(self, user, version, last_sync=None):
        """
        Generates a report fixture for mobile that can be used by a report module
        """
        if not toggles.MOBILE_UCR.enabled(user.domain):
            return []

        reports = ReportConfiguration.by_domain(user.domain)
        if not reports:
            return []

        root = ElementTree.Element('fixture', attrib={'id': self.id})
        reports_elem = ElementTree.Element('reports')
        for report in reports:
            reports_elem.append(_report_to_fixture(report))
        root.append(reports_elem)
        return [root]

report_fixture_generator = ReportFixturesProvider()


def _report_to_fixture(report):
    report_elem = ElementTree.Element('report',
        attrib={
            'id': report._id,
        },
    )
    report_elem.append(_element('name', report.title))
    report_elem.append(_element('description', report.description))
    # todo: set filter values properly?
    data_source = ReportFactory.from_spec(report)

    rows_elem = ElementTree.Element('rows')

    for i, row in enumerate(data_source.get_data()):
        row_elem = ElementTree.Element('row', attrib={'index': str(i)})
        for k in sorted(row.keys()):
            row_elem.append(_element('column', _serialize(row[k]), attrib={'id': k}))
        rows_elem.append(row_elem)

    report_elem.append(rows_elem)
    return report_elem


def _element(name, text, attrib=None):
    attrib = attrib or {}
    element = ElementTree.Element(name, attrib=attrib)
    element.text = text
    return element


def _serialize(value):
    # todo: be smarter than this
    return '' if value is None else unicode(value)

@@ -844,16 +844,21 @@
 .append(
+self.
 _report_
@@ -938,62 +938,12 @@
 t%5D%0A%0A
-report_fixture_generator = ReportFixturesProvider()%0A%0A%0A
+    
 def 
@@ -957,24 +957,30 @@
 _to_fixture(
+self, 
 report):%0A   
@@ -972,24 +972,28 @@
 f, report):%0A
+    
     report_e
@@ -1027,24 +1027,16 @@
 report',
-%0A       
  attrib=
@@ -1036,29 +1036,16 @@
 attrib=%7B
-%0A            
 'id': re
@@ -1056,27 +1056,15 @@
 ._id
-,%0A        %7D,
+%7D)
 %0A    
-)%0A
     
@@ -1074,32 +1074,37 @@
 ort_elem.append(
+self.
 _element('name',
@@ -1119,24 +1119,28 @@
 title))%0A    
+  
+  
 report_elem.
@@ -1138,32 +1138,37 @@
 ort_elem.append(
+self.
 _element('descri
@@ -1196,24 +1196,28 @@
 ption))%0A    
+  
+  
 # todo: set 
@@ -1240,16 +1240,20 @@
 operly?%0A
+    
     data
@@ -1295,24 +1295,28 @@
 eport)%0A%0A    
+   
+ 
 rows_elem = 
@@ -1344,16 +1344,20 @@
 rows')%0A%0A
+    
     for 
@@ -1397,24 +1397,28 @@
 et_data()):%0A
+    
         row_
@@ -1481,24 +1481,28 @@
 )%7D)%0A        
+    
 for k in sor
@@ -1514,24 +1514,28 @@
 ow.keys()):%0A
+    
             
@@ -1550,16 +1550,21 @@
 .append(
+self.
 _element
@@ -1574,16 +1574,21 @@
 olumn', 
+self.
 _seriali
@@ -1618,32 +1618,36 @@
 ': k%7D))%0A        
+    
 rows_elem.append
@@ -1658,16 +1658,20 @@
 _elem)%0A%0A
+    
     repo
@@ -1692,24 +1692,28 @@
 (rows_elem)%0A
+    
     return r
@@ -1724,17 +1724,38 @@
 t_elem%0A%0A
-%0A
+    @staticmethod%0A    
 def _ele
@@ -1789,16 +1789,20 @@
 e):%0A    
+  
+  
 attrib =
@@ -1815,16 +1815,20 @@
 b or %7B%7D%0A
+    
     elem
@@ -1874,24 +1874,28 @@
 attrib)%0A    
+   
+ 
 element.text
@@ -1902,16 +1902,20 @@
  = text%0A
+    
     retu
@@ -1926,17 +1926,38 @@
 lement%0A%0A
-%0A
+    @staticmethod%0A    
 def _ser
@@ -1967,24 +1967,28 @@
 ize(value):%0A
+    
     # todo: 
@@ -2008,16 +2008,20 @@
 an this%0A
+    
     retu
@@ -2063,8 +2063,61 @@
 (value)%0A
+%0Areport_fixture_generator = ReportFixturesProvider()%0A

Move functions to methods