(function collonadeClosure() {
  'use strict';

  window.utils = window.utils || {};

  window.utils.asyncTable = function(wrapper, options) {

    var tableIdent = wrapper.dataset.dbtIdent;
    var shortCircuitHeader = #{String (toPathPiece HeaderDBTableShortcircuit)};

    var ths = [];
    var pageLinks = [];
    var pagesizeForm;
    var scrollTable;

    function init() {
    var table = wrapper.querySelector('#' + tableIdent);
      if (!table) {
        return;
      }

      scrollTable = wrapper.querySelector('.scrolltable');

      // sortable table headers
      ths = Array.from(table.querySelectorAll('th.sortable')).map(function(th) {
        return { element: th };
      });

      // pagination links
      var pagination = wrapper.querySelector('#' + tableIdent + '-pagination');
      if (pagination) {
        pageLinks = Array.from(pagination.querySelectorAll('.page-link')).map(function(link) {
          return { element: link };
        });
      }

      // pagesize form
      pagesizeForm = wrapper.querySelector('#' + tableIdent + '-pagesize-form');

      // take options into account
      if (options && options.scrollTo) {
        window.scrollTo(options.scrollTo);
      }

      if (options && options.horizPos && scrollTable) {
        scrollTable.scrollLeft = options.horizPos;
      }

      setupListeners();
      wrapper.classList.add('js-initialized');
    }

    function setupListeners() {
      ths.forEach(function(th) {
        th.clickHandler = function(event) {
          var boundClickHandler = clickHandler.bind(this);
          var horizPos = (scrollTable || {}).scrollLeft;
          boundClickHandler(event, { horizPos });
        };
        th.element.addEventListener('click', th.clickHandler);
      });

      pageLinks.forEach(function(link) {
        link.clickHandler = function(event) {
          var boundClickHandler = clickHandler.bind(this);
          var wrapperBoundingRect = wrapper.getBoundingClientRect();
          var options = {};
          if (wrapperBoundingRect.top < 160) {
            options.scrollTo = {
              top: (wrapper.offsetTop || 0) - 60,
              left: wrapper.offsetLeft || 0,
              behavior: 'smooth',
            };
          }
          boundClickHandler(event, options);
        }
        link.element.addEventListener('click', link.clickHandler);
      });

      if (pagesizeForm) {
        var pagesizeSelect = pagesizeForm.querySelector('[name=' + tableIdent + '-pagesize]');
        pagesizeSelect.addEventListener('change', changePagesizeHandler);
      }
    }

    function removeListeners() {
      ths.forEach(function(th) {
        th.element.removeEventListener('click', th.clickHandler);
      });

      pageLinks.forEach(function(link) {
        link.element.removeEventListener('click', link.clickHandler);
      });

      if (pagesizeForm) {
        var pagesizeSelect = pagesizeForm.querySelector('[name=' + tableIdent + '-pagesize]')
        pagesizeSelect.removeEventListener('change', changePagesizeHandler);
      }
    }

    function clickHandler(event, options) {
      event.preventDefault();
      var url = new URL(window.location.origin + window.location.pathname + getClickDestination(this));
      updateTableFrom(url, options);
    }

    function getClickDestination(el) {
      if (!el.querySelector('a')) {
        return '';
      }
      return el.querySelector('a').getAttribute('href');
    }

    function changePagesizeHandler(event) {
      var currentTableUrl = wrapper.dataset.currentUrl || window.location.href;
      var url = getUrlWithUpdatedPagesize(currentTableUrl, event.target.value);
      url = getUrlWithResetPagenumber(url);
      updateTableFrom(url);
    }

    function getUrlWithUpdatedPagesize(url, pagesize) {
      if (url.indexOf('pagesize') >= 0) {
        return url.replace(/pagesize=(\d+|all)/, 'pagesize=' + pagesize);
      } else if (url.indexOf('?') >= 0) {
        return url += '&' + tableIdent + '-pagesize=' + pagesize;
      }

      return url += '?' + tableIdent + '-pagesize=' + pagesize;
    }

    function getUrlWithResetPagenumber(url) {
      return url.replace(/-page=\d+/, '-page=0');
    }

    function updateWrapperContents(newHtml, options) {
      wrapper.innerHTML = newHtml;
      wrapper.classList.remove("js-initialized");

      // setup the wrapper and its components to behave async again
      window.utils.asyncTable(wrapper, options);

      // make sure to hide any new submit buttons
      document.dispatchEvent(new CustomEvent('setup', {
        detail: {
          scope: wrapper,
          module: 'autoSubmit'
        }
      }));
    }

    // fetches new sorted table from url with params and replaces contents of current table
    function updateTableFrom(url, options) {

      fetch(url, {
        credentials: 'same-origin',
        headers: {
          'Accept': 'text/html',
          [shortCircuitHeader]: tableIdent
        }
      }).then(function(response) {
        if (!response.ok) {
          throw new Error('Looks like there was a problem fetching ' + url + '. Status Code: ' + response.status);
        }
        return response.text();
      }).then(function(data) {
        wrapper.dataset.currentUrl = url;
        removeListeners();
        updateWrapperContents(data, options);
      }).catch(function(err) {
        console.error(err);
      });
    }

    init();
  };
})();

document.addEventListener('DOMContentLoaded', function() {
  var dbtIdent = #{String $ dbtIdent};
  var selector = '#' + dbtIdent + '-table-wrapper:not(.js-initialized)';
  var wrapper = document.querySelector(selector);
  if (wrapper) {
    wrapper.dataset.dbtIdent = dbtIdent;
    window.utils.asyncTable(wrapper);
  }
});
