# Path: diva/widgets.py
# 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
# 
# 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 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


from flask import render_template
from .widgets import parse_widget_form_data, validate_widget_form_data, widgets_template_data
from functools import singledispatch
from flask import send_file, jsonify
import base64
        """
        user_func must be like appy_func followed by widget-set args
        """
        register_widget_util(ui_name, some_type, lambda val: widgets, user_func)
        return user_func

    return decorator

def register_widget_util(ui_name, some_type, gen_widgets, apply_with_params):
    """
    ui_name: the name of this utility in the UI

    some_type: this utility will appear in the sidebar whenever your view function
    returns a value of type ``some_type``

    gen_widgets(val): a function that takes the report value (of the specified type), and 
    returns a list of widgets. These widget values will be passed like:
    ``apply_with_params(val, *widget_values)``.

    apply_with_params: a function that takes the report value (of the specified type) as 
    its first parameter, followed by a list of arguments that are given by widgets. The function must
    return the result of a call to ``file_response``
    """
    def gen_html(val):
        widgets = gen_widgets(val)
        widget_data = widgets_template_data(widgets)
        return render_template('utility_button.html', name=ui_name, widgets=widget_data)

    def apply_util(val, data):
        widgets = gen_widgets(val)

# Path: diva/widgets.py
# 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
# 
# 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 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


# Path: diva/utilities.py
from flask import render_template
from .widgets import parse_widget_form_data, validate_widget_form_data, widgets_template_data
from functools import singledispatch
from flask import send_file, jsonify
import base64

        """
        user_func must be like appy_func followed by widget-set args
        """
        register_widget_util(ui_name, some_type, lambda val: widgets, user_func)
        return user_func

    return decorator

def register_widget_util(ui_name, some_type, gen_widgets, apply_with_params):
    """
    ui_name: the name of this utility in the UI

    some_type: this utility will appear in the sidebar whenever your view function
    returns a value of type ``some_type``

    gen_widgets(val): a function that takes the report value (of the specified type), and 
    returns a list of widgets. These widget values will be passed like:
    ``apply_with_params(val, *widget_values)``.

    apply_with_params: a function that takes the report value (of the specified type) as 
    its first parameter, followed by a list of arguments that are given by widgets. The function must
    return the result of a call to ``file_response``
    """
    def gen_html(val):
        widgets = gen_widgets(val)
        widget_data = widgets_template_data(widgets)
        return render_template('utility_button.html', name=ui_name, widgets=widget_data)

    def apply_util(val, data):
        widgets = gen_widgets(val)

        validate_widget_form_data(widgets, data)