var filterTerms = {}
var filters = {}
$.fn.dataTable.ext.search.push(
    function (settings, data, dataIndex) {
        var isAllowed = true
        for (var i = 0; i < data.length; i++) {
            var filter = filters[i]
            if (filter && !filter(data[i], dataIndex)) {
                isAllowed = false
            }
        }

        return isAllowed
    }
)

function createStandardFilters(table, columns, items) {
    createTextFilter(table)
	
	createClearFilters()

    $.each(columns, function (index, column) {
        switch (column.type) {
            case "item":
            case "column":
            case "list":
            case "subnodes":
                createItemFilter(table, column, index, items)
                break
            default:
                hideFilter(column)
        }
    })
}

function createMasterDetailFilters(table, columns, items) {
    createTextFilter(table)
	
	createClearFilters()

    $.each(columns, function (index, column) {
        switch (column.type) {
            case "column":
                createColumnFilter(table, column, items)
                break
            case "item":
                createMasterDetailFilter(table, column, index, items)
                break
            default:
                hideFilter(column)
        }
    })
}

function createColumnFilter(table, column, items) {
    var element = $('#filter-' + column.name)

    var values = items
        .map(function (v) { return v.generatedColumns })
        .flat()
        .filter(distinct)
        .map(function (v) { return [v] })

    createFilterElements(element, column, values)

    element.find("input[type='checkbox']").each(function () {
        var tableColumn = table.column(this.value + ":name")
        $(this).prop("defaultChecked", tableColumn.visible())

        $(this).change(function () {
            tableColumn.visible(this.checked)
            table.draw() // To reapply filters
        })
    })
}

function createTextFilter(table) {
    $('#text-filter-input').keyup(function () {
        table.search(this.value).draw()
    })
    $('#text-filter-input').change(function () {
        table.search(this.value).draw()
    })
}

function createClearFilters() {
    $('#clear-filters-button').click(function() {
        $(".filter-content input[type='checkbox']").prop('checked', function() {
            return $(this).prop('defaultChecked')
        }).change()
        $('#text-filter-input').prop('value', '').change()
    })
}

function hideFilter(column) {
    var element = $('#filter-' + column.name)
    element.parent().hide()
}

function createItemFilter(table, column, columnIndex, items) {
    var element = $('#filter-' + column.name)

    var values = items.map(function (v) { return (v[column.name] || {}).content }).filter(exists)

    createFilterElements(element, column, values)

    element.find("input[type='checkbox']").change(function () {
        var selected = element.find("input:checked")
            .map(function () { return $(this).attr("value") })
            .get()

        filterTerms[column.name] = selected

        filters[columnIndex] = function (value, dataIndex) {
            return !selected.length || includes(selected, (items[dataIndex][column.name] || {content:[]}).content)
        }

        table.draw()
    })
}

function createMasterDetailFilter(table, column, columnIndex, items) {
    var element = $('#filter-' + column.name)

    var values = items.map(function (item) { return getRowValues(item) })

    createFilterElements(element, column, values)

    element.find("input[type='checkbox']").change(function () {
        var selected = element.find("input:checked")
            .map(function () { return $(this).attr("value") })
            .get()

        filterTerms[column.name] = selected

        filters[columnIndex] = function (value, dataIndex) {
            var item = items[dataIndex]

            var rowValues = getRowValues(item, function (c) { return table.column(c + ":name").visible() === true })

            return !selected.length || includes(selected, rowValues)
        }

        table.draw()
    })

    function getRowValues(item, predicate) {
        return item.generatedColumns
            .filter(function (c) { return !predicate || predicate(c) })
            .map(function (c) { return item[c][column.name] })
            .flat()
            .filter(function (v) { return v.length })
            .filter(distinct)
    }
}

function createFilterElements(element, column, values) {
	var template = '<div class="custom-control custom-checkbox {{default-hidden-filter}}"><input id="{{id}}" type="checkbox" class="custom-control-input" value="{{value}}"> <label for="{{id}}" class="custom-control-label">{{value}}</label></div>'

    var html = ''
    var allValues = []
    $.each(values, function (index, items) {
        $.each(items, function (i, item) {
            if (allValues.indexOf(item.trim()) == -1) {
                allValues.push(item.trim())
            }
        })
    })

    //allValues.sort()
	
	var visibleCount = 15

    $.each(allValues.filter(distinct), function (itemIndex, item) {
		var hiddenFilter = itemIndex < visibleCount ? "" : "default-hidden-filter" 
        var id = "filter-" + column.name + "-item-" + itemIndex
        html += template.replace(/{{default-hidden-filter}}/g, hiddenFilter).replace(/{{id}}/g, id).replace(/{{value}}/g, item)
    })
	
	if (allValues.length > visibleCount) {
		html += '<div class="show-all-filters-button"><a href="#">Show all</a></div>'
	}

    element.html(html)
	
	element.find(".show-all-filters-button > a").click(function () {
		element.addClass("show-hidden-filters")
	})

    element.find(".custom-control-label").each(function () {
        if (!$(this).text().length) {
            $(this).parent().hide()
        }
    })
}

function distinct(value, index, self) {
    return self.indexOf(value) === index
}

function exists(value) {
    return !!value
}

function includes(searchIn, searchFor) {
    if (!searchIn || !searchFor) return false
	
    var found = false
    $.each(searchIn, function (_i1, value1) {
        $.each(searchFor, function (_i2, value2) {
            if (value1.trim() == value2.trim()) {
                found = true
            }
        })
    })

    return found
}