const SystemUtils = function () {
    let actionMenuCounter = 0;

    return {
        isFilterUpdate : false,
        generateTableButtons : function (buttons, grouped = true) {
            let html;

            if (grouped) {
                html = '<div class="btn-group btn-table-group action-buttons" data-menu="' +
                    SystemUtils.actionMenuCounter + '"><button type="button" ' +
                    'class="btn btn-default btn-sm btn-table dropdown-toggle" data-toggle="dropdown" data-boundary="viewport">' +
                    'Ações</button><div class="dropdown-menu action-menu-' + SystemUtils.actionMenuCounter +
                    '" role="menu">';

                buttons.forEach(function (params) {
                    let attributes = '';

                    if (typeof params.attributes === 'object') {
                        params.attributes.forEach(function (paramData) {
                            attributes += paramData.name + '="' + paramData.value + '" ';
                        });
                    }

                    html += '<a class="dropdown-item ' + params.class +
                        '" href="' + params.href + '" ' + attributes + '>' + params.text + '</a>';
                });

                html += '</div></div>';
            } else {
                html = '<div class="btn-group">';
                buttons.forEach(function (params) {
                    let attributes = '';

                    if (typeof params.attributes === 'object') {
                        params.attributes.forEach(function (paramData) {
                            attributes += paramData.name + '="' + paramData.value + '" ';
                        });
                    }

                    html += '<a class="btn btn-sm btn-table ' + params.class +
                        '" href="' + params.href + '" ' + attributes + '>' + params.text + '<i class="' + params.iconClass + '"></i></a>';
                });
                html += '</div>';
            }

            SystemUtils.actionMenuCounter++;

            return html;
        },

        objectToTableFilter : function (object) {
            let result = [];

            Object.entries(object).forEach(entry => {
                const [key, value] = entry;
                result.push({
                    'text'  : value,
                    'value' : key,
                });
            });

            return result;
        },

        filtroSimNao : function () {
            return [
                {
                    'text'  : 'Não',
                    'value' : '0',
                },
                {
                    'text'  : 'Sim',
                    'value' : '1',
                },
            ];
        },

        initPhoneMask : function () {
            let maskBehavior = function (val) {
                return val.replace(/\D/g, '').length === 11 ? '(00) 00000-0000' : '(00) 0000-00009';
            };
            let options      = {
                onKeyPress : function (val, e, field, options) {
                    field.mask(maskBehavior.apply({}, arguments), options);
                },
            };
            let $mascara     = $('.mascara-telefone');
            $mascara.mask(maskBehavior, options);
            $mascara.attr('novalidate', 'true');
            $mascara.attr('pattern', '[0-9]*');
            $mascara.attr('inputmode', 'numeric');
        },

        initMasks : function () {
            SystemUtils.initPhoneMask();
            SystemUtils.initDateMask();
            SystemUtils.initDocumentoMask();
        },

        initDocumentoMask : function () {
            let maskBehavior = function (val) {
                return val.replace(/\D/g, '').length <= 11 ? '000.000.000-00#' : '00.000.000/0000-00';
            };
            let options      = {
                onKeyPress : function (val, e, field, options) {
                    field.mask(maskBehavior.apply({}, arguments), options);
                },
            };
            let $mascara     = $('.documento');
            $mascara.mask(maskBehavior, options);
            $mascara.attr('novalidate', 'true');
            $mascara.attr('pattern', '[0-9]*');
            $mascara.attr('inputmode', 'numeric');
        },

        initDateMask : function () {
            $('.mascara-data').datepicker({
                format         : 'dd/mm/yyyy',
                language       : 'pt-BR',
                autoclose      : true,
                todayHighlight : true,
                forceParse     : false,
                clearBtn       : true,
            }).mask('99/99/9999');

            $('.datepicker').datepicker({
                format    : 'dd/mm/yyyy',
                endDate   : '0d',
                autoclose : true,
                language  : 'pt-BR',
            }).mask('00/00/0000');

            $.fn.dataTable.moment('DD/MM/YYYY HH:mm:ss');
        },

        formatTelefoneColumn : function (data) {
            return data === null ? data :
                '<span class="mascara-telefone">' + data + '</span>';
        },
    };
}();

const WIN7_TABLE_OPTIONS = {
    language : {
        'decimal'        : '',
        'emptyTable'     : 'Nenhum dado encontrado',
        'info'           : 'Exibindo de _START_ a _END_ de _TOTAL_ registros',
        'infoEmpty'      : '',
        'infoFiltered'   : '',
        'infoPostFix'    : '',
        'thousands'      : ',',
        'lengthMenu'     : 'Mostrar _MENU_ linhas',
        'loadingRecords' : 'Carregando...',
        'processing'     : '<i class="fa fa-spinner fa-spin fa-3x fa-fw"></i><span class="sr-only">Loading...</span>',
        'search'         : 'Pesquisar:',
        'zeroRecords'    : 'Nenhum registro encontrado',
        'paginate'       : {
            'first'    : 'Primeiro',
            'last'     : 'Último',
            'next'     : 'Próximo',
            'previous' : 'Anterior',
        },
        'aria'           : {
            'sortAscending'  : ': ativar para ordenar em ordem crescente',
            'sortDescending' : ': ativar para ordenar em ordem decrescente',
        },
    },
};

$.fn.smallTable = function (options = {}) {
    return $(this).DataTable($.extend(WIN7_TABLE_OPTIONS, {
        dom          : '<\'row\'<\'col-sm-12\'<\'small-table-container\'tr>>><\'row\'<\'col-sm-12\'p>>',
        'lengthMenu' : [5],
        'order'      : [],
        'data'       : [],
        'info'       : false,
        'ordering'   : true,
        'paging'     : false,
    }, options));
};

$.fn.serverTable = function (options = {}) {
    let $this = $(this);

    const calculateResponsive = function (columns) {
        for (let i = 0; i < columns.length; i++) {
            if (columns[i]) {
                $('.filter-header:eq(' + i + ')').show();
            } else {
                $('.filter-header:eq(' + i + ')').hide();
            }
        }
    };

    let defaults = {
        serverSide : true,
        processing : false,
        stateSave  : false,

        dom : '<\'row\'<\'col-sm-12 col-md-6\'l>><\'row\'<\'col-sm-12\'<\'custom-table-container\'tr>>><\'row\'<\'col-sm-12 col-md-5\'i><\'col-sm-12 col-md-12\'p>>',

        initComplete : function () {
            let api      = this.api();
            let columns  = api.settings().init().columns;
            let $filters = $('<tr class="filters"></tr>').prependTo($this.find('thead'));
            $this.find('thead').css('display', 'table-header-group');
            api.columns()
                .eq(0)
                .each(function (colIdx) {
                    let column = columns[colIdx];
                    let html;

                    if (typeof column.visible !== 'undefined' && column.visible === false) {
                        return;
                    }

                    if (column.filter === 'search-title') {
                        html = '<th class="filter-header filters-title control">';
                        html += 'Filtros';
                        html += '</th>';
                        $(html).appendTo($filters).find('input');
                        return;
                    }

                    html            = '<th class="filter-header control">';
                    let search      = api.column(colIdx).search();
                    let filterClass = typeof column.filterClass !== 'undefined' ?
                        column.filterClass : '';

                    if (column.filter === 'text') {
                        html += '<div class="input-group input-group-sm">';
                        html += '<input type="text" class="form-control ' + filterClass + '" ';
                        html += 'data-column="' + colIdx + '">';
                        html += '</div>';
                    } else if (column.filter && column.filter.constructor === Array) {
                        html += '<div class="form-group"><select class="small-table-select custom-select rounded-0 form-control" data-column="' + colIdx + '">';
                        html += '<option value=""></option>';
                        column.filter.forEach(function (params) {
                            let extra = search === params.value ? 'selected' : '';
                            html += '<option value="' + params.value + '" ' + extra +
                                '>' + params.text + '</option>';
                        });
                        html += '</select></div>';
                    } else if (column.filter === 'number') {
                        html += '<div class="input-group input-group-sm">';
                        html += '<input type="number" class="form-control" ';
                        html += 'data-column="' + colIdx + '">';
                        html += '</div>';
                    }

                    html += '</th>';

                    if (column.filterClass && column.filterClass.includes('mascara-data')) {
                        let data = moment(search, 'YYYY-MM-DD');
                        if (data.isValid()) {
                            search = data.format('DD/MM/YYYY');
                        }
                    }

                    $(html).appendTo($filters).find('input').val(search);
                });
            $this.find('input,select').off('change').on('change', function () {
                let $this = $(this);
                let val   = $this.val().trim();
                $this.val(val);

                if ($this.hasClass('mascara-telefone') || $this.hasClass('documento')) {
                    val = val.replace(/\D/g, '');
                }

                if ($this.hasClass('mascara-data')) {
                    let date = moment(val, 'DD/MM/YYYY');
                    val      = date.isValid() ? date.format('YYYY-MM-DD') : val;
                }

                SystemUtils.isFilterUpdate = true;
                api.column($this.data('column')).search(val).draw();
            });
            SystemUtils.initMasks();
            calculateResponsive(api.columns().responsiveHidden().toArray());
        },

        'drawCallback' : function () {
            SystemUtils.actionMenuCounter = 0;
            SystemUtils.initMasks();
        },
    };

    let DataTable = $this.DataTable($.extend(WIN7_TABLE_OPTIONS, defaults, options));

    DataTable.on('responsive-resize', function (e, datatable, columns) {
        calculateResponsive(columns);
    });

    return DataTable;
};

if (typeof $.fn.dataTable !== 'undefined') {
    $.fn.dataTable.ext.errMode = 'none';
}