var filterTerms = {};
var filters = {};
var filterRows = {};
const getTableID = () => "table-filter-" + $("body").attr("data-node-id");
const getTableSearchID = () => "table-search-" + $("body").attr("data-node-id");

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

  return isAllowed;
});

function createStandardFilters(table, tableType, columns, items) {
  handleNavigationCleanup();
  createTextFilter(table);
  createClearFilters()

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

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);
    }
  });
}

// Remove session storage based on ID
// if new link is opened or reload
function handleNavigationCleanup() {
  const shouldPerformCleanup = performance
  .getEntriesByType("navigation")
  .some((entry) => entry.type === "navigate" || entry.type === "reload");
 if (shouldPerformCleanup) {
 	sessionStorage.removeItem(getTableID());
	sessionStorage.removeItem(getTableSearchID());
 }
}

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 () {
    // Store search input for back/forward session on website
    sessionStorage.setItem(getTableSearchID(), this.value);
    table.search(this.value).draw();
  });
  $("#text-filter-input").change(function () {
    // Store search input for back/forward session on website
    sessionStorage.setItem(getTableSearchID(), this.value);
    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 applyFilter(table, column, columnIndex, items) {
  // Retrive search data if we have and apply filter.
  let searchValue = sessionStorage.getItem(getTableSearchID());
  if (getTableSearchID() in sessionStorage) {
    table.search(searchValue).draw();
  }
  // Retrive checked checkboxes value
  let sessionVal = sessionStorage.getItem(getTableID());

  if (sessionVal !== null && sessionVal !== undefined) {
    sessionVal = JSON.parse(sessionVal);
    let selectedValues = sessionVal[column.name];

    if (selectedValues !== undefined) {
      filterTerms[column.name] = selectedValues;
      filters[columnIndex] = function (value, dataIndex) {
        return (
          !selectedValues.length ||
          includes(
            selectedValues,
            column.name === "title"
              ? [items[dataIndex].title]
              : (items[dataIndex][column.name] || { content: [] }).content
          )
        );
      };
    }
  }
}
function hideFilter(column) {
  var element = $("#filter-" + column.name);
  element.parent().hide();
}

/** Only allow one title to be selected at a time.
    Uncheck all other if there is already one active */
function filterTypeCheck(column) {
  var className = ".filter-" + column.name + "-item";
    $("input[type='checkbox']").change(function () {
    if (column.filterType == "single") {
      let checked = $(className).is(":checked");
      if (checked) {
        $(className).not(this).prop("checked", false);
      }
    }
  });
}

function createItemFilter(table, tableType, column, columnIndex, items) {
  var element = $("#filter-" + column.name);
  var values = items
    .map(function (v) {
      return column.name === "title"
        ? [v.title]
        : (v[column.name] || {}).content;
    })
    .filter(exists);

  createFilterElements(element, column, values);
  filterTypeCheck(column);

  element.find("input[type='checkbox']").change(function () {
    var selected = element
      .find("input:checked")
      .map(function () {
        return $(this).attr("value");
      })
      .get();
    filterTerms[column.name] = selected;
    // Table ID to determine which session-storage belongs to wich table
    sessionStorage.setItem(getTableID(), JSON.stringify(filterTerms));

    if (tableType === "show-when-filtered") {
      toggleShowTable();
    }
    filters[columnIndex] = function (value, dataIndex) {
      return (
        !selected.length ||
        includes(
          selected,
          column.name === "title"
            ? [items[dataIndex].title]
            : (items[dataIndex][column.name] || { content: [] }).content
        )
      );
    };

    table.draw();
  });
}

function toggleShowTable() {
  // We find all selected checkboxes to show table if we have multiple choices
  let selectedChoices = [];
  $("input[type='checkbox']:checked").each(function () {
  selectedChoices.push($(this).val());
  });

  // Hide/show the table
  if (selectedChoices.length) {
    $("#datatable").show();
  } else {
    $("#datatable").hide();
  }
}

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 {{class}}" 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 = 5;

  $.each(allValues.filter(distinct), function (itemIndex, item) {
    var hiddenFilter = itemIndex < visibleCount ? "" : "default-hidden-filter";
    var id = "filter-" + column.name + "-item-" + itemIndex;
    var class_ = "filter-" + column.name + "-item";

    html += template
      .replace(/{{default-hidden-filter}}/g, hiddenFilter)
      .replace(/{{id}}/g, id)
      .replace(/{{class}}/g, class_)
      .replace(/{{value}}/g, item);
  });

  html +=
    '<div class="show-all-filters-button"><a href="#">' +
    getTranslation("ShowMore", "Show all") +
    "</a></div>";
  html +=
    '<div class="show-less-filters-button"><a href="#">' +
    getTranslation("ShowLess", "Show less") +
    "</a></div>";

  if (allValues.length > visibleCount) {
    element.addClass("has-hidden-items");
  }

  element.html(html);

  // Adding new classes for filter-options

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

  element.find(".show-less-filters-button > a").click(function () {
    element.removeClass("show-hidden-filters");
  });

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

function updateFilterVisibility(columns) {
  for (var columnIndex = 0; columnIndex < columns.length; columnIndex++) {
    var allowedColumnFilters = [];
    for (var key in filterRows) {
      if (
        filterRows[key]
          .filter((_, filterColumnIndex) => columnIndex != filterColumnIndex)
          .every((x) => x.isAllowed)
      ) {
        allowedColumnFilters.push(
          filterRows[key][columnIndex].value.split(",").map((m) => m.trim())
        );
      }
    }

    allowedColumnFilters = allowedColumnFilters.flat();

    var visibleItems = 0;
    var maxVisibleItems = 5;

    $(".filter-" + columns[columnIndex].name + "-item").each(function (
      itemIndex,
      item
    ) {
      if (allowedColumnFilters.includes(item.value)) {
        $(item).parent().removeClass("always-hidden-filter");

        visibleItems++;
        if (visibleItems > maxVisibleItems) {
          $(item).parent().addClass("default-hidden-filter");
        } else {
          $(item).parent().removeClass("default-hidden-filter");
        }
      } else {
        $(item).parent().addClass("always-hidden-filter");
        $(item).parent().removeClass("default-hidden-filter");
      }
    });

    if (visibleItems > maxVisibleItems) {
      $("#filter-" + columns[columnIndex].name).addClass("has-hidden-items");
    } else {
      $("#filter-" + columns[columnIndex].name).removeClass("has-hidden-items");
    }
  }
}

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;
}
