(function ($, undefined) {

    var codemirrors = {},
        index = $('.js-form-field-container .js-form-field').length + 1,
        form = $('.js-form-serialize');

    $(function () {

        // Define "twig" mode, a mode with html and twig
        // @todo figure out how to get jinja2 highlighting to work
        // inside multiplexer
        CodeMirror.defineMode("twig", function (config) {
            return CodeMirror.multiplexingMode(
                CodeMirror.getMode(config, "text/html"),
                { open: "{{", close: "}}", mode: CodeMirror.getMode(config, "jinja2"), parseDelimiters :  true },
                { open: "{#", close: "#}", mode: CodeMirror.getMode(config, "jinja2"), parseDelimiters :  true },
                { open: "{%", close: "%}", mode: CodeMirror.getMode(config, "jinja2"), parseDelimiters :  true }
            );
        });

        /**
         * Create CodeMirror
         *
         * @param {DOMElement} el Element
         */
        var fnCreateCodeMirror = function(el) {
            var $el = $(el),
                $copy_el = $('#' + $el.attr('data-copy')),
                id = $el.attr('id'),
                mode = $el.attr('data-mode'),
                codemirror_el;

            codemirror_el = $('<div />').insertBefore($el);
            codemirrors[id] = CodeMirror.MergeView(codemirror_el[0], {
                value : $el.val(),
                orig : '' + $copy_el.val(),
                theme: 'monokai',
                mode: mode,
                highlightDifferences : true,
                connect : null,
                lineNumbers: true
            });

            $el.css({ 'display' : 'none' });
            codemirrors[id].editor().setSize(null, '600px');
            codemirrors[id].rightOriginal().setSize(null, '600px');
            $(codemirrors[id].wrap).css({ height : '600px' });
        };

        /**
         * Refresh CodeMirror
         *
         * @param {DOMElement} el Element
         */
        var fnRefreshCodeMirror = function(el) {
            var $el = $(el), id = $el.attr('id');
            if (codemirrors[id] !== undefined) {
                codemirrors[id].editor().refresh();
                codemirrors[id].rightOriginal().refresh();
                $(codemirrors[id].wrap).css({ height : '600px' });
            }
        };

        /**
         * Save CodeMirror content to textfield
         *
         * @param {DOMElement} el Element
         */
        var fnSaveCodeMirrorToTextField = function(el) {
            var $el = $(el), $copy_el = $('#' + $el.attr('data-copy')), id = $el.attr('id');
            if (codemirrors[id] !== undefined) {
                $el.val(codemirrors[id].editor().getValue());
                $copy_el.val(codemirrors[id].rightOriginal().getValue());
            }
        };



        // Save content to textarea before submit and serializing
        form.on('submit beforeserialize', function() {
            form.find('textarea.codemirror[id][data-mode]').each(function () {
                fnSaveCodeMirrorToTextField(this);
            });
        });

        

        // Initialiseer CodeMirror
        $('textarea.codemirror[id][data-mode][data-copy]').each(function () {
            fnCreateCodeMirror(this);
        });

        // Handel wisselen van tabs af
        $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
            var panel = $($(e.target).attr('href'));
            panel.find('textarea.codemirror[id][data-mode][data-copy]').each(function () {
                fnRefreshCodeMirror(this);
            });
        });

        /**
         * Bepaal tekstweergave voor veld
         *
         * @param {DOMElement} el 
         * @returns {String}
         */
        var getTextValue = function (el) {
            if (el.is('select')) {
                if (el.find('option:selected').length > 0) {
                    return el.find('option:selected').text();
                } else {
                    return '';
                }
            }
            return el.val();
        };

        /**
         * Voeg event listeners toe aan container
         *
         * @param {DOMElement} container
         */
        var addFieldListeners = function (container) {
            container.find('[data-source]').each(function () {
                var el = $(this), target = $(el.attr('data-source'));
                el.text(getTextValue(target));
                target.on('change keypress keyup', function () {
                    el.text(getTextValue(target));
                });
            });
        };

        /**
         * Update volgorde veld
         */
        var updateVolgorde = function () {
            var val = 1;
            $('.js-form-field-volgorde').each(function () {
                $(this).val(val).trigger('change');
                val++;
            });
        };

        // Update current items, add listeners
        updateVolgorde();
        $('.js-form-field').each(function () {
            addFieldListeners($(this));
        });

        // Make fields sortable
        $('.js-form-field-container').sortable({
            items: "> .js-form-field"
        });

        // Update volgorde after sorting
        $('.js-form-field-container').on('sortupdate', function () {
            updateVolgorde();
        });

        // Delete field
        $('.js-form-field-container').on('click', '.js-form-field-del', function (e) {
            var el = $(this), message = el.attr('data-confirm');
            e.preventDefault();
            if (confirm(message)) {
                el.parents('.js-form-field').remove();
                updateVolgorde();
                $('.js-form-field-container').sortable('refresh');
            }
        });

        // Add Field
        $('.js-form-field-add').on('click', function () {
            var container = $('.js-form-field-container'),
                    prototype = container.attr('data-prototype'),
                    $prototype;
            $prototype = $(prototype.replace(/__name__/g, index));
            index++;

            container.append($prototype);
            updateVolgorde();
            addFieldListeners($prototype);

            $('.js-form-field-container').sortable('refresh');
        });


        $('button[data-url][data-confirm][data-target]').on('click', function () {
            var el = $(this),
                    url = el.attr('data-url'),
                    target = el.attr('data-target'),
                    message = el.attr('data-confirm'),
                    xhr;

            if (codemirrors[target] == undefined) {
                return;
            }

            xhr = $.ajax({
                type: 'POST',
                url: url,
                data: form.serialize()
            });

            xhr.fail(function() {
                alert("Er is een fout opgetreden tijdens het laden van de HTML");
            });

            xhr.done(function (data) {
                if (data.html != undefined) {
                    codemirrors[target].rightOriginal().setValue(data.html);
                    codemirrors[target].rightOriginal().refresh();
                    if (codemirrors[target].editor().getValue() == '' || !confirm(message)) {
                        codemirrors[target].editor().setValue(data.html);
                    }
                }
            });


        });


    });

})(jQuery);