$(function()
{
    var $editModal = $('#editorElementModal');
    var $editModalBtn = $('#editorElementModalBtn');
    var $editorDeleteBtn = $('#editorDeleteBtn');
    var $editorCanvas = $('#editorCanvas');
    var editCallback;

    var showElementEditModal = function(position, element, callback)
    {
        var $window   = $(window);
        var width     = $editModal.outerWidth();
        var height    = $editModal.outerHeight();
        position.top  = Math.max(0, Math.min($window.height() - height, position.top));
        position.left = Math.max(0, Math.min($window.width()  - width,  position.left));
        $editModal.find('#elementName').val(element.name).parent().removeClass('has-error');
        $editModal.find('#elementCode').val(element.code).attr('readonly', element.codeReadonly ? 'readonly' : null).parent().removeClass('has-error');
        if($editModalBtn.data('zui.tooltip')) $editModalBtn.tooltip('destroy');
        editCallback = callback;
        $editModal.css(position).addClass('show');
        $editModal.find('#elementName').select().focus();
    };

    var isElementReadonly = function(element)
    {
        return element.type === 'start' || element.type === 'stop' || element.getData('readonly') ||(readonlyActions && readonlyActions.indexOf(element.getData('code')) > -1);
    };

    var handleElementActiveChange = function()
    {
        var activeElements = this.getActiveElements();
        var elementsCanDelete = activeElements.filter(function(ele)
        {
            return !isElementReadonly(ele) && (defaultActions.indexOf(ele.getData('code')) === -1 || !ele.data._saved);
        });
        $editorDeleteBtn.attr('disabled', elementsCanDelete.length ? null : 'disabled');
    };

    var getStartStopElements = function(flowchart)
    {
        flowchart = flowchart || getFlowchart();
        var start, stop;
        var nodeList = flowchart.nodeList;
        for(var i = 0; i < nodeList.length; ++i)
        {
            var node = nodeList[i];
            if(node.type === 'start') start = node;
            else if(node.type === 'stop') stop = node;
            if(start && stop) break;
        }
        return {start: start, stop: stop};
    };

    $editModal.on('input change', 'input', function()
    {
        $editModal.find('td.has-error').removeClass('has-error');
        if($editModalBtn.data('zui.tooltip')) $editModalBtn.tooltip('destroy');
    });
    $editModalBtn.on('click', function()
    {
        var $name = $editModal.find('#elementName');
        var $code = $editModal.find('#elementCode');
        var data = {name: $name.val(), code: $code.val()};
        var hasError;
        if(!data.name.length)
        {
            $name.parent().addClass('has-error');
            hasError = true;
        }
        if(!data.code.length)
        {
            $code.parent().addClass('has-error');
            hasError = true;
        }
        if(hasError)
        {
            if(!$editModalBtn.data('zui.tooltip'))
            {
                $editModalBtn.attr('data-toggle', 'tooltip').tooltip(
                {
                    show: true,
                    title: langNameAndCodeRequired,
                    tipClass: 'tooltip-danger',
                    placement: 'top',
                });
            }
            $editModalBtn.tooltip('show');
            return;
        }
        if(editCallback)
        {
            editCallback(data);
            editCallback = null;
        }
        $editModal.removeClass('show');
    });
    $(document).on('mouseup', function(e)
    {
        var $modal = $('#editorElementModal');
        if($modal.hasClass('show') && !$(e.target).closest('#editorElementModal').length)
        {
            editCallback = null;
            $modal.removeClass('show');
        }
    });

    $('.editor-element').on('mousedown', function()
    {
        $(this).tooltip('hide');
    })

    var canvasHeight  = $editorCanvas.height() || ($(window).height() - 145);
    flowchartData.forEach(function(data, index)
    {
        data.codeReadonly = true;

        if(isDefaultData)
        {
            // Adjust positions for default data
            if(data.id === 'start') data.position = {left: 40, top: 20};
            else if(data.id === 'stop') data.position = {left: 40, top: canvasHeight - 60};
            else data.position = {left: 30, top: 20 + index * 100};
        }
        else data._saved = true;
    });

    var flowChartOptions =
    {
        height: 'auto',
        data: flowchartData,
        autoLayoutDirection: 'vert',
        relationLineWidth: 2,
        padding: 20,
        relationLineColor: '#a6aab8',
        relationLineShape: 'polyline',
        defaultNodeType: 'process',
        relationArrowSize: 6,
        allowFreePorts: true,
        nodeMinWidth: 80,
        addFromDrop: '#editorElements',
        nodeHeight: 42,
        activeColor: '#1CA5FF',
        exportDetailPosition: false,
        centerOnCreate: 'horz',

        elementTypes:
        {
            start:
            {
                minWidth: 80,
                shapeStyle: {backgroundColor: '#b0bac1', borderColor: 'transparent'},
                textStyle: {color: '#fff'},
                text: flowchartElementTypes.start
            },
            process:
            {
                minWidth: 100,
                type: 'action',
                shapeStyle: {backgroundColor: '#40caca', borderColor: 'transparent'},
                textStyle: {color: '#fff'},
                text: flowchartElementTypes.process
            },
            decision:
            {
                type: 'diamond',
                style: {minWidth: 70, minHeight: 70},
                shapeStyle: {backgroundColor: '#fad43c', borderColor: 'transparent'},
                textStyle: {color: '#fff'},
                text: flowchartElementTypes.decision
            },
            result:
            {
                type: 'circle',
                shapeStyle: {backgroundColor: '#0964eb', borderColor: 'transparent', minWidth: 70, minHeight: 70},
                textStyle: {color: '#fff'},
                text: flowchartElementTypes.result
            },
            stop:
            {
                minWidth: 80,
                shapeStyle: {backgroundColor: '#b0bac1', borderColor: 'transparent'},
                textStyle: {color: '#fff'},
                text: flowchartElementTypes.stop
            },
        },
        onActiveElement: handleElementActiveChange,
        onUnactiveElement: handleElementActiveChange,
        onAddElement: function(elementsToAdd)
        {
            var flowchart = this;
            var elementsCanAdd = [];
            var startAndStop = getStartStopElements(flowchart);
            elementsToAdd.forEach(function(element)
            {
                var duplicatedStart = element.type === 'start' && startAndStop.start;
                var duplicatedStop = !duplicatedStart && element.type === 'stop' && startAndStop.stop;
                if(!duplicatedStart && !duplicatedStop)
                {
                    elementsCanAdd.push(element);
                }
                if(element.data && element.data['zui.tooltip']) delete element.data['zui.tooltip'];
            });
            if(elementsCanAdd.length < elementsToAdd.length)
            {
                bootbox.alert(langStartOrStopDuplicated);
            }
            return elementsCanAdd.length ? elementsCanAdd : false;
        },
        afterUpdateElement: function()
        {
            var startAndStop = getStartStopElements(this);
            var $editorElements = $('#editorElements');
            $editorElements.find('.editor-element-start')[startAndStop.start ? 'hide' : 'show']();
            $editorElements.find('.editor-element-stop')[startAndStop.stop ? 'hide' : 'show']();
            if(this.created) this.changed = true;
        },
        onChangeElementPosition: function()
        {
            if(this.created) this.changed = true;
        },
        deleteConfirm: function(ele, deleteElement)
        {
            window.bootbox.confirm(langConfirmToDelete.replace('%s', flowchartElementTypes[ele.type]), function(result)
            {
                if(result) deleteElement();
            });
        },
        onDeleteElement: function(elements)
        {
            handleElementActiveChange.call(this);
            elements.forEach(function(ele)
            {
                $('#tooltip-' + ele.id).remove();
            });
            if(this.created) this.changed = true;
        },
        doubleClickToEdit: function(element, flowchart, e)
        {
            var elementType = element.type;
            if(elementType === 'process' && !isElementReadonly(element))
            {
                showElementEditModal({left: e.pageX, top: e.pageY},
                {
                    name: element.getText(),
                    code: element.getData('code'),
                    codeReadonly: element.getData('codeReadonly'),
                }, function(newData)
                {
                    if(!element.codeReadonly) element.setData('code', newData.code);
                    element.setText(newData.name);
                    flowchart.render(element);
                    if(flowchart.created) flowchart.changed = true;
                });
                return true;
            }
            if(elementType === 'start' || elementType === 'stop') return true;
        }
    };
    var flowChart = $editorCanvas.flowChart(flowChartOptions).data('zui.flowChart');
    $editorDeleteBtn.on('click', function()
    {
        flowChart.tryDeleteElement(flowChart.getActiveElements()[0]);
        handleElementActiveChange.call(flowChart);
    });

    $('#saveBtn').on('click', saveFlowchart.bind(this, null, true));

    $('.nextStep, #editorSteps > ul > li > a[href*=ui]').on('click', function()
    {
        var href = $(this).attr('href');
        if(saveFlowchart(function(result)
        {
            if(result) setTimeout(function(){location.href = href;}, 1200);
        })) return false;
    });

    $('#elementCode').on('change', function()
    {
        var $input = $(this);
        $input.val($input.val().replace(/[^a-zA-Z]/g, ''));
    });

    $(window).on('beforeunload', function(e)
    {
        if(getFlowchart().changed)
        {
            e = e || window.event;

            // IE8, Firefox 4
            if(e) e.returnValue = leavePageTip;

            // Chrome, Safari, Firefox 4+, Opera 12+ , IE 9+
            return leavePageTip;
        }
    });

    setAutoHeight();
    $(window).on('resize', setAutoHeight);
});

/**
 * Get FlowChart object instance
 * @return {FlowChart}
 */
function getFlowchart()
{
    return $('#editorCanvas').data('zui.flowChart');
}

/**
 * Save flowChart data
 * @param {function} [callback] Callback for save complete
 * @param {boolean} [force] Force save and ignore changes status
 * @return {Object[]} Flowchart elements list
 */
function saveFlowchart(callback, force)
{
    var flowChart = getFlowchart();
    if(!force && !flowChart.changed) return;

    var data = flowChart.exportData();
    data.forEach(function(elementData) {delete elementData._saved;});
    var link = createLink('workflow', 'ajaxSaveFlowchart', 'module=' + module);
    $.post(link, {'data':JSON.stringify(data)}, function(response)
    {
        try {response = JSON.parse(response);}
        catch(error)
        {
            response = response ? response : unknownError;
            new $.zui.Messager(response,
            {
                type:      'danger',
                icon:      'bell',
                placement: 'center',
                time:       10000
            }).show();
            if(callback) callback(false, response);
            return;
        }

        if(response.result == 'fail')
        {
            if($.type(response.message) == 'object')
            {
                for(var controlID in response.message)
                {
                    var $element = $('#editorCanvas-' + controlID);
                    var tooltip = $element.data('zui.tooltip');
                    if(tooltip && tooltip.show)
                    {
                        tooltip.hoverState = 'in';
                        tooltip.show(response.message[controlID]);
                    }
                    else $element.attr('data-toggle', 'tooltip').tooltip({tipClass: 'tooltip-danger', tipId: 'tooltip-' + controlID}).tooltip('show', response.message[controlID]);
                }
            } else if($.type(response.message) == 'string') bootbox.alert(response.message);

            if(callback) callback(false, response);
        }
        else
        {
            var flowChartData = JSON.parse(response.flowchart);
            flowChartData.forEach(function(element)
            {
                element._saved = true;
            });
            flowChart.resetData(flowChartData);

            flowChart.changed = false;
            $('#saveBtn').popover(
            {
                trigger:   'manual',
                content:   response.message,
                tipClass:  'popover-success popover-form-result',
                placement: 'left'
            }).popover('show');

            setTimeout(function(){$('#saveBtn').popover('destroy')}, 2000);

            if($.isFunction(callback)) callback(true, response);
        }
    });
    return true;
}
