async function generate()
{
    if(validateForm())
    {
        const fileName  = $('#fileName').val();
        const extension = $('#extension').val();

        var sections = [];

        if(window.methodMap)
        {
            const methods = $('#methods').val();
            for(var methodID of methods)
            {
                sections.push(await createSection(methodID));
            }
        }

        if(window.resultMap)
        {
            const results = $('#results').val().sort(function(a, b){ return a - b; });
            var resultArr = [];

            results.forEach(function(item)
            {
                var id     = parseInt(item);
                var result = window.resultMap.get(id);

                resultArr.push(result);
                if(result.children)
                {
                    for(var i = 1; i <= result.children; i ++)
                    {
                        var children = window.resultMap.get(id + i);
                        resultArr.push(children);
                    }
                }
            });

            window.methodInfo.results = resultArr;
            sections.push(await createSection(0, window.methodInfo));
        }


        const doc = new docx.Document({ sections: sections });

        const blob = await docx.Packer.toBlob(doc);
        console.log(blob);
        saveAs(blob, fileName);
        console.log("Document created successfully");

        $.zui.closeModal();
    }
}

async function createSection(methodID, results = '')
{
    var section = new Object();
    section.properties = new Object();
    section.children   = [];

    var result = results ? results : window.methodMap.get(parseInt(methodID));

    if(result.title) section.children.push(new docx.Paragraph({ text: result.title, heading: docx.HeadingLevel.HEADING_3, }));
    if(result.results)
    {
        for (var item of result.results)
        {
            section.children.push(new docx.Paragraph({ text: '' }));
            if(item.type == 'table')
            {
                if(item.title) section.children.push(new docx.Paragraph({ text: item.title, heading: docx.HeadingLevel.HEADING_5, }));
                if(item.desc)
                {
                    var desc = item.desc.replace(/<\/?.+?\/?>/g, '');
                    desc = desc.replace(/&nbsp;/g, '');
                    section.children.push(new docx.Paragraph({ text: desc }));
                }

                var tableRow   = [];
                var thChildren = [];

                item.data.columns.forEach(function(column)
                {
                    var thTitle = column == null ? '' : column;
                    thTitle     = typeof thTitle.label == 'undefined' ? thTitle : thTitle.label;
                    thTitle     = thTitle == null ? '' : thTitle.toString();

                    thChildren.push(new docx.TableCell({ children: [new docx.Paragraph(thTitle)] }));
                });

                tableRow.push(new docx.TableRow({ children: thChildren}));

                item.data.data.forEach(function(rowData)
                {
                    var tdChildren = [];
                    rowData.forEach(function(data)
                    {
                        var tdData = data
                        tdData     = tdData == null ? '' : data.toString();

                        tdChildren.push(new docx.TableCell({ children: [new docx.Paragraph(tdData)] }));
                    });
                    tableRow.push(new docx.TableRow({ children: tdChildren }));
                });

                section.children.push(new docx.Table({ rows: tableRow }));
            }

            if(item.type == 'text')
            {
                if(item.title) section.children.push(new docx.Paragraph({ text: item.title, heading: docx.HeadingLevel.HEADING_5, }));
                if(item.data.content)
                {
                    var content = item.data.content.replace(/<\/?.+?\/?>/g, '');
                    content = content.replace(/&nbsp;/g, '');
                    section.children.push(new docx.Paragraph({ text: content }));
                }
            }

            if(item.type == 'chart')
            {
                if(item.title) section.children.push(new docx.Paragraph({ text: item.title, heading: docx.HeadingLevel.HEADING_5, }));
                const gd = await Plotly.newPlot('plotly_div', eval(item.data.data), eval(item.data.layout));
                const res = await Plotly.toImage(gd,{height:500,width:1000});

                var image = [];
                image.push(new docx.ImageRun({ data: res, transformation: { width: 400, height: 200, } }));
                section.children.push(new docx.Paragraph({ children: image }));
            }
        }
    }

    return section;
}

function isEmptyValue(val)
{
    return val === null || val === undefined || (typeof val === 'string' && !val.trim().length);
}

function validateForm()
{
    if(window.methodMap) var varList  = ['methods', 'fileName'];
    if(window.resultMap) var varList  = ['results', 'fileName'];

    for(item of varList)
    {
        var $control = $('#' + item);
        var $label   = $('#' + item + 'Label');
        if($label.length) $label.remove();

        if(isEmptyValue($control.val()))
        {
            $label = '<div id="' + item + 'Label" class="text-danger help-text">' + window.notempty.replace('%s', window[item]) + '</div>';
            $control.closest('td').append($label);
            return false;
        }
    }
    return true;
}

$(function()
{
    if(window.methodList)
    {
        var methodMap = new Map();
        window.methodList.forEach(function(method)
        {
            methodMap.set(method.id, method);
        });
        window.methodMap = methodMap;
    }

    if(window.methodInfo)
    {
        var i = 0;
        var resultMap = new Map();
        window.methodInfo.results.forEach(function(result)
        {
            resultMap.set(i, result);
            i ++;
        });
        window.resultMap = resultMap;
    }

    $('.picker-column-type').picker(
    {
        onUpdateSelectOption: function($option, picker)
        {
            var text = $option.text();
            var val = $option.val();
            if (!text.length && !val.length) {
                return;
            }
            var options = picker.options;
            var item = {};

            if(/:[FISD]$/.test(text))
            {
                var strArr = text.split(':');
                text = strArr[0];
                item.dtype = strArr[1];
            }

            item[options.valueKey] = val;
            item[options.textKey] = text;
            item[options.keysKey] = $option.data(options.keysKey);
            return item;
        },
        optionRender: function($option, item)
        {
            $option.attr('data-dtype', item.dtype);
        },
        selectionTextRender: function($selection, text, item)
        {
            $selection.text(text).attr('data-dtype', item.dtype);
        }
    });

    $('#results').next('.picker').on('click', function()
    {
        var $label = $('#resultsLabel');
        if($label.length) $label.remove();
    });
    $('#methods').next('.picker').on('click', function()
    {
        var $label = $('#methodsLabel');
        if($label.length) $label.remove();
    });
    $('#fileName').on('click', function()
    {
        var $label = $('#fileNameLabel');
        if($label.length) $label.remove();
    });

});
