(function() {
  'use strict';

  /**
   *
   * Alerts Utility
   *  makes alerts interactive
   *
   * Attribute: uw-alerts
   *
   * Types of alerts:
   *   [default]
   *     Regular Info Alert
   *     Disappears automatically after 30 seconds
   *     Disappears after x seconds if explicitly specified via data-decay='x'
   *     Can be told not to disappear with data-decay='0'
   *
   *   [success]
   *     Currently no special visual appearance
   *     Disappears automatically after 30 seconds
   *
   *   [warning]
   *     Will be coloured warning-orange regardless of user's selected theme
   *     Does not disappear
   *
   *   [error]
   *     Will be coloured error-red regardless of user's selected theme
   *     Does not disappear
   *
   * Example usage:
   *  <div .alerts uw-alerts>
   *    <div .alerts__toggler>
   *      <div .alert.alert-info>
   *      <div .alert__closer>
   *      <div .alert__icon>
   *      <div .alert__content>
   *        This is some information
   *
   */

  var ALERTS_UTIL_NAME = 'alerts';
  var ALERTS_UTIL_SELECTOR = '[uw-alerts]';

  var ALERTS_INITIALIZED_CLASS = 'alerts--initialized';
  var ALERTS_TOGGLER_CLASS = 'alerts__toggler';
  var ALERTS_TOGGLER_VISIBLE_CLASS = 'alerts__toggler--visible';
  var ALERTS_TOGGLER_APPEAR_DELAY = 120;

  var ALERT_CLASS = 'alert';
  var ALERT_INITIALIZED_CLASS = 'alert--initialized';
  var ALERT_CLOSER_CLASS = 'alert__closer';
  var ALERT_INVISIBLE_CLASS = 'alert--invisible';
  var ALERT_AUTO_HIDE_DELAY = 10;
  var ALERT_AUTOCLOSING_MATCHER = '.alert-info, .alert-success';

  var alertsUtil = function(element) {
    var togglerCheckRequested = false;
    var togglerElement;
    var alertElements;

    function init() {
      if (!element) {
        throw new Error('Alerts util has to be called with an element!');
      }

      if (element.classList.contains(ALERTS_INITIALIZED_CLASS)) {
        return false;
      }

      togglerElement = element.querySelector('.' + ALERTS_TOGGLER_CLASS);
      alertElements = gatherAlertElements();

      initToggler();
      initAlerts();

      // mark initialized
      element.classList.add(ALERTS_INITIALIZED_CLASS);

      return {
        name: ALERTS_UTIL_NAME,
        element: element,
        destroy: function() {},
      };
    }

    function gatherAlertElements() {
      return Array.from(element.querySelectorAll('.' + ALERT_CLASS)).filter(function(alert) {
        return !alert.classList.contains(ALERT_INITIALIZED_CLASS);
      });
    }

    function initToggler() {
      togglerElement.addEventListener('click', function() {
        alertElements.forEach(function(alertEl) {
          toggleAlert(alertEl, true);
        });
        togglerElement.classList.remove(ALERTS_TOGGLER_VISIBLE_CLASS);
      });
      element.classList.add(ALERTS_INITIALIZED_CLASS);
    }

    function initAlerts() {
      alertElements.forEach(initAlert);
    }

    function initAlert(alertElement) {
      var autoHideDelay = ALERT_AUTO_HIDE_DELAY;
      if (alertElement.dataset.decay) {
        autoHideDelay = parseInt(alertElement.dataset.decay, 10);
      }

      var closeEl = alertElement.querySelector('.' + ALERT_CLOSER_CLASS);
      closeEl.addEventListener('click', function() {
        toggleAlert(alertElement);
      });

      if (autoHideDelay > 0 && alertElement.matches(ALERT_AUTOCLOSING_MATCHER)) {
        window.setTimeout(function() {
          toggleAlert(alertElement);
        }, autoHideDelay * 1000);
      }

      alertElement.classList.add(ALERTS_INITIALIZED_CLASS);
    }

    function toggleAlert(alertEl, visible) {
      alertEl.classList.toggle(ALERT_INVISIBLE_CLASS, !visible);
      checkToggler();
    }

    function checkToggler() {
      if (togglerCheckRequested) {
        return;
      }

      var alertsHidden = alertElements.reduce(function(acc, alert) {
        return acc && alert.classList.contains(ALERT_INVISIBLE_CLASS);
      }, true);

      window.setTimeout(function() {
        togglerElement.classList.toggle(ALERTS_TOGGLER_VISIBLE_CLASS, alertsHidden);
        togglerCheckRequested = false;
      }, ALERTS_TOGGLER_APPEAR_DELAY);
    }

    return init();
  };

  if (UtilRegistry) {
    UtilRegistry.register({
      name: ALERTS_UTIL_NAME,
      selector: ALERTS_UTIL_SELECTOR,
      setup: alertsUtil,
    });
  }
})();
