/**
 *  System signature module
 */

define([
    'jquery',
    'app/init',
    'app/util',
    'app/render',
    'bootbox'
], function($, Init, Util, Render, bootbox) {
    'use strict';

    var config = {
        // module info
        moduleClass: 'pf-module',                                               // class for each module

        // system signature module
        systemSigModuleClass: 'pf-sig-table-module',                            // module wrapper

        // tables
        tableToolsClass: 'pf-table-tools',                                      // class for table toolbar
        tableToolsActionClass: 'pf-table-tools-action',                         // class for table toolbar action

        // dialogs
        signatureReaderDialogId: 'pf-signature-reader-dialog',                  // id for signature reader dialog

        // signature progress bar
        signatureScannedProgressBarClass: 'pf-system-progress-scanned',         // class for signature progress bar

        // toolbar
        sigTableClearButtonClass: 'pf-sig-table-clear-button',                  // class for "clear" signatures button

        // signature table
        sigTableClass: 'pf-sig-table',                                          // Table class for all Signature Tables
        sigTablePrimaryClass: 'pf-sig-table-primary',                           // class for primary sig table
        sigTableSecondaryClass: 'pf-sig-table-secondary',                       // class for secondary sig table
        sigTableRowIdPrefix: 'pf-sig-table-row-',                               // id prefix for a table row <tr>
        sigTableEditText: 'pf-sig-table-edit-text',                             // class for editable fields (text)
        sigTableEditSigNameInput: 'pf-sig-table-edit-name-input',               // class for editable fields (input)
        sigTableEditSigGroupSelect: 'pf-sig-table-edit-group-select',           // class for editable fields (sig group)
        sigTableEditSigTypeSelect: 'pf-sig-table-edit-type-select',             // class for editable fields (sig type)
        sigTableEditSigDescriptionTextarea: 'pf-sig-table-edit-desc-text',      // class for editable fields (sig description)
        sigTableCreatedCellClass: 'pf-sig-table-created',                       // class for "created" cells
        sigTableUpdatedCellClass: 'pf-sig-table-updated',                       // class for "updated" cells
        sigTableActionButtonClass: 'pf-sig-table-action-button',                // class for row action button

        sigTableCounterClass: 'pf-table-counter-cell',                          // class for "counter" cells
        sigTableActionCellClass: 'pf-table-action-cell',                        // class for "action" cells


        // animation
        animationPulseSuccessClass: 'pf-animation-pulse-success',               // animation class
        animationPulseWarningClass: 'pf-animation-pulse-warning',               // animation class

        // xEditable
        editableDiscriptionInputClass: 'pf-editable-description'                // class for "description" textarea
    };

    // lock Signature Table update temporary (until. some requests/animations) are finished
    var disableTableUpdate = true;

    // disable "copy&paste" from clipboard (until  request finished)
    var disableCopyFromClipboard = false;

    // cache for dataTable object
    var signatureTable = null;

    // empty signatureData object -> for "add row" table
    var emptySignatureData = {
        id: 0,
        name: '',
        groupId: 0,
        typeId: 0,
        description: '',
        created: {
            created: null
        },
        updated: {
            updated: null
        }
    };

    var fullSignatureOptions = {
        action: 'delete',
        actionClass: ['fa-close', 'txt-color', 'txt-color-redDarker'].join(' ')
    };

    // empty signatureData row Options
    var emptySignatureOptions = {
        action: 'add',
        actionClass: ['fa-plus'].join(' ')
    };

    var sigNameCache = {};                                                      // cache signature names

    /**
     * collect all data of all editable fields in a signature table
     * @returns {Array}
     */
    var getSignatureTableData = function(){

        var signatureTableApi = signatureTable.api();

        var tableData = [];

        signatureTableApi.rows().eq(0).each(function(idx){

            var row = signatureTableApi.row(idx);
            // default row data
            var defaultRowData = row.data();
            var rowElement = row.nodes().to$();

            if(defaultRowData.id > 0){
                // get all editable fields per row
                var editableFields = rowElement.find('.editable');

                if(editableFields.length > 0){
                    var values = $(editableFields).editable('getValue');

                    // convert to lower for better compare options
                    values.name = values.name.toLowerCase();

                    // add pk for this row
                    values.id = defaultRowData.id;

                    // add updated for this row
                    values.updated = defaultRowData.updated;

                    // add row index
                    values.index = idx;

                    tableData.push( values );
                }
            }

        });

        return tableData;
    };

    /**
     * updates a single cell with new data (e.g. "updated" cell)
     * @param rowElement
     * @param cellIndex
     * @param data
     */
    var updateSignatureCell = function(rowElement, cellIndex, data){

        var signatureTableApi = signatureTable.api();
        var rowIndex = signatureTableApi.row( rowElement ).index();

        var updateCell = signatureTableApi.cell( rowIndex, cellIndex );
        var updateCellElement = updateCell.nodes().to$();

        if(cellIndex === 6){
            // clear existing counter interval
            clearInterval( updateCellElement.data('interval') );
        }

        // set new value
        updateCell.data( data ).draw();

        if(cellIndex === 6){
            updateCellElement.initTimestampCounter();
        }
    };

    /**
     * Updates a signature table, changes all signatures where name matches
     * add all new signatures as a row
     *
     * @param signatureDataOrig
     * @param deleteOutdatedSignatures -> set to "true" if signatures should be deleted that are not included in "signatureData"
     */
    $.fn.updateSignatureTable = function(signatureDataOrig, deleteOutdatedSignatures){

        // check if table update is allowed
        if(disableTableUpdate === true){
            return;
        }

        // clone signature array because of further manipulation
        var signatureData = $.extend([], signatureDataOrig);

        // disable update until function is ready;
        disableTableUpdate = true;

        var moduleElement = $(this);

        // get signature table API
        var signatureTableApi = signatureTable.api();

        // get current system data
        var currentSystemData = Util.getCurrentSystemData();


        var tableData = getSignatureTableData();

        var notificationCounter = {
            added: 0,
            changed: 0,
            deleted: 0
        };

        for(var i = 0; i < signatureData.length; i++){
            for(var j = 0; j < tableData.length; j++){
                if(signatureData[i].id === tableData[j].id){

                    // check if row has updated
                    if(signatureData[i].updated.updated > tableData[j].updated.updated){

                        // row element to remove
                        var currentRowElement = signatureTableApi.row(tableData[j].index).nodes().to$();

                        // hide open editable fields on the row before removing them
                        currentRowElement.find('.editable').editable('destroy');

                        // remove "old" row
                        signatureTableApi.row(currentRowElement).remove().draw();

                        // and add "new" row
                        var changedRowElement = addSignatureRow(currentSystemData.systemData, signatureData[i], false);

                        // highlight
                        changedRowElement.pulseTableRow('changed');

                        notificationCounter.changed++;
                    }

                    // remove signature data -> all left signatures will be added
                    signatureData.splice(i, 1);
                    i--;

                    // remove signature data -> all left signatures will be deleted
                    tableData.splice(j, 1);
                    j--;

                    break;
                }
            }
        }

        // delete signatures ====================================================
        if(deleteOutdatedSignatures === true){

            // callback function after row deleted
            var toggleTableRowCallback = function(tempRowElement){
                // hide open editable fields on the row before removing them
                tempRowElement.find('.editable').editable('destroy');

                // delete signature row
                signatureTableApi.row(tempRowElement).remove().draw();
            };

            for(var l = 0; l < tableData.length; l++){
                var rowElement = signatureTableApi.row(tableData[l].index).nodes().to$();
                rowElement.toggleTableRow(toggleTableRowCallback);
                notificationCounter.deleted++;
            }
        }

        // add new signatures ===================================================
        for(var k = 0; k < signatureData.length; k++){
            // and add "new" row
            var newRowElement = addSignatureRow(currentSystemData.systemData, signatureData[k], false);

            // highlight
            newRowElement.pulseTableRow('added');

            notificationCounter.added++;
        }


        // show notification ====================================================
        if(
            notificationCounter.added > 0 ||
            notificationCounter.changed > 0 ||
            notificationCounter.deleted > 0
        ){
            // update signature bar
            moduleElement.updateScannedSignaturesBar({showNotice: true});

            // show Notification
            var notification = notificationCounter.added + ' added<br>';
            notification += notificationCounter.changed + ' changed<br>';
            notification += notificationCounter.deleted + ' deleted<br>';
            Util.showNotify({title: 'Signatures updated', text: notification, type: 'success'});

            // wait until add/remove animations are finished before enable table for auto update again
            setTimeout(function(){ disableTableUpdate = false; }, 2000);
        }else{
            // enable table update
            disableTableUpdate = false;
        }


    };

    /**
     * highlight jquery elements
     * add/remove css class for keyframe animation
     * @returns {any|JQuery|*}
     */
    $.fn.pulseTableRow = function(status){

        var animationClass = '';
        switch(status){
            case 'added':
                animationClass = config.animationPulseSuccessClass;
                break;
            case 'changed':
                animationClass = config.animationPulseWarningClass;
                break;
        }

        return this.each(function(){
            var element = $(this);
            element.addClass( animationClass );

            var timer = setTimeout(
                function() {
                    element.removeClass( animationClass );

                    clearTimeout( timer );
                }, 3000);
        });
    };

    /**
     * update Progressbar for all scanned signatures in a system
     * @param options
     */
    $.fn.updateScannedSignaturesBar = function(options){

        var moduleElement = $(this);

        // get progress bar
        var progressBarWrapper = moduleElement.find('.' + config.signatureScannedProgressBarClass);
        var progressBar = $(progressBarWrapper).find('.progress-bar');
        var progressBarLabel = $(progressBarWrapper).find('.progress-label-right');

        var tableData = getSignatureTableData();

        var percent = 0;
        var progressBarType = 'progress-bar-danger';

        if(tableData){
            var sigCount = tableData.length;
            var sigIncompleteCount = 0;
            // check for  signatures without "groupId" -> these are un scanned signatures

            for(var i = 0; i < tableData.length; i++){
                var groupId = parseInt(tableData[i].groupId);
                if(groupId === 0){
                    sigIncompleteCount++;
                }
            }

            if(sigCount > 0){
                percent = 100 - Math.round( 100 / sigCount * sigIncompleteCount );
            }

            if(percent < 30){
                progressBarType = 'progress-bar-danger' ;
            }else if(percent < 100){
                progressBarType = 'progress-bar-warning';
            }else{
                progressBarType = 'progress-bar-success';
            }
        }

        setTimeout(
            function() {
                progressBarLabel.text(percent + '%');
                progressBar.removeClass().addClass('progress-bar').addClass(progressBarType);
                progressBar.attr('aria-valuenow', percent);
                progressBar.css({width: percent + '%'});

                var notification = (sigCount - sigIncompleteCount) + ' / ' + sigCount + ' (' + percent + '%) signatures scanned';

                // show notifications
                if(options.showNotice !== false){
                    if(percent < 100){
                        Util.showNotify({title: 'Unknown signatures', text: notification, type: 'info'});
                    }else{
                        Util.showNotify({title: 'System is scanned', text: notification, type: 'success'});
                    }
                }

            }, 100);

    };

    /**
     * open "signature reader" dialog for signature table
     * @param systemData
     */
    $.fn.showSignatureReaderDialog = function(systemData){

        var moduleElement = $(this);

        var data = {
            id: config.signatureReaderDialogId
        };

        requirejs(['text!templates/modules/signature_reader_dialog.html', 'mustache'], function(template, Mustache) {

            var content = Mustache.render(template, data);

            var signatureReaderDialog = bootbox.dialog({
                title: 'Signature reader',
                message: content,
                buttons: {
                    close: {
                        label: 'cancel',
                        className: 'btn-default',
                        callback: function(){
                            $(signatureReaderDialog).modal('hide');
                        }
                    },
                    success: {
                        label: '<i class="fa fa-clipboard fa-fw"></i>&nbsp;update signatures',
                        className: 'btn-success',
                        callback: function () {
                            // get form Values
                            var form = $('#' + config.signatureReaderDialogId).find('form');

                            var formData = $(form).getFormValues();

                            moduleElement.updateSignatureTableByClipboard(systemData, formData.clipboard);
                        }
                    }
                }
            });

            // dialog shown event
            signatureReaderDialog.on('shown.bs.modal', function(e) {
                // set focus on sig-input textarea
                signatureReaderDialog.find('textarea').focus();
            });


        });
    };

    /**
     * updates the signature table with all signatures pasted into the "signature reader" dialog
     * -> Hint: copy&paste signature data (without any open dialog) will add signatures as well
     * @param systemData
     * @param clipboard data stream
     */
    $.fn.updateSignatureTableByClipboard = function(systemData, clipboard){

        // check if copy&paste is enabled
        if( !disableCopyFromClipboard ){
            var moduleElement = $(this);

            // parse input stream
            var signatureData = parseSignatureString(systemData, clipboard);

            if(signatureData.length > 0){
                // save signature data

                // lock update function until request is finished
                disableTableUpdate = true;

                // lock copy during request (prevent spamming (ctrl + c )
                disableCopyFromClipboard = true;

                var requestData = {
                    signatures: signatureData
                };

                $.ajax({
                    type: 'POST',
                    url: Init.path.saveSignatureData,
                    data: requestData,
                    dataType: 'json'
                }).done(function(responseData){
                    disableTableUpdate = false;

                    // updates table with new/updated signature information
                    moduleElement.updateSignatureTable(responseData.signatures, false);
                }).fail(function( jqXHR, status, error) {
                    var reason = status + ' ' + error;
                    Util.showNotify({title: jqXHR.status + ': Update signatures', text: reason, type: 'warning'});
                    $(document).setProgramStatus('problem');
                }).always(function() {
                    disableTableUpdate = false;
                    disableCopyFromClipboard = false;
                });
            }
        }
    };

    /**
     * parses a copy&paste string from ingame scanning window and parses it
     * @param systemData
     * @param clipboard
     * @returns {Array}
     */
    var parseSignatureString = function(systemData, clipboard){

        var signatureData = [];

        var signatureRows = clipboard.split(/\r\n|\r|\n/g);

        var signatureGroupOptions = Util.getSignatureGroupInfo('name');

        for(var i = 0; i < signatureRows.length; i++){
            var rowData = signatureRows[i].split(/\t/g);

            if(rowData.length === 6){

                // check if sig Type = anomaly or combat site
                if(
                    rowData[1] === 'Cosmic Anomaly' ||
                    rowData[1] === 'Cosmic Signature'
                ){

                    var sigGroup = $.trim(rowData[2]).toLowerCase();
                    var sigDescription = $.trim(rowData[3]);
                    var sigGroupId = 0;
                    var typeId = 0;

                    // get groupId by groupName
                    for (var prop in signatureGroupOptions) {
                        if(signatureGroupOptions.hasOwnProperty(prop)){
                            if(signatureGroupOptions[prop] === sigGroup){
                                sigGroupId = parseInt( prop );
                                break;
                            }
                        }
                    }

                    // wormhole type cant be extracted from signature string -> skip function call
                    if(sigGroupId !== 5){
                        // try to get "typeId" by description string
                        typeId = Util.getSignatureTypeIdByName( systemData, sigGroupId, sigDescription );

                        // set signature name as "description" if signature matching failed
                        sigDescription = (typeId === 0) ? sigDescription : '';
                    }else{
                        sigDescription = '';
                    }

                    // map array values to signature Object
                    var signatureObj = {
                        systemId: systemData.id,
                        name: $.trim( rowData[0].substr(0, 3) ).toLowerCase(),
                        groupId: sigGroupId,
                        typeId: typeId,
                        description: sigDescription
                    };

                    signatureData.push(signatureObj);
                }
            }
        }

        return signatureData;
    };

    /**
     * get a labeled button
     * @param options
     * @returns {*|jQuery}
     */
    var getLabledButton = function(options){

        var buttonClasses = ['btn', 'btn-sm', 'btn-labeled'];

        switch(options.type){
            case 'default':
                buttonClasses.push('btn-default');
                break;
            case 'primary':
                buttonClasses.push('btn-primary');
                break;
            case 'danger':
                buttonClasses.push('btn-danger');
                break;
        }

        // add optional classes
        if(options.classes){
            buttonClasses = buttonClasses.concat(options.classes);
        }


        var buttonElement = $('<button>', {
            class: buttonClasses.join(' '),
            type: 'button',
            html: '&nbsp;' + options.label + '&nbsp;&nbsp;'
        }).on('click', function(e){
            options.onClick(e);
        }).prepend(
            $('<span>', {
                class: 'btn-label'
            }).prepend(
                $('<i>', {
                    class: ['fa', options.icon, 'fa-fw'].join(' ')
                })
            )
        );

        // add optional badge
        if(options.badge){
            buttonElement.append(
                $('<span>', {
                    class: ['badge'].join(' '),
                    text: options.badge.label
                })
            );
        }

        return buttonElement;
    };

    /**
     * draw signature table toolbar (add signature button, scan progress bar
     * @param systemData
     */
    $.fn.drawSignatureTableToolbar = function(systemData){

        var moduleElement = $(this);

        // add toolbar buttons for table -------------------------------------
        var tableToolbar = $('<div>', {
            class: config.tableToolsClass
        }).append(
            getLabledButton({
                type: 'primary',
                label: 'add',
                icon: 'fa-plus',
                onClick: function(e){
                    // show "add sig" div
                    var toolsElement = $(e.target).parents('.' + config.moduleClass).find('.' + config.tableToolsActionClass);

                    // set toggle animation
                    if(toolsElement.is(':visible')){
                        toolsElement.velocity('stop').velocity('reverse');
                    }else{
                        toolsElement.velocity('stop').velocity({
                            opacity: 1,
                            height: '75px'
                        },{
                            duration: 150,
                            display: 'block',
                            visibility: 'visible'
                        });
                    }
                }
            })
        ).append(
            getLabledButton({
                type: 'primary',
                label: 'signature reader',
                icon: 'fa-clipboard',
                onClick: function(){
                    moduleElement.showSignatureReaderDialog(systemData);
                }
            })
        ).append(
            getLabledButton({
                type: 'default',
                label: 'select all',
                icon: 'fa-check-square',
                onClick: function(){
                    var allRows = getRows(signatureTable);
                    var selectedRows = getSelectedRows(signatureTable);
                    var allRowElements = allRows.nodes().to$();

                    if(allRows.data().length === selectedRows.data().length){
                        allRowElements.removeClass('selected');
                    }else{
                        allRowElements.addClass('selected');
                    }

                    // check delete button
                    checkDeleteSignaturesButton();
                }
            })
        ).append(
            getLabledButton({
                type: 'danger',
                classes: [config.sigTableClearButtonClass, 'pull-right'],
                label: 'delete',
                icon: 'fa-close',
                badge: {
                    label: '0'
                },
                onClick: function(){
                    // delete all rows

                    var selectedRows = getSelectedRows(signatureTable);

                    bootbox.confirm('Delete ' + selectedRows.data().length + ' signature?', function(result) {
                        if(result){
                            deleteSignatures(selectedRows);
                        }
                    });
                }
            })
        );

        moduleElement.append(tableToolbar);

        // add toolbar action for table ================================================================================
        var tableToolbarAction = $('<div>', {
            class: config.tableToolsActionClass
        });

        // create "empty table for new signature
        var table = $('<table>', {
            class: ['display', 'compact', 'nowrap', config.sigTableClass, config.sigTableSecondaryClass].join(' ')
        });

        tableToolbarAction.append(table);

        tableToolbar.after(tableToolbarAction);

        var signatureData = formatSignatureData(systemData, [emptySignatureData], emptySignatureOptions);
        table.dataTable( {
            data: signatureData,
            paging: false,
            ordering: false,
            info: false,
            searching: false
        } );

        table.makeEditable(systemData);

        // scanned signatures progress bar =============================================================================
        var moduleConfig = {
            name: 'form/progress',
            position: tableToolbar,
            link: 'before'
        };

        var moduleData = {
            label: true,
            wrapperClass: config.signatureScannedProgressBarClass,
            class: ['progress-bar-success'].join(' '),
            percent: 0,
            headline: 'System scanned',
            headlineRight: ' ' // will be updated by js
        };

        Render.showModule(moduleConfig, moduleData);

        // event listener for global "paste" signatures into the page ==================================================
        $(document).off('paste').on('paste', function(e){

            // do not read clipboard if pasting into form elements
            if(
                $(e.target).prop('tagName').toLowerCase() !== 'input' &&
                $(e.target).prop('tagName').toLowerCase() !== 'textarea'
            ){
                var clipboard = (e.originalEvent || e).clipboardData.getData('text/plain');
                moduleElement.updateSignatureTableByClipboard(systemData, clipboard);
            }
        });
    };

    /**
     * make a table or row editable
     * @param systemInfoData
     */
    $.fn.makeEditable = function(systemData){

        // table element OR row element
        var tableElement = $(this);

        // find editable fields
        var sigNameFields = tableElement.find('.' + config.sigTableEditSigNameInput);
        var sigGroupFields = tableElement.find('.' + config.sigTableEditSigGroupSelect);
        var sigTypeFields = tableElement.find('.' + config.sigTableEditSigTypeSelect);
        var sigDescriptionFields = tableElement.find('.' + config.sigTableEditSigDescriptionTextarea);

        // jump to "next" editable field on save
        var openNextEditDialogOnSave = function(fields){
            fields.on('save', function(e, a){

                var currentField = $(this);

                setTimeout(function() {
                    var nextField = getNextEditableField(currentField);
                    nextField.editable('show');

                    // update scanning progressbar if sig "type" has changed AND
                    // the current field is in the "primary" table (not the "add" new sig row)
                    if(
                        $(e.target).hasClass(config.sigTableEditSigGroupSelect) &&
                        tableElement.hasClass(config.sigTablePrimaryClass)
                    ){
                        currentField.parents('.' + config.moduleClass).updateScannedSignaturesBar({showNotice: true});
                    }
                }, 200);
            });
        };

        // helper function - get the next editable field in next table column
        var getNextEditableField = function(field){
            var nextEditableField = $(field).closest('td').next().find('.editable');
            return $(nextEditableField);
        };

        /**
         * add map/system specific data for each editable field in the sig-table
         * @param params
         * @returns {*}
         */
        var modifyFieldParamsOnSend = function(params){
            params.systemId = systemData.id;

            return params;
        };

        // set global xEditable options for all table fields
        $.extend($.fn.editable.defaults, {
            url: Init.path.saveSignatureData,
            dataType: 'json',
            mode: 'popup',
            container: 'body',
            error: function(jqXHR, newValue){
                var reason = '';
                var status = '';
                if(jqXHR.name){
                    // save error new sig (mass save)
                    reason = jqXHR.name;
                    status = 'Error';
                }else{
                    reason = jqXHR.responseJSON.text;
                    status = jqXHR.status;
                }

                Util.showNotify({title: status + ': save signature', text: reason, type: 'error'});
                $(document).setProgramStatus('problem');
                return reason;
            }
        });


        // Input sig name ------------------------------------------------------------------------
        sigNameFields.editable({
            type: 'text',
            title: 'signature id',
            name: 'name',
            emptytext: '? ? ?',
            validate: function(value) {
                if($.trim(value).length < 3) {
                    return 'Id is less than min of "3"';
                }else if($.trim(value).length > 10){
                    return 'Id is more than max of "10"';
                }
            },
            params: modifyFieldParamsOnSend,
            success: function(response, newValue){
                if(response){
                    var signatureTypeField = $(this);
                    var rowElement = signatureTypeField.parents('tr');
                    var newRowData = response.signatures[0];

                    // update "updated" cell
                    updateSignatureCell(rowElement, 6, newRowData.updated);
                }
            }
        });


        // Select sig group (master) -------------------------------------------------------------
        sigGroupFields.editable({
            type: 'select',
            title: 'group',
            name: 'groupId',
            emptytext: 'unknown',
            onblur: 'submit',
            showbuttons: false,
            params: modifyFieldParamsOnSend,
            source: function(){

                var signatureGroupField = $(this);
                var systemTypeId = parseInt( signatureGroupField.attr('data-systemTypeId') );

                // get all available Signature Types
                // json object -> "translate" keys to names
                var availableTypes = Util.getSignatureGroupInfo('label');

                // add empty option
                availableTypes[0] = '';

                return availableTypes;
            },
            success: function(response, newValue){
                var signatureTypeField = $(this);
                var rowElement = signatureTypeField.parents('tr');
                newValue = parseInt(newValue);

                if(response){
                    var newRowData = response.signatures[0];

                    // update "updated" cell
                    updateSignatureCell(rowElement, 6, newRowData.updated);
                }

                // find related "name" select (same row) and change options
                var nameSelect = getNextEditableField(signatureTypeField);

                var systemTypeId = parseInt( signatureTypeField.attr('data-systemTypeId') );
                var areaId = parseInt( signatureTypeField.attr('data-areaid') );

                var newSelectOptions = getAllSignatureNames(systemData, systemTypeId, areaId, newValue);
                nameSelect.editable('option', 'source', newSelectOptions);
                nameSelect.editable('setValue', null);

                if(
                    newValue > 0 &&
                    newSelectOptions.length > 0
                ){
                    nameSelect.editable('enable');
                }else{
                    nameSelect.editable('disable');
                }
            }
        });


        // Select sig type (slave: depends on sig type) -----------------------------------------
        sigTypeFields.editable({ mode: 'popup',
            type: 'select',
            title: 'type',
            name: 'typeId',
            emptytext: 'unknown',
            onblur: 'submit',
            showbuttons: false,
            params: modifyFieldParamsOnSend,
            source: function(){
                var signatureNameField = $(this);

                var systemTypeId = parseInt( signatureNameField.attr('data-systemTypeId') );
                var areaId = parseInt( signatureNameField.attr('data-areaid') );
                var groupId = parseInt( signatureNameField.attr('data-groupId') );

                var cacheKey = [systemTypeId, areaId, groupId].join('_');

                // check for cached signature names
                if(sigNameCache.hasOwnProperty( cacheKey )){
                    return sigNameCache[cacheKey];
                }

                var signatureNames = getAllSignatureNames(systemData, systemTypeId, areaId, groupId);

                // get all available Signature Names
                var availableSigs = sigNameCache[cacheKey] = signatureNames;

                return availableSigs;
            },
            success: function(response, newValue){
                if(response){
                    var signatureTypeField = $(this);
                    var rowElement = signatureTypeField.parents('tr');
                    var newRowData = response.signatures[0];

                    // update "updated" cell
                    updateSignatureCell(rowElement, 6, newRowData.updated);
                }
            }
        });

        // Textarea sig description -------------------------------------------------------------
        sigDescriptionFields.editable({
            type: 'textarea',
            title: 'description',
            name: 'description',
            emptytext: '<i class="fa fa-fw fa-lg fa-pencil"></i>',
            onblur: 'submit',
            mode: 'inline',
            showbuttons: false,
            inputclass: config.editableDiscriptionInputClass,
            params: modifyFieldParamsOnSend,
            success: function(response, newValue){
                if(response){
                    var signatureTypeField = $(this);
                    var rowElement = signatureTypeField.parents('tr');
                    var newRowData = response.signatures[0];

                    // update "updated" cell
                    updateSignatureCell(rowElement, 6, newRowData.updated);
                }
            }
        });

        // open even
        sigDescriptionFields.on('shown', function(e, editable) {
            // enlarge the tools-action container because the tables gets bigger
            tableElement.parents('.' + config.tableToolsActionClass).css( 'height', '+=35px' );
        });

        // close event
        sigDescriptionFields.on('hidden', function(e, editable) {
            // enlarge the tools-action container because the tables gets bigger
            tableElement.parents('.' + config.tableToolsActionClass).css( 'height', '-=35px' );
        });

        // open next field dialog ---------------------------------------------------------------
        openNextEditDialogOnSave(sigNameFields);
        openNextEditDialogOnSave(sigGroupFields);
    };

    /**
     * get all signatures that can exist for a given system
     * @param systemData
     * @param systemTypeId
     * @param areaId
     * @param groupId
     * @returns {Array}
     */
    var getAllSignatureNames = function(systemData, systemTypeId, areaId, groupId){
        var newSelectOptions = [];
        var newSelectOptionsCount = 0;

        // set new Options ----------
        // get all possible "static" signature names by the selected groupId
        var tempSelectOptions = Util.getAllSignatureNames(systemTypeId, areaId, groupId);

        // format options into array with objects advantages: keep order, add more options (whs), use optgroup
        if(tempSelectOptions){
            var fixSelectOptions = [];
            for (var key in tempSelectOptions) {
                if (
                    key > 0 &&
                    tempSelectOptions.hasOwnProperty(key)
                ) {
                    //newSelectOptions.push({value: key, text: tempSelectOptions[key] });
                    fixSelectOptions.push( {value: key, text: tempSelectOptions[key] } );
                    newSelectOptionsCount++;
                }
            }

            if(newSelectOptionsCount > 0){
                if(groupId === 5){
                    // "wormhole" selected => multiple <optgroup> available
                    newSelectOptions.push({ text: 'Wandering WHs', children: fixSelectOptions});
                }else{
                    newSelectOptions = fixSelectOptions;
                }
            }
        }

        // wormhole
        if( groupId === 5 ){
            // add static WH(s) for this system
            if(systemData.statics){
                var staticWHData = [];
                for(var i = 0; i < systemData.statics.length; i++){
                    newSelectOptionsCount++;
                    var staticWHName = systemData.statics[i].name + ' - ' + systemData.statics[i].security;

                    staticWHData.push( {value: newSelectOptionsCount, text: staticWHName} );
                    newSelectOptionsCount++;
                }

                if(staticWHData.length > 0){
                    newSelectOptions.unshift({ text: 'Static WHs', children: staticWHData});
                }
            }

            // add possible frigate holes
            var frigateHoles = getFrigateHolesBySystem(areaId);
            var frigateWHData = [];
            for(var frigKey in frigateHoles){
                if (
                    frigKey > 0 &&
                    frigateHoles.hasOwnProperty(frigKey)
                ) {
                    frigateWHData.push( {value: newSelectOptionsCount, text: frigateHoles[frigKey]} );
                    newSelectOptionsCount++;
                }
            }

            if(frigateWHData.length > 0){
                newSelectOptions.push({ text: 'Frigate WHs', children: frigateWHData});
            }

            // add possible incoming holes
            var incomingWHData = [];
            for(var incomingKey in Init.incomingWormholes){
                if (
                    incomingKey > 0 &&
                    Init.incomingWormholes.hasOwnProperty(incomingKey)
                ) {
                    incomingWHData.push( {value: newSelectOptionsCount, text: Init.incomingWormholes[incomingKey]} );
                    newSelectOptionsCount++;
                }
            }

            if(incomingWHData.length > 0){
                newSelectOptions.push({ text: 'Incoming WHs', children: incomingWHData});
            }


        }

        // if selectOptions available -> add "empty" option as well
        if(newSelectOptionsCount > 0){
            newSelectOptions.unshift({ value: 0, text: ''});
        }


        return newSelectOptions;
    };

    /**
     * get possible frig holes that could spawn in a system
     * filtered by "systemTypeId"
     * @param systemTypeId
     * @returns {{}}
     */
    var getFrigateHolesBySystem = function(systemTypeId){
        var signatureNames = {};

        if(Init.frigateWormholes[systemTypeId]){
            signatureNames =  Init.frigateWormholes[systemTypeId];
        }

        return signatureNames;
    };

    /**
     * deletes signature rows from signature table
     * @param rows
     */
    var deleteSignatures = function(rows){

        var deletedSignatures = 0;

        var moduleElement = $('.' + config.systemSigModuleClass);
        var data = rows.data();
        var signatureTableApi = signatureTable.api();
        var rowElements = rows.nodes().to$();
        var signatureCount = data.length;

        var signatureIds = [];
        for(var i = 0; i < data.length; i++){
            signatureIds.push(data[i].id);
        }

        var requestData = {
            signatureIds: signatureIds
        };

        // animation callback function
        var removeCallback = function(rowElement){
            // delete signature row
            signatureTableApi.row(rowElement).remove().draw();

            deletedSignatures++;

            if(deletedSignatures === signatureCount){
                // all animations finished

                // update signature bar
                moduleElement.updateScannedSignaturesBar({showNotice: false});

                Util.showNotify({title: 'Signature deleted', text: signatureCount + ' signatures deleted', type: 'success'});
            }
        };

        $.ajax({
            type: 'POST',
            url: Init.path.deleteSignatureData,
            data: requestData,
            dataType: 'json'
        }).done(function(data){

            for(var j = 0; j < rowElements.length; j++){
                // removeRow
                $(rowElements[j]).toggleTableRow(removeCallback);
            }

        }).fail(function( jqXHR, status, error) {
            var reason = status + ' ' + error;
            Util.showNotify({title: jqXHR.status + ': Delete signature', text: reason, type: 'warning'});
            $(document).setProgramStatus('problem');
        });

    };


    /**
     * adds a new row to signature Table
     * @param systemData
     * @param signatureData
     * @param animate
     * @returns {*}
     */
    var addSignatureRow = function(systemData, signatureData, animate){

        var newSignatureData = formatSignatureData(systemData, [signatureData], fullSignatureOptions);

        // insert new row in main signature table
        var tablePrimaryElement = $('.' + config.sigTablePrimaryClass);
        var dataTablePrimary = tablePrimaryElement.DataTable();
        var newRowNode = dataTablePrimary.row.add(newSignatureData.shift()).draw().nodes();
        var newRowElement = newRowNode.to$();

        if(animate === true){
            newRowElement.hide();

            newRowElement.toggleTableRow(function(newRowElement){
                // make new row editable

                newRowElement.makeEditable(systemData);

                // update scan progress bar
                newRowElement.parents('.' + config.moduleClass).updateScannedSignaturesBar({showNotice: true});
            });
        }else{
            newRowElement.makeEditable(systemData);
        }

        return newRowElement;
    };

    /**
     * show/hides a table <tr> tag
     * @param callback
     */
    $.fn.toggleTableRow = function(callback){
        var rowElement = $(this);
        var cellElements = rowElement.children('td');

        var duration = 100;
        var tdCounter = 0;


        // wrap each <td> into a container (for better animation performance)
        // slideUp new wrapper divs
        if(rowElement.is(':visible')){
            // hide row

            // stop sig counter by adding a stopClass to each <td>, remove padding
            cellElements.addClass('stopCounter')
                .velocity({
                    paddingTop: 0,
                    paddingBottom: 0
                },{
                    duration: duration
                }).wrapInner('<div>')
                .children()
                .css({
                    'willChange': 'height'
                }).velocity('slideUp', {
                    duration: duration,
                    complete: function(animationElements){
                        tdCounter++;
                        // execute callback when last <td> animation finished
                        if(tdCounter === animationElements.length){
                            // remove wrapper
                            $(animationElements).children().unwrap();

                            if(callback !== undefined){
                                callback(rowElement);
                            }
                        }
                    }
                });
        }else{
            // show row

            // remove padding on "hidden" cells for smother animation
            cellElements.css({
                'padding-top': 0,
                'padding-bottom': 0,
                'willChange': 'padding-top, padding-top, height'
            });

            // add hidden wrapper for ea
            cellElements.wrapInner($('<div>').hide());

            // show row for padding animation
            rowElement.show();

            cellElements.velocity({
                paddingTop: '4px',
                paddingBottom: '4px'
            },{
                duration: duration,
                queue: false,
                complete: function(){
                    // animate <td> wrapper
                    cellElements.children()
                        .css({
                            'willChange': 'height'
                        }).velocity('slideDown', {
                            duration: duration,
                            complete: function(animationElements){
                                tdCounter++;
                                // execute callback when last <td> animation finished
                                if(tdCounter === animationElements.length){

                                    // remove wrapper
                                    var wrapperElements = cellElements.children();
                                    for(var i = 0; i < wrapperElements.length; i++){
                                        var currentWrapper = $(wrapperElements[i]);
                                        if(currentWrapper.children().length > 0){
                                            currentWrapper.children().unwrap();
                                        }else{
                                            currentWrapper.parent().html( currentWrapper.html() );
                                        }
                                    }

                                    if(callback !== undefined){
                                        callback(rowElement);
                                    }

                                }
                            }
                        });
                }
            });
        }
    };

    /**
     * draw a signature table with data
     * @param signatureData
     * @param systemData
     * @returns {*}
     */
    $.fn.drawSignatureTable = function(signatureData, systemData){

        var moduleElement = $(this);

        // create new signature table -------------------------------------------
        var table = $('<table>', {
            class: ['display', 'compact', 'nowrap', config.sigTableClass, config.sigTablePrimaryClass].join(' ')
        });

        moduleElement.append(table);

        // create signature table and store the jquery object global for this module
        signatureTable = table.dataTable( {
            data: signatureData
        } );

        // make Table editable
        signatureTable.makeEditable(systemData);

        moduleElement.updateScannedSignaturesBar({showNotice: true});

        return signatureTable;
    };

    /**
     * format signature data array into dataTable structure
     * @param systemData
     * @param signatureData
     * @param options
     * @returns {Array}
     */
    var formatSignatureData = function(systemData, signatureData, options){

        var formattedData = [];

        // security check
        if(
            systemData &&
            systemData.id &&
            systemData.id > 0
        ){
            var systemTypeId = systemData.type.id;

            // areaId is required as a key for signature names
            // if areaId is 0, no signature data is available for this system
            var areaId = Util.getAreaIdBySecurity(systemData.security);

            for(var i = 0; i < signatureData.length; i++){
                var data = signatureData[i];

                var tempData = {};

                // set id ------------------------------------------------------------------------------------------
                var sigId = 0;
                if(data.id > 0){
                    sigId = data.id;
                }
                tempData.id = sigId;

                // set status --------------------------------------------------------------------------------------
                var status = '';
                var statusClass = '';
                if(data.updated.character !== undefined){
                    statusClass = Util.getStatusInfoForCharacter(data.updated.character, 'class');
                }
                status =  '<i class="fa fa-fw fa-circle pf-user-status ' + statusClass + '"></i>';

                tempData.status = {
                    status: status,
                    status_sort: statusClass
                };

                // set name ----------------------------------------------------------------------------------------
                var sigName = '<a href="#" class="' + config.sigTableEditSigNameInput + '" ';
                if(data.id > 0){
                    sigName += 'data-pk="' + data.id + '" ';
                }
                sigName += '>' + data.name + '</a>';

                tempData.name = sigName;

                // set group id ------------------------------------------------------------------------------------
                var sigGroup = '<a href="#" class="' + config.sigTableEditSigGroupSelect + '" ';
                if(data.id > 0){
                    sigGroup += 'data-pk="' + data.id + '" ';
                }
                sigGroup += 'data-systemTypeId="' + systemTypeId + '" ';
                sigGroup += 'data-areaId="' + areaId + '" ';
                sigGroup += 'data-value="' + data.groupId + '" ';
                sigGroup += '></a>';

                tempData.group = {
                    group: sigGroup,
                    group_sort: data.groupId
                };

                // set type id -------------------------------------------------------------------------------------
                var sigType = '<a href="#" class="' + config.sigTableEditSigTypeSelect + '" ';
                if(data.id > 0){
                    sigType += 'data-pk="' + data.id + '" ';
                }

                // set disabled if sig type is not selected
                if(data.groupId < 1){
                    sigType += 'data-disabled="1" ';
                }

                sigType += 'data-systemTypeId="' + systemTypeId + '" ';
                sigType += 'data-areaId="' + areaId + '" ';
                sigType += 'data-groupId="' + data.groupId + '" ';
                sigType += 'data-value="' + data.typeId + '" ';
                sigType += '></a>';

                tempData.type = sigType;

                // set description ---------------------------------------------------------------------------------
                var sigDescription = '<a href="#" class="' + config.sigTableEditSigDescriptionTextarea + '" ';
                if(data.id > 0){
                    sigDescription += 'data-pk="' + data.id + '" ';
                }
                sigDescription += '>' + data.description + '</a>';

                tempData.description = sigDescription;

                // set created -------------------------------------------------------------------------------------
                tempData.created = data.created;

                // set updated -------------------------------------------------------------------------------------
                tempData.updated = data.updated;

                // info icon ---------------------------------------------------------------------------------------
                var infoButton = '';
                if(data.id > 0){
                    infoButton = '<i class="fa fa-fw fa-question-circle"></i>';
                }
                tempData.info = infoButton;

                // action icon -------------------------------------------------------------------------------------

                var actionButton = '<i class="fa ' + options.actionClass + ' ' + config.sigTableActionButtonClass + '"></i>';
                tempData.action = {
                    action: options.action,
                    button: actionButton
                };

                formattedData.push(tempData);

            }

        }

        return formattedData;
    };

    /**
     * setup dataTable options for all signatureTables
     * @param systemData
     */
    var initSignatureDataTable = function(systemData){

        $.extend( $.fn.dataTable.defaults, {
            pageLength: -1,
            lengthMenu: [[5, 10, 25, 50, -1], [5, 10, 25, 50, 'All']],
            order: [1, 'asc'],
            autoWidth: false,
            responsive: {
                details: false
            },
            language: {
                emptyTable:  'No signatures added',
                zeroRecords: 'No signatures found',
                lengthMenu:  'Show _MENU_ signatures',
                info:        'Showing _START_ to _END_ of _TOTAL_ signatures'
            },
            columnDefs: [
                {
                    targets: 0,
                    orderable: true,
                    searchable: false,
                    title: '',
                    width: '10px',
                    class: ['text-center', 'min-tablet-l'].join(' '),
                    data: 'status',
                    type: 'html',
                    render: {
                        _: 'status',
                        sort: 'status_sort'
                    }
                },{
                    targets: 1,
                    orderable: true,
                    searchable: true,
                    title: 'id',
                    type: 'html',
                    width: '30px',
                    data: 'name'
                },{
                    targets: 2,
                    orderable: true,
                    searchable: false,
                    title: 'group',
                    type: 'html',
                    width: '50px',
                    data: 'group',
                    render: {
                        _: 'group',
                        sort: 'group_sort'
                    }
                },{
                    targets: 3,
                    orderable: false,
                    searchable: false,
                    title: 'type',
                    type: 'html',
                    width: '180px',
                    data: 'type'
                },{
                    targets: 4,
                    orderable: false,
                    searchable: false,
                    title: 'description',
                    type: 'html',
                    data: 'description'
                },{
                    targets: 5,
                    title: 'created',
                    width: '90px',
                    searchable: false,
                    className: ['text-right', config.sigTableCounterClass, config.sigTableCreatedCellClass, 'min-tablet-l'].join(' '),
                    data: 'created',
                    render: {
                        _: 'created',
                        sort: 'created'
                    },
                    createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
                        $(cell).initTimestampCounter();
                    }
                },{
                    targets: 6,
                    title: 'updated',
                    width: '90px',
                    searchable: false,
                    className: ['text-right', config.sigTableCounterClass, config.sigTableUpdatedCellClass, 'min-tablet-l'].join(' '),
                    data: 'updated',
                    render: {
                        _: 'updated',
                        sort: 'updated'
                    },
                    createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
                        $(cell).initTimestampCounter();

                        // highlight cell
                        var diff = Math.floor((new Date()).getTime()) - cellData.updated * 1000;

                        // age > 1 day
                        if( diff > 86400000){
                            $(cell).addClass('txt-color txt-color-warning');
                        }
                    }
                },{
                    targets: 7,
                    title: '',
                    orderable: false,
                    searchable: false,
                    width: '10px',
                    class: 'pf-help text-center',
                    data: 'info',
                    createdCell: function(cell, cellData, rowData, rowIndex, colIndex){

                        if(rowData.id > 0){

                            // add row tooltip
                            var tooltipData = {
                                created: rowData.created,
                                updated: rowData.updated
                            };

                            $(cell).addCharacterInfoTooltip( tooltipData );
                        }
                    }
                },{
                    targets: 8,
                    title: '',
                    orderable: false,
                    searchable: false,
                    width: '10px',
                    class: ['text-center', config.sigTableActionCellClass].join(' '),
                    data: 'action',
                    render: {
                        _: 'button',
                        sort: 'action'
                    },
                    createdCell: function(cell, cellData, rowData, rowIndex, colIndex){

                        var tempTableElement = this;
                        var rowElement = $(cell).parents('tr');

                        switch(cellData.action){
                            case 'add':
                                // add new signature ---------------------------------------------------------------
                                $(cell).on('click', function(e) {
                                    // submit all fields within a table row
                                    var formFields = rowElement.find('.editable');

                                    // submit all xEditable fields
                                    formFields.editable('submit', {
                                        url: Init.path.saveSignatureData,
                                        ajaxOptions: {
                                            dataType: 'json' //assuming json response
                                        },
                                        data: {
                                            systemId: systemData.id, // additional data to submit
                                            pk: 0 // new data no primary key
                                        },
                                        error: $.fn.editable.defaults.error, // user default xEditable error function
                                        success: function (data, editableConfig) {

                                            var newRowElement = addSignatureRow(systemData, data.signatures[0], true);

                                            // highlight
                                            newRowElement.pulseTableRow('added');

                                            // prepare "add signature" table for new entry -> reset --------------------------------------------
                                            var signatureData = formatSignatureData(systemData, [emptySignatureData], emptySignatureOptions);

                                            var dataSecondaryElement = $('.' + config.sigTableSecondaryClass);
                                            var dataTableSecondary = dataSecondaryElement.DataTable();
                                            var newAddRowElement = dataTableSecondary.clear().row.add(signatureData.shift()).draw().nodes();

                                            newAddRowElement.to$().makeEditable(systemData);

                                            Util.showNotify({
                                                title: 'Signature added',
                                                text: 'Name: ' + data.name,
                                                type: 'success'
                                            });
                                        }
                                    });
                                });
                                break;
                            case 'delete':
                                // delete signature ----------------------------------------------------------------
                                var confirmationSettings = {
                                    container: 'body',
                                    placement: 'left',
                                    btnCancelClass: 'btn btn-sm btn-default',
                                    btnCancelLabel: 'cancel',
                                    btnCancelIcon: 'fa fa-fw fa-ban',
                                    title: 'Delete signature',
                                    btnOkClass: 'btn btn-sm btn-danger',
                                    btnOkLabel: 'delete',
                                    btnOkIcon: 'fa fa-fw fa-close',
                                    onConfirm : function(e, target){
                                        var deleteRowElement = $(target).parents('tr');
                                        var row = tempTableElement.DataTable().rows(deleteRowElement);
                                        deleteSignatures(row);
                                    }
                                };

                                // init confirmation dialog
                                $(cell).confirmation(confirmationSettings);


                                break;
                        }

                    }
                }
            ],
            createdRow: function(row, data, dataIndex){

            },
            initComplete: function(settings, json){
                // table init complete

            }
        });
    };

    /**
     * set module observer and look for relevant signature data to update
     * @param moduleElement
     */
    var setModuleObserver = function(moduleElement){
        var tablePrimaryElement = $('.' + config.sigTablePrimaryClass);
        var dataTablePrimary = signatureTable.DataTable();
        var signatureTableApi = signatureTable.api();

        $(document).off('pf:updateSystemModules').on('pf:updateSystemModules', function(e, data){
            if(data.signatures){
                moduleElement.updateSignatureTable(data.signatures, true);
            }

        });

        // set multi row select -----------------------------------------------------------------
        tablePrimaryElement.on('click', 'tr', function(e){
            if(e.ctrlKey) {
                $(this).toggleClass('selected');

                // check delete button
                checkDeleteSignaturesButton();
            }
        });

        // draw event for signature table -------------------------------------------------------
        signatureTableApi.on('draw.dt', function(){
            // check delete button
            checkDeleteSignaturesButton();
        });
    };

    /**
     * check the "delete signature" button. show/hide the button if a signature is selected
     */
    var checkDeleteSignaturesButton = function(){

        var selectedRows = getSelectedRows(signatureTable);
        var selectedRowCount = selectedRows.data().length;
        var clearButton = $('.' + config.sigTableClearButtonClass);

        if(selectedRowCount > 0){
            var allRows = getRows(signatureTable);
            var rowCount = allRows.data().length;

            var badgetText = selectedRowCount;
            if(selectedRowCount >= rowCount){
                badgetText = 'all';
            }
            clearButton.find('.badge').text( badgetText );

            // update clear signatures button text
            clearButton.velocity('stop');

            if( clearButton.is(':hidden') ){
                // show button
                clearButton.velocity('transition.bounceIn', {
                    duration: 180
                });
            }else{
                // highlight button
                clearButton.velocity('callout.pulse', {
                    duration: 240
                });
            }
        }else{
            // hide button
            clearButton.velocity('transition.bounceOut', {
                duration: 180
            });
        }
    };

    /**
     * get all rows of a table
     * @param table
     * @returns {*}
     */
    var getRows = function(table){
        var tableApi = table.api();
        var rows = tableApi.rows();

        return rows;
    };

    /**
     * get all selected rows of a table
     * @param table
     * @returns {*}
     */
    var getSelectedRows = function(table){
        var tableApi = table.api();

        var selectedRows = tableApi.rows('.selected');

        return selectedRows;
    };

    /**
     * get module element
     * @param parentElement
     * @param systemData
     * @returns {*|HTMLElement}
     */
    var getModule = function(parentElement, systemData){

        // create new module container
        var moduleElement = $('<div>', {
            class: [config.moduleClass, config.systemSigModuleClass].join(' '),
            css: {opacity: 0}
        });

        // headline
        var headline = $('<h5>', {
            text: 'Signatures'
        });

        moduleElement.append(headline);

        $(parentElement).append(moduleElement);

        // init dataTables
        initSignatureDataTable(systemData);

        // draw "new signature" add table --------------------------------------------

        moduleElement.drawSignatureTableToolbar(systemData);

        // request signature data for system -----------------------------------------

        var requestData = {
            systemIds: [systemData.id]
        };

        $.ajax({
            type: 'POST',
            url: Init.path.getSignatures,
            data: requestData,
            dataType: 'json'
        }).done(function(signatureData){

            var signatureTableData = formatSignatureData(systemData, signatureData, fullSignatureOptions);

            // draw signature table
            moduleElement.drawSignatureTable(signatureTableData, systemData);

            // set module observer
            setModuleObserver(moduleElement);
        }).fail(function( jqXHR, status, error) {
            var reason = status + ' ' + error;
            Util.showNotify({title: jqXHR.status + ': Get signatures', text: reason, type: 'warning'});
            $(document).setProgramStatus('problem');
        });

        return moduleElement;
    };

    /**
     * main module load function
     * @param systemData
     */
    $.fn.drawSignatureTableModule = function(systemData){

        var parentElement = $(this);

        // show module
        var showModule = function(moduleElement){
            if(moduleElement){
                moduleElement.velocity('transition.slideDownIn', {
                    duration: Init.animationSpeed.mapModule,
                    delay: Init.animationSpeed.mapModule,
                    complete: function(){
                        disableTableUpdate = false;
                    }
                });

            }
        };

        // check if module already exists
        var moduleElement = parentElement.find('.' + config.systemSigModuleClass);

        if(moduleElement.length > 0){

            // disable update
            disableTableUpdate = true;

            moduleElement.velocity('transition.slideDownOut', {
                duration: Init.animationSpeed.mapModule,
                complete: function(tempElement){
                     // Destroying the data tables throws
                     // save remove of all dataTables
                     signatureTable.api().destroy();

                    $(tempElement).remove();

                    moduleElement = getModule(parentElement, systemData);
                    // make modules appear "nice"
                    moduleElement.delay(150);
                    showModule(moduleElement);
                }
            });
        }else{
            moduleElement = getModule(parentElement, systemData);
            showModule(moduleElement);
        }

        return;
    };


});