var filters = [];
var sortColumn;
var sortOrder;
var filteredColumn;
var sideMenuDataTable = $(".side-menu-datatable");
var url = new URL(window.location.href);
var date = decodeURI(url.searchParams.get("date"));
var displayBuffer = (sideMenuDataTable ? 50 : (date !== "null" ? 100 : 4));
var hasDataInDB;
var editedDataTable = false;
var isAutoTest = $('#IsAutoTest').val().toLowerCase() === 'true';

$.fn.dataTable.ext.errMode = 'throw';
$.extend(true, $.fn.dataTable.defaults, {
    serverSide: true,
    lengthChange: false,
    searching: false,
    responsive:
    {
        details: {
            display: $.fn.dataTable.Responsive.display.childRowImmediate,
            type: 'column',
            target: ''
        }
    },
    autoWidth: false,
    processing: true,
    ordering: false,
    dom: isAutoTest ? "BZlfrtip" : "Zlfrtip",
    buttons: isAutoTest ? [
        {
            extend: 'excelHtml5',
            filename: function () {
                var pageTitle = $(document).prop('title');
                // only include begining of the page title
                if (pageTitle.indexOf('|') > -1) {
                    var parts = pageTitle.split('|');
                    return paw.utils.value.trimString(parts[0]);
                }
                return paw.utils.value.trimString(pageTitle);
            },
            exportOptions: {
                columns: ':visible',
                format: {
                    body: function (data, row, column, node) {
                        // check for number
                        // number export solution hint:
                        // https://datatables.net/forums/discussion/71150/export-excel-numbers
                        // https://jsfiddle.net/colin0117/9yrvzmb4/
                        var text = $('<p>' + data + '</p>').text();
                        if (text.indexOf(',') > -1) {
                            return $.isNumeric(text.replace(',', '.')) ? text.replace(',', '.') : text;
                        }

                        // check for bool
                        if ($(node).find('.glyphicon-ok').length > 0) {
                            return 'true';
                        }
                        if ($(node).find('.glyphicon-remove').length > 0) {
                            return 'false';
                        }

                        // export as text
                        return text;
                    }
                }
            }
        }
    ] : [],
    colReorder: true,
    scrollResize: true,
    scrollCollapse: true,
    stateSave: true,
    stateSaveCallback: function (settings, data) {
        if (editedDataTable) {
            $.ajax({
                url: $("#SaveTableGrid").val(),
                type: "POST",
                data: {
                    tableData: {
                        TableName: $(".dataTable:last").attr("data-grid-id"),
                        DatatableData: JSON.stringify(data)
                    }
                },
            });
        }
       
        datatablesBaseDrawCallback($(this));
        select2withAPI();
        editedDataTable = false;
    },
    stateLoadCallback: function (settings, callback) {
        var gridId = $(".dataTable:last").attr("data-grid-id");
        if (gridId) {
            $.ajax({
                url: $("#GetTableGrid").val(),
                type: "GET",
                data: {
                    tableName: gridId
                },
                success: function (data) {
                    try {
                        populateDropdownDT();
                        if (jQuery.isEmptyObject(data)) {
                            callback(null);
                        } else {
                            callback(JSON.parse(data.DatatableData));
                            hasDataInDB = true;
                        }
                    }
                    catch (e) {
                        console.error("Exception resolving Datatable settings: ", e);
                        callback(null);
                    }
                }
            });
        } else {
            callback(null);
        }
    },
    scrollY: "calc(100vh - 280px)", //function () { return $(this).children("table").attr("data-height") ? $(this).children("table").attr("data-height") : 'calc(100vh - 280px)'; },
    deferRender: true,
    scroller: {
        displayBuffer: displayBuffer,
        loadingIndicator: true
    },
    ajax: {
        type: "POST",
        beforeSend: function (jqXHR, settings) {
            // TODO: When multiple filters will be possible
            //var modalFilters = $(".filter-modal[id^='" + tableId + "']");

            //if (modalFilters)
            //    for (var j = 0; j < modalFilters.length; j++) {
            //        addFilter(modalFilters[j].id);
            //    }

            for (var i = 0; i < filters.length; i++) {
                settings.data += "&FilterColumn=" + filters[i].filterColumn +
                    "&FilterCriteria=" + filters[i].filterCriteria +
                    "&FilterValue=" + filters[i].filterValue +
                    "&FilterValue2=" + filters[i].filterValue2;
            }

            if (sortColumn && sortOrder)
                settings.data += "&SortColumn=" + sortColumn + "&SortOrder=" + sortOrder;
        }
    },
    language: {
        zeroRecords: $("#datatable-noResults").val(),
        info: $("#datatable-info").val(),
        infoEmpty: "",
        processing: "<div class='datatables-loading'></div>",
        emptyTable: $("#datatable-noResults").val(),
        paginate: {
            first: "<i class='fa fa-angle-double-left'></i>",
            last: "<i class='fa fa-angle-double-right'></i>",
            next: "<i class='fa fa-angle-right'></i>",
            previous: "<i class='fa fa-angle-left'></i>"
        }
    },
    initComplete: function (settings) {
        var filterId;

        for (var c = 0; c < settings.aoColumns.length; c++) {
            if (settings.aoColumns[c].filtertype) {
                createFilterModal($(this)[0].id, settings.aoColumns[c].data, settings.aoColumns[c].name, settings.aoColumns[c].filtertype);
                $(settings.aoColumns[c].nTh).append("<div class='filter-icon pull-right " + (c === settings.aoColumns.length - 1 ? 'm-r-md' : '') + "'></div>");
            }
        }

        // Scroll to focused row
        //$(".dataTables_scrollBody").scrollTo($(".side-menu-item-active"), 1000); Do we need this?

        $('body').on('focus', ".datepicker", function () {
            $(this).datepicker();
        });

        let $scrollTable = $(this).closest(".dataTables_scroll").find(".dataTables_scrollHead table");
        $(this).add($scrollTable).on('click', 'th', function () {
            filteredColumn = this;

            var nonHiddenColumns = settings.aoColumns.filter(function (node) {
                return node.bVisible;
            });

            $(".filter-modal").addClass("hidden");
            var columnId = nonHiddenColumns[$(this).index()].data;
            var type = nonHiddenColumns[$(this).index()].filtertype;
            if (!type)
                return;

            var position = $(this).offset();
            var dtId = $(this).closest('.dataTables_scrollHead').next(".dataTables_scrollBody").children("table")[0].id;
            filterId = $("#" + dtId + "_" + columnId + "_" + type);

            if ($(document).width() > (position.left + $(".filter-modal").width()))
                $(filterId).css("left", position.left).css("top", position.top + $(this).outerHeight());
            else
                $(filterId).css("left", $(document).width() - $(".filter-modal").width() - 10).css("top", position.top + $(this).outerHeight());

            $(filterId).removeClass("hidden");
        });

        $(document).mousedown(function (e) {
            var container = $(filterId);

            // if the target of the click isn't the container nor a descendant of the container
            if (container &&
                !container.is(e.target) &&
                container.has(e.target).length === 0 &&
                !($(e.target).hasClass("datepicker") ||
                $(e.target).closest(".datepicker").length > 0)) {

                container.addClass("hidden");
                filterId = null;
            }
        });

        showHideColumns();

        $('.dataTable').DataTable().on('column-reorder', function (e, settings, details) {
            editedDataTable = true;
        });

        $('.dataTable').DataTable().on('column-sizing.dt', function (e, settings) {
            editedDataTable = true;
        });
    },
    drawCallback: function (settings, json) {
        datatablesBaseDrawCallback($(this));
    }
});

function datatablesBaseDrawCallback($datatable) {
    let $wrapper = $datatable.closest(".dataTables_wrapper");
    if ($wrapper.length > 0) $datatable = $wrapper.first();

    $datatable.find('input[type="checkbox"]').customCheckbox();
}

$.fn.dataTable.reload = function ($element) {
    $(window).trigger('resize');
    $element.DataTable().ajax.reload();
};

$.fn.dataTable.render.url = function (idColumn, urlColumn, allowRedirect) {
    return function (data, type, row, meta) {
        if (type === 'display') {
            if (row[idColumn] && row[idColumn] !== "")
                return "<a href=\"" + row[urlColumn] + encodeURIComponent(row[idColumn]) + "\" " + (allowRedirect ? "class='allow-redirect'" : "") + ">" + data + "</a>";
            else
                return data;
        }

        return data;
    };
};

$.fn.dataTable.render.link = function (idColumn, allowRedirect, urlIndex, cutoff) {
    return function (data, type, row, meta) {
        if (type === 'display') {
            var url = $(meta.settings.aoHeader[0][meta.col].cell).attr('data-url');
            if (urlIndex)
                url = $(meta.settings.aoHeader[0][meta.col].cell).attr('data-url-' + urlIndex);
            var dataMethod = $(meta.settings.aoHeader[0][meta.col].cell).attr('data-method');

            let fullData = data;
            if (data && data != null && cutoff) {
                data = data.toString().length < cutoff ?
                    data :
                    data.substr(0, cutoff - 1) + '&#8230;';
            }

            if (row[idColumn] && row[idColumn] !== "")
                return "<a id=\"DataTableRowEntityLink-" + idColumn + "-" + row[idColumn] + "\" href=\"" + url + encodeURIComponent(row[idColumn]) + "\" " + (dataMethod ? "data-method=\"" + dataMethod + "\" " : "") + " " + (allowRedirect ? "class='allow-redirect'" : "") + " title=\"" + fullData + "\">" + (data ? data : "") + "</a>";
            else
                return data;
        }

        return data;
    };
};


$.fn.dataTable.render.linkByDocType = function (idColumn, allowRedirect = false) {
    return function (data, type, row, meta) {
        if (type === 'display') {
            if (row["DocTypeType"] === "")
                return "";

            var url = $(meta.settings.aoHeader[0][meta.col].cell).attr('data-url');

            if (row["DocTypeType"] === "I")
                url = $(meta.settings.aoHeader[0][meta.col].cell).attr('data-url-I');
            else if (row["DocTypeType"] === "P")
                url = $(meta.settings.aoHeader[0][meta.col].cell).attr('data-url-P');

            var dataMethod = $(meta.settings.aoHeader[0][meta.col].cell).attr('data-method');

            return "<a href=\"" + url + encodeURIComponent(row[idColumn]) + "\" " + (dataMethod ? "data-method=\"" + dataMethod + "\" " : "") + " " + (allowRedirect ? "class='allow-redirect'" : "") + ">" + data + "</a>";
        }

        return data;
    };
};

$.fn.dataTable.render.toggle = function (toggleCondition = 'T', color = false, colorTrue = 'text-success', colorFalse = 'text-danger',
    iconTrue = 'glyphicon glyphicon-ok', iconFalse = 'glyphicon glyphicon-remove') {
    return function (data, type) {
        if (type === 'display') {
            if (data === toggleCondition)
                return "<span class=\"" + iconTrue + " " + (color ? colorTrue : "") + "\" aria-hidden=\"true\"></span>";
            else
                return "<span class=\"" + iconFalse + " " + (color ? colorFalse : "") + "\" aria-hidden=\"true\"></span>";
        }

        return data;
    };
};

$.fn.dataTable.render.GDPR = function (isGDPR, VATColumn) {
    return function (data, type) {
        if (type === 'display') {
            return data;

            //TODO: uncomment when GDPR correctly implemented
            //return anonymizeText(isGDPR && isGDPR === "True", row[VATColumn], data);
        }

        return data;
    };
};

$.fn.dataTable.render.ellipsis = function (cutoff, isGDPR, VATColumn) {
    return function (data, type, row) {
        if (isGDPR === "True") {
            //TODO: uncomment when GDPR correctly implemented
            //return anonymizeText(isGDPR && isGDPR === "True", row[VATColumn], data);
        }

        if (type === 'display' && data) {
            var str = data.toString();

            return str.length < cutoff ?
                str :
                str.substr(0, cutoff - 1) + '&#8230;';
        }

        return data;
    };
};

$.fn.dataTable.render.checkbox = function (selectionEventName, id, idColumn) {
    return function (data, type, row) {
        if (type === 'display') {
            return "<div class='checkbox-border'><input " + (id && id !== "" ? " id='" + id + row[idColumn] + "'" : " id='cb" + data + "'") + " type='checkbox'" +
                (selectionEventName ? "onclick='" + selectionEventName + "(this);'" : "") + "class='ackey selector' name='select' value='" + data + "'" +
                (data === true || data === "T" ? "' checked='" + data + "'" : "") + "></div>";
        }

        return data;
    };
};

$.fn.dataTable.render.textbox = function (selectionEventName) {
    return function (data, type) {
        if (type === 'display') {
            return "<input type='text'" + (selectionEventName ? "onclick='" + selectionEventName + "(this);'" : "") + "value='" + data + "' class='form-control'>";
        }

        return data;
    };
};

$.fn.dataTable.render.input = function (onClick, isRequired, id, idColumn, additionalClass) {
    return function (data, type, row) {
        if (type === 'display') {
            return "<input type='text'" +
                (id && id !== "" ? " id='" + id + row[idColumn] + "'" : "") +
                (onClick ? " onclick='" + onClick + "(this);'" : "") +
                " value='" + data + "' autocomplete='off' class='form-control " +
                (additionalClass && additionalClass !== "" ? additionalClass : "") +
                ((!data || data === "") && (isRequired && isRequired === true) ? " table-input-error" : "") + "'>";
        }

        return data;
    };
};

$.fn.dataTable.render.note = function (idColumn) {
    return function (data, type, row) {
        if (type === 'display') {
            var id = row[idColumn];

            if (data && data.length > 15) {
                return "<button type='button' class='btn btn-link no-padding m-r-sm' onclick=\"" + 'openTableNoteModal(' + id + ')' + "\">" +
                    "<i class='fa fa-comment btn-active'></i>" +
                    "</button>" +
                    "<span title='" + data + "'>" +
                        data.substring(0, 10) + '&#8230;' +
                    "</span>" +
                    "<input type='hidden' id='NoteId-" + id + "' value='" + data + "'>";
            } else
                return data;
        }

        return data;
    };
};

function openTableNoteModal(id) {
    $("#item-note").val($("#NoteId-" + id).val()).attr("readonly", "readonly");
    $("#note-modal .modal-footer").addClass("hidden");
    $('#note-modal').modal('show');
}

$.fn.dataTable.render.dropdown = function (items, id, idColumn, additionalClass) {
    return function (data, type, row) {
        if (type === 'display') {
            let $select = $("<select class='form-control " + (additionalClass && additionalClass !== "" ? additionalClass : "") + "'" +
                (id && id !== "" ? " id='" + id + row[idColumn] + "'" : "") + "></select>");

            items.forEach(function (item, index) {
                $select.append("<option value='" + item.value + "' " + (data === item.value ? "selected" : "") + ">" +
                    item.value + (item.name && item.name !== "" ? " - " + item.name : "") +
                    "</option>");
            });

            return $select[0].outerHTML;
        }

        return data;
    };
};

$.fn.dataTable.render.dropdownOptions = function ($itemsContainer, id, idColumn, additionalClass) {
    return function (data, type, row) {
        if (type === 'display') {
            let $select = $("<select id='" + id + row[idColumn] + "' value='" + data + "' class='form-control " +
                (additionalClass && additionalClass !== "" ? additionalClass : "") + "'></select>");

            var items = $itemsContainer.html();
            if (data && data !== "")
                items = items.replace("<option value=" + '"' + data + '"' + ">", "<option value=" + '"' + data + '"' + " selected>");
            $select.append(items);

            return $select[0].outerHTML;
        }

        return data;
    };
};

$.fn.dataTable.render.select2 = function ($itemsContainer, id, idColumn, additionalClass) {
    return function (data, type, row) {
        if (type === 'display') {
            let $select = $("<select id='" + id + row[idColumn] + "' value='" + data + "' class='form-control dt-select2'>" +
                "</select>");

            $select.append("<option value='" + data + "' selected>" + data + "</option>");

            return $select[0].outerHTML;
        }

        return data;
    };
};

$.fn.dataTable.render.typeahead = function (id, idColumn, isRequired, typeaheadType, additionalClass) {
    return function (data, type, row) {
        if (type === 'display') {
            var input = "<input type='text'" +
                (" id='" + id + row[idColumn] + "'") +
                " value='" + data + "' class='form-control" +
                (additionalClass && additionalClass !== "" ? " " + additionalClass : "") +
                (typeaheadType && typeaheadType !== "" ? " " + typeaheadType : "") +
                ((!data || data === "") && (isRequired && isRequired === true) ? " table-input-error" : "") + "'>";

            return input;
        }

        return data;
    };
};

$.fn.dataTable.render.preview = function (idColumn, urlIndex) {
    return function (data, type, row, meta) {
        if (type === 'display') {
            var url = $(meta.settings.aoHeader[0][meta.col].cell).attr('data-url');
            var func = $(meta.settings.aoHeader[0][meta.col].cell).attr('data-function');
            if (urlIndex)
                func = $(meta.settings.aoHeader[0][meta.col].cell).attr('data-function-' + urlIndex);
            var params = $(meta.settings.aoHeader[0][meta.col].cell).attr('data-params');

            if (url)
                return "<a href=\"" + url + row[idColumn] + "\"><i class=\"" + 'fa fa-eye fa-lg text-muted' + "\"></i></a>";
            else if (func) {
                if (params) {
                    var docNames = $(meta.settings.aoHeader[0][meta.col].cell).attr('data-local');
                    var docNamesArray = docNames.split(',');
                    var paramsArray = params.split(',');
                    var output = "<div class='dropdown dropdown-preview'><i class=\"" + 'fa fa-eye fa-lg text-muted clickable-icon dropbtn-preview' + "\"></i>";
                    output += "<div class='dropdown-content dropdown-content-preview'>";
                    output += "<a onClick=\"" + func.replace("{0}", row[idColumn]) + "\">" + docNamesArray[0] + "</a>";
                    for (var i = 0; i < paramsArray.length; i++) {
                        output += "<a onClick=\"" + func.replace("{0}", row[idColumn] + "&" + paramsArray[i]) + "\">" + docNamesArray[i + 1] + "</a>";
                    }
                    output += "</div></div>";

                    return output;
                }
                else {
                    return "<div onClick=\"" + func.replace("{0}", row[idColumn]) + "\"><i class=\"" + 'fa fa-eye fa-lg text-muted clickable-icon' + "\"></i></div>";
                }
            }
        }

        return data;
    };
};

$.fn.dataTable.render.previewWithOptions = function (id, url, secondParameterOptions, onClickPreview) {
    return function (data, type, row, meta) {
        if (!secondParameterOptions) secondParameterOptions = [];

        var func = url.replace("{0}", id);
        var dropdownButton = "<button id=" + ("previewIcon-" + id) + " type='button' onclick=" + onClickPreview + " class='btn btn-ghost dropdown-toggle p-none' data-toggle='dropdown'><span class='fa fa-eye fa-lg text-muted m-r-xs eyeIcon'></span><span class='text-muted caret'></span></button>";
        var dropdownMenu = "<ul id=" + ("previewDropdown-" + id) + " class='dropdown-menu dropdown-menu-left'>";
        secondParameterOptions.forEach(secondParameter => {
            dropdownMenu += "<li><a onClick=\"" + func.replace("{1}", secondParameter.Value) + "\">" + secondParameter.Text + "</a></li>";
        });
        dropdownMenu += "</ul>";

        return "<div class='btn-group dropdown'>" + dropdownButton + dropdownMenu + "</div>";
    };
};

$.fn.dataTable.render.previewReportTreeOptions = function (idColumn, urlIndex, reportTreeTypeColumn = null) {
    return function (data, type, row, meta) {
        if (type === 'display') {
            var func = $(meta.settings.aoHeader[0][meta.col].cell).attr('data-function');
            if (urlIndex)
                func = $(meta.settings.aoHeader[0][meta.col].cell).attr('data-function-' + urlIndex);
            func = func.replace("{0}", row[idColumn]) + "; onClickPreviewSelectRow(this)";

            setPreviewOnClicks(func);

            if (reportTreeTypeColumn) {
                var reportTreeId = $(meta.settings.aoHeader[0][meta.col].cell).attr('data-reportTree-' + row[reportTreeTypeColumn]);
                return $("#" + reportTreeId).html();
            } else
                return $("#reportTreeDropdown").html();
        }

        return data;
    };
};

$.fn.dataTable.render.previewByDocType = function (idColumn) {
    return function (data, type, row, meta) {
        if (type === 'display') {
            if (row["DocTypeType"] === "")
                return "";

            var url = $(meta.settings.aoHeader[0][meta.col].cell).attr('data-url');
            var params = $(meta.settings.aoHeader[0][meta.col].cell).attr('data-params');
            var func = $(meta.settings.aoHeader[0][meta.col].cell).attr('data-function');

            if (row["DocTypeType"] === "I")
                func = $(meta.settings.aoHeader[0][meta.col].cell).attr('data-function-I');
            else if (row["DocTypeType"] === "P")
                func = $(meta.settings.aoHeader[0][meta.col].cell).attr('data-function-P');

            if (url)
                return "<a href=\"" + url + row[idColumn] + "\" onclick=\"" + 'onClickPreviewSelectRow(this)' + "\"><i class=\"" + 'fa fa-eye fa-lg text-muted' + "\"></i></a>";
            else if (func) {
                if (params) {
                    var docNames = $(meta.settings.aoHeader[0][meta.col].cell).attr('data-local');
                    var docNamesArray = docNames.split(',');
                    var paramsArray = params.split(',');
                    var output = "<div class='dropdown dropdown-preview'><i class=\"" + 'fa fa-eye fa-lg text-muted clickable-icon dropbtn-preview' + "\"></i>";
                    output += "<div class='dropdown-content dropdown-content-preview'>";
                    output += "<a onClick=\"" + func.replace("{0}", row[idColumn]) + "; onClickPreviewSelectRow(this)" + "\">" + docNamesArray[0] + "</a>";
                    for (var i = 0; i < paramsArray.length; i++) {
                        output += "<a onClick=\"" + func.replace("{0}", row[idColumn] + "&" + paramsArray[i]) + "; onClickPreviewSelectRow(this)" + "\">" + docNamesArray[i + 1] + "</a>";
                    }
                    output += "</div></div>";

                    return output;
                }
                else {
                    return "<div onClick=\"" + func.replace("{0}", row[idColumn]) + "; onClickPreviewSelectRow(this)" + "\"><i class=\"" + 'fa fa-eye fa-lg text-muted clickable-icon' + "\"></i></div>";
                }
            }
        }

        return data;
    };
};

function onClickPreviewSelectRow($element) {
    $("tbody tr").removeClass("bank-selected");
    $($element).closest("tr").addClass("bank-selected");
}

$.fn.dataTable.render.errorStatus = function (id, idColumn) {
    return function (data, type, row) {
        if (type === 'display' && (data && data === true)) {
            return "<span id='" + id + row[idColumn] + "'><i class=\"" + 'fa fa-times fa-lg text-danger' + "\"></i></span>";
        }

        return "<span id='" + id + row[idColumn] + "'></span>";
    };
};

function createFilterModal(tableId, columnId, columnName, id) {
    $.ajax({
        method: "POST",
        url: $("#dataFilterURL").val(),
        data: { type: id },
        success: function (data) {
            var divData = '<div class="filter-modal hidden" id="' + tableId + '_' + columnId + '_' + id + '" data-column="' + columnName + '"><div class="m-sm">';

            // Sorting
            divData += $("#filterSortText").val() + ':';
            divData += '<div class="row"><div class="col-md-12 m-t-xs m-l-xs clickable-icon" id="' + tableId + '_' + columnName + '" data-sort="asc" onclick="onSort(this, \'' + tableId + '\')">';
            divData += 'A <i class="fa fa-long-arrow-right"></i> Z';
            divData += '</div><div class="col-md-12 m-t-xs m-l-xs clickable-icon" id="' + tableId + '_' + columnName + '" data-sort="desc" onclick="onSort(this, \'' + tableId + '\')">';
            divData += 'Z <i class="fa fa-long-arrow-right"></i> A';
            divData += '</div></div>';
            divData += '<hr>';

            // Filtering
            divData += $("#filterText").val() + ': <select onchange="changeFilterCriteria(this)" id="filter_' + tableId + "_" + columnId + '_' + id + '" data-criteria="' + id + '" class="form-control m-t-xs">';
            for (var i = 0; i < data.length; i++) {
                divData += '<option value=' + data[i].CriteriaCode + '>' + data[i].Text + '</option>';
            }
            divData += '</select>';
            divData += '<div class="row m-t-sm hidden" id="filter_' + tableId + '_' + columnId + '_' + id + '_valueBetween">';
            divData += '<div class="col-md-6"><input type="text" id="filter_' + tableId + '_' + columnId + '_' + id + '_valueFrom" class="form-control ' + (id === "dateTime" ? "datepicker" : "") + '" autocomplete="off" /></div>';
            divData += '<div class="col-md-6"><input type="text" id="filter_' + tableId + '_' + columnId + '_' + id + '_valueTo" class="form-control ' + (id === "dateTime" ? "datepicker" : "") + '" autocomplete="off" /></div></div>';
            divData += '<input type="text" id="filter_' + tableId + '_' + columnId + '_' + id + '_singleValue" class="form-control m-t-sm ' + (id === "dateTime" ? "datepicker" : "") + '" autocomplete="off" />';
            divData += '<div class="m-t-sm pull-right">';
            divData += '<button class="btn btn-default btn-outline" onclick="closeFilter(\'' + tableId + '_' + columnId + '_' + id + '\')">' + $("#filterCancel").val() + '</button>';
            divData += '<button class="btn btn-success m-l-sm" onclick="applyFilter(\'' + tableId + '_' + columnId + '_' + id + '\', \'' + tableId + '\')">' + $("#filterSubmit").val() + '</button>';
            divData += '</div></div></div>';

            $("body").append(divData);
        }
    });
}

function closeFilter(id) {
    $("#" + id).addClass("hidden");
}

function applyFilter(id, idTable) {
    addFilter($("#" + id));
    manageHeaderIcons("filter", null, idTable);
    $("#" + id).addClass("hidden");
    $.fn.dataTable.reload($("#" + idTable));
}

function addFilter($modal) {
    // TODO: Remove when using multiple filters
    filters = [];

    var modalId = $modal.attr("id");
    var filterCriteria = $("#filter_" + modalId).val();
    var column = $modal.attr("data-column");

    $("#filterColumn").val(column);
    $("#filterCriteria").val(filterCriteria);

    if ($("#filter_" + modalId + "_singleValue").val()) {
        $("#filterValue").val($("#filter_" + modalId + "_singleValue").val());
        filters.push({
            filterColumn: column, filterCriteria: filterCriteria, filterValue: $("#filter_" + modalId + "_singleValue").val(), filterValue2: ""
        });
    }
    else {
        $("#filterValue").val($("#filter_" + modalId + "_valueFrom").val());
        $("#filterValue2").val($("#filter_" + modalId + "_valueTo").val());
        filters.push({
            filterColumn: column, filterCriteria: filterCriteria, filterValue: $("#filter_" + modalId + "_valueFrom").val(), filterValue2: $("#filter_" + modalId + "_valueTo").val()
        });
    }
}

function changeFilterCriteria(e) {
    if ($("#" + e.id + " option:selected").val() === $("#enumNumberBetween").val() || $("#" + e.id + " option:selected").val() === $("#enumDateBetween").val()) {
        $("#" + e.id + "_singleValue").addClass("hidden");
        $("#" + e.id + "_valueBetween").removeClass("hidden");
        $("#" + e.id + "_singleValue").val("");
    } else {
        $("#" + e.id + "_singleValue").removeClass("hidden");
        $("#" + e.id + "_valueBetween").addClass("hidden");
        $("#" + e.id + "_valueFrom").val("");
        $("#" + e.id + "_valueTo").val("");
    }
}

function onSort(sort, idTable) {
    sortOrder = $(sort).attr("data-sort");
    sortColumn = sort.id.substring(sort.id.indexOf('_') + 1, sort.id.length);
    manageHeaderIcons("sort", sortOrder, idTable);
    $(sort).closest(".filter-modal").addClass("hidden");
    $.fn.dataTable.reload($("#" + idTable));
}

function manageHeaderIcons(iconType, sortOrder, idTable) {
    if (iconType === "filter") {
        let scroll = $("#" + idTable).closest(".dataTables_scroll");
        let th;
        if (scroll.length === 0) {
            th = $("#" + idTable + " .fa-filter").parent();
        }
        else {
            th = $("#" + idTable).closest(".dataTables_scroll").find(".fa-filter").parent();
        }

        var hasSortIcons = th.children().hasClass(".fa-sort-up", ".fa-sort-down");
        if (!hasSortIcons) {
            th.append('<div class="filter-icon pull-right"></div>');
        }

        th.children().remove(".fa-filter");
        $(filteredColumn).children().remove(".filter-icon");
        $(filteredColumn).append('<i class="fa fa-filter m-t-xxs pull-right"></i>');

    } else if (iconType === "sort") {
        let scroll = $("#" + idTable).closest(".dataTables_scroll");
        let th;
        if (scroll.length === 0) {
            th = $("#" + idTable + " .fa-sort-up, #" + idTable + ".fa-sort-down").parent();
        }
        else {
            th = $("#" + idTable).closest(".dataTables_scroll").find(".fa-sort-up, .fa-sort-down").parent();
        }

        if (!th.children().hasClass(".fa-filter")) {
            th.append('<div class="filter-icon pull-right"></div>');
        }

        th.children(".fa-sort-up, .fa-sort-down").remove();
        $(filteredColumn).children().remove(".filter-icon");

        if (sortOrder === "asc")
            $(filteredColumn).append('<i class="fa fa-sort-up m-t-xs pull-right"></i>');
        else
            $(filteredColumn).append('<i class="fa fa-sort-down m-t-xs pull-right"></i>');
    }
}

function showHideColumns() {
    $(document).ready(function () {
        var headTable = $(".dataTable:not(.side-table):first");
        var gridId = headTable.data("grid-id");
        var showHideColumnsTitle = $("#ShowHideColumns").val();
        var isDropdownPushedLeft = $(".divided-content-toggle-close").length ? "push-left" : "";
        var showHideDropdown = `<span id="sh-dropdown-menu-DT" class='show-hide-dropdown' title='${showHideColumnsTitle}'>
                                    <a role='button' class='pull-right'>
                                        <span class='default-icon-color'>   
                                            <i class='fas fa-ellipsis-v'></i>
                                        </span>
                                    </a>
                                    <ul class='dropdown-menu show-hide-column show-hide-position ${isDropdownPushedLeft}'></ul>
                                </span>`;

        if (gridId) {
            headTable.addClass("list-table not-select-text").append(showHideDropdown);
            openCloseDropdownDT();
            $('.show-hide-column').append(listElements);
            setCheckBoxes();
        }
        if (headTable.hasClass("dont-use-custom-hide") !== true)
            hideColumnsDT(hasDataInDB);

        positionShowHideColumnsMenu(headTable, $(".show-hide-column"));

        $(window).on('resize', function () {
            // recalculate menu position on resize
            positionShowHideColumnsMenu(headTable, $(".show-hide-column"));
        })
    });
}

/**
 * Calculates showhide columns menu position.
 * 
 * @param {any} headTable
 * @param {any} $showHideColumn
 */
function positionShowHideColumnsMenu(headTable, $showHideColumn) {
    var shDropdownMenuDT = document.getElementById("sh-dropdown-menu-DT");
    if (shDropdownMenuDT) {
        var width = $showHideColumn.innerWidth();
        var showHideDropdownElement = shDropdownMenuDT.getBoundingClientRect();
        var showHideDropdownTop = showHideDropdownElement.top;
        var showHideDropdownLeft = showHideDropdownElement.left - width;

        // Calculate showHideDropdown left position if datatable is in modal
        if (headTable.hasClass('modal-data-table')) {
            var modalDataTable = document.getElementById(gridId);
            var modalDataTableRect = modalDataTable.getBoundingClientRect();
            showHideDropdownLeft = modalDataTableRect.width - width;

            // Add modal padding around datatable 
            if (!isMobile() && !isTablet()) {
                showHideDropdownLeft += 15;
            }
        }

        $showHideColumn.css({ "left": showHideDropdownLeft, "top": showHideDropdownTop });
    }
}

// Add data-default-hidden="true" on columns that should be hidden on first load in DataTables
// Add data-visible="false" on columns that should be always hidden in DataTables
function hideColumnsDT(hasDataInDB) {
    var mainTable = $(".dataTable").DataTable();
    
    $('.dataTable:not(.side-table):first > thead > tr > th').each(function (index) {
        var isColVisibleOnFirstLoad = $(this).data("default-hidden");
        var isColVisible = $(this).data("visible");

        if ((isColVisibleOnFirstLoad == true || isColVisibleOnFirstLoad == "True") && !hasDataInDB) {
            mainTable.column(index).visible(false);
        }

        if (isColVisible == false || isColVisible == "False") {
            mainTable.column(index).visible(false);
        }
    });
}

var listElements = "";

function populateDropdownDT() {
    listElements = "";
    
    $('.dataTable:not(.side-table):first > thead > tr > th').each(function (index) {
        var isChecked = 0;
        var thNodeText = $(this).text().trim();
        var hidden = thNodeText == '' || thNodeText == null ? 'hidden' : '';
        var isColVisible = $(this).data("visible");

        if (isColVisible == false || isColVisible == "False" || listElements.indexOf("name='" + thNodeText + "'") >= 0) {
            return;
        }

        var dropdownElement = `
                <li class='${hidden}' style='padding: 4px 6px;'>
                    <label style='width: 100%' class='custom-checkbox-container'>
                        <input type='checkbox' data-column='${index}' name='${thNodeText}' class='custom-checkbox-DT' ${isChecked ? 'checked' : ''} />
                        ${thNodeText}
                        <span class="custom-checkbox-checkmark"></span>
                    </label>
                </li>`;

        listElements += dropdownElement;
    });

    return listElements;
};

function setCheckBoxes() {
    $('.dataTable:not(.side-table):first > thead > tr > th').each(function (index) {
        var thNodeText = $(this).text().trim();
        var defaultHidden = $(this).data("default-hidden");

        $("#sh-dropdown-menu-DT > ul > li > label > input[name='" + thNodeText + "']").attr("checked", true);

        if (defaultHidden && !hasDataInDB) {
            $("#sh-dropdown-menu-DT > ul > li > label > input[name='" + thNodeText + "']").attr("checked", false);
        }
    });
}

function openCloseDropdownDT() {
    $('#sh-dropdown-menu-DT a').on('click', function (event) {
        $(this).parent().toggleClass('open');
    });

    $('body').on('click', function (e) {
        if (!$('#sh-dropdown-menu-DT').is(e.target)
            && $('#sh-dropdown-menu-DT').has(e.target).length === 0
            && $('.open').has(e.target).length === 0
        ) {
            $('#sh-dropdown-menu-DT').removeClass('open');
        }
    });
}

// Show/hide column on click
$(document).on('click', '.custom-checkbox-DT', function () {
    var mainTable = $(".dataTable:last").DataTable();
    var thName = $(this).attr("name");

    if ($(this).is(':checked')) {
        $(this).prop('checked', true);
    } else {
        $(this).prop('checked', false);
    }

    editedDataTable = true;
      
    var column;
    var columns = mainTable.columns()[0];
    columns.forEach(function (index) {
        var columnHeader = mainTable.column([index]).header().textContent.trim();
        if (columnHeader === thName) {
            column = mainTable.column([index]);
        }
    });

    column.visible(!column.visible());
    $('.dataTable').DataTable().ajax.reload();
});