# Path: diva/converters.py
# @singledispatch
# def convert_to_html(val):
#     # default is to just display the value as a string
#     return '<p>{}</p>'.format(str(val))
# 
# Path: diva/widgets.py
# def widgets_template_data(widgets):
#     """
#     The return value of this func should be the input to the widgetform 
#     macro. This generates a widgets form for the given list of widgets.
#     """
#     widget_data = []
#     for index, widget in enumerate(widgets):
#         # the widget type is the name of its python class
#         # the JS setup func is Reports.Widgets.setupMap[widget_type]
#         widget_type = type(widget).__name__
#         html = widget.generateHTML(index)
#         data = {'type': widget_type, 'html': html}
#         widget_data.append(data)
#     return widget_data
# 
# def validate_widget_form_data(widgets, inputs):
#     try:
#         # validate all of the given widget values in 'widgetValues'
#         if type(inputs) is not list:
#             raise ValueError("inputs must be an array")    
#         if len(inputs) != len(widgets):
#             raise ValueError("the inputs array has an incorrect number of items")
#         for wid, value in zip(widgets, inputs):
#             wid.validate_input(value)
#     except Exception as e:
#         raise ValidationError(str(e))
# 
# def parse_widget_form_data(widgets, form_data):
#     """
#     Given list of widgets and a list of form data, with one item
#     for each widget, return a list of parsed form data
#     """
#     inputs = [wid.parseForm(data) for wid, data in 
#             zip(widgets, form_data) if not should_skip(wid)]
#     return inputs
# 
# class Skip(Widget):
#     """
#     A non-interactive widget that just provides a label/header.
#     Useful for clarifying long widget forms
#     """
#     def __init__(self, description):
#         self.description = description
# 
#     def generateHTML(self, formid):
#         return render_template('label_widget.html', description=self.description)
# 
#     def parseForm(self, form_data):
#         """
#         This widget should be skipped when parsing form data
#         see the should_skip and parse_widget_form_data functions below
#         """
#         pass
# 
#     def validate_input(self, form_data):
#         pass
# 
# def should_skip(widget):
#     """
#     True if should skip this widget when parsing values, false ow
#     """
#     return type(widget).__name__ == 'Skip'   
# 
# Path: diva/utilities.py
# @singledispatch
# def get_utilities_for_value(val):
#     return type_utils.get(type(val), [])    
# 
# Path: diva/dashboard.py
# class Dashboard():
#     # default layout is a vertical list of items
#     def __init__(self, items, layout=None):
#         self.items = items
#         if layout is None:
#             self.layout = [[0, i, 1, 1] for i in range(len(items))]
#         else:
#             self.layout = layout


import inspect
from jsonschema import validate
from collections import OrderedDict
from .converters import convert_to_html
from .widgets import (widgets_template_data, validate_widget_form_data,
        parse_widget_form_data, Skip, should_skip)
from .utilities import get_utilities_for_value
from .dashboard import Dashboard
from .exceptions import *
from flask import Flask, render_template, request, abort, jsonify
    # func that generates the figure by passing the user func the 
    # parsed form data, then converting the func's output to HTML
    def update_report(self, report, form_data={}):
        inputs = parse_widget_form_data(report['widgets'], form_data)
        user_func = report['user_func']
        try:
            output = user_func(*inputs)
        except TypeError as err:
            raise WidgetInputError(user_func, inputs)
        utilities = get_utilities_for_value(output)
        # update the report
        report['current_value'] = output
        report['utilities'] = utilities
        # generate the HTML required to update the UI
        figure_html = convert_to_html(output)
        utilityHTML = [util['generate_html'](output) for util in utilities]
        response = {'figureHTML': figure_html, 'utilityHTML': utilityHTML}
        return response
                
    def get_index(self):
        report_data = []
        for report in self.reports:
            widgets = widgets_template_data(report['widgets'])
            report_data.append({'name': report['name'], 'widgets': widgets})
        return render_template(
                'index.html',
                reports=report_data)
            
    def validate_widget_values(self, report, json):
        inputs = json.get('widgetValues', [])

# Path: diva/converters.py
# @singledispatch
# def convert_to_html(val):
#     # default is to just display the value as a string
#     return '<p>{}</p>'.format(str(val))
# 
# Path: diva/widgets.py
# def widgets_template_data(widgets):
#     """
#     The return value of this func should be the input to the widgetform 
#     macro. This generates a widgets form for the given list of widgets.
#     """
#     widget_data = []
#     for index, widget in enumerate(widgets):
#         # the widget type is the name of its python class
#         # the JS setup func is Reports.Widgets.setupMap[widget_type]
#         widget_type = type(widget).__name__
#         html = widget.generateHTML(index)
#         data = {'type': widget_type, 'html': html}
#         widget_data.append(data)
#     return widget_data
# 
# def validate_widget_form_data(widgets, inputs):
#     try:
#         # validate all of the given widget values in 'widgetValues'
#         if type(inputs) is not list:
#             raise ValueError("inputs must be an array")    
#         if len(inputs) != len(widgets):
#             raise ValueError("the inputs array has an incorrect number of items")
#         for wid, value in zip(widgets, inputs):
#             wid.validate_input(value)
#     except Exception as e:
#         raise ValidationError(str(e))
# 
# def parse_widget_form_data(widgets, form_data):
#     """
#     Given list of widgets and a list of form data, with one item
#     for each widget, return a list of parsed form data
#     """
#     inputs = [wid.parseForm(data) for wid, data in 
#             zip(widgets, form_data) if not should_skip(wid)]
#     return inputs
# 
# class Skip(Widget):
#     """
#     A non-interactive widget that just provides a label/header.
#     Useful for clarifying long widget forms
#     """
#     def __init__(self, description):
#         self.description = description
# 
#     def generateHTML(self, formid):
#         return render_template('label_widget.html', description=self.description)
# 
#     def parseForm(self, form_data):
#         """
#         This widget should be skipped when parsing form data
#         see the should_skip and parse_widget_form_data functions below
#         """
#         pass
# 
#     def validate_input(self, form_data):
#         pass
# 
# def should_skip(widget):
#     """
#     True if should skip this widget when parsing values, false ow
#     """
#     return type(widget).__name__ == 'Skip'   
# 
# Path: diva/utilities.py
# @singledispatch
# def get_utilities_for_value(val):
#     return type_utils.get(type(val), [])    
# 
# Path: diva/dashboard.py
# class Dashboard():
#     # default layout is a vertical list of items
#     def __init__(self, items, layout=None):
#         self.items = items
#         if layout is None:
#             self.layout = [[0, i, 1, 1] for i in range(len(items))]
#         else:
#             self.layout = layout


# Path: diva/reporter.py
import inspect
from jsonschema import validate
from collections import OrderedDict
from .converters import convert_to_html
from .widgets import (widgets_template_data, validate_widget_form_data,
        parse_widget_form_data, Skip, should_skip)
from .utilities import get_utilities_for_value
from .dashboard import Dashboard
from .exceptions import *
from flask import Flask, render_template, request, abort, jsonify

    # func that generates the figure by passing the user func the 
    # parsed form data, then converting the func's output to HTML
    def update_report(self, report, form_data={}):
        inputs = parse_widget_form_data(report['widgets'], form_data)
        user_func = report['user_func']
        try:
            output = user_func(*inputs)
        except TypeError as err:
            raise WidgetInputError(user_func, inputs)
        utilities = get_utilities_for_value(output)
        # update the report
        report['current_value'] = output
        report['utilities'] = utilities
        # generate the HTML required to update the UI
        figure_html = convert_to_html(output)
        utilityHTML = [util['generate_html'](output) for util in utilities]
        response = {'figureHTML': figure_html, 'utilityHTML': utilityHTML}
        return response
                
    def get_index(self):
        report_data = []
        for report in self.reports:
            widgets = widgets_template_data(report['widgets'])
            report_data.append({'name': report['name'], 'widgets': widgets})
        return render_template(
                'index.html',
                reports=report_data)
            
    def validate_widget_values(self, report, json):
        inputs = json.get('widgetValues', [])

        validate_widget_form_data(report['widgets'], inputs)