(function() {
  'use strict';

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

  window.utils.modal = function(modal) {
    var overlay = document.createElement('div');
    var closer = document.createElement('div');
    var trigger = document.querySelector('#' + modal.dataset.trigger);
    // var origParent = modal.parentNode;

    function open(event) {
      if (!modal.classList.contains('js-modal-initialized')) {
        return;
      }

      // disable modals for narrow screens
      if (event) {
        event.preventDefault();
      }
      modal.classList.add('modal--open');
      overlay.classList.add('modal__overlay');
      // document.body.insertBefore(modal, null);
      document.body.insertBefore(overlay, modal);
      overlay.classList.add('modal__overlay--open');

      if ('closeable' in modal.dataset) {
        closer.classList.add('modal__closer');
        modal.insertBefore(closer, null);
        closer.addEventListener('click', close, false);
        overlay.addEventListener('click', close, false);
      }
    }

    // you can open this modal via event
    // example: document.dispatchEvent(new CustomEvent('modal-open', { details: { for: 'modal-[id]' }}))
    function openOnEvent(event) {
      if (event.detail.for === modal.getAttribute('id')) {
        open();
      }
    }

    function close(event) {
      overlay.remove();
      // origParent.insertBefore(modal, null);
      modal.classList.remove('modal--open');
      closer.removeEventListener('click', close, false);
    };

    function setup() {
      document.body.insertBefore(modal, null);

      // every modal can be openend via document-wide event, see openOnEvent
      document.addEventListener('modal-open', openOnEvent, false);

      if ('dynamic' in modal.dataset) {
        function fetchModal(url, init) {
          function responseHtml(body) {
            var modalContent = document.createElement('div');
            modalContent.innerHTML = body;

            var contentBody = modalContent.querySelector('.main__content-body');
            var scriptTags = [];
            if (contentBody) {
              modalContent.querySelectorAll('script').forEach(function(scriptTag) {
                var existsAlready = Array.from(document.body.querySelectorAll('script')).some(function(haystack) {
                  if (haystack.text === scriptTag.text && haystack.getAttribute('src') === scriptTag.getAttribute('src')) {
                    scriptTags.push(haystack);
                    return true;
                  } else {
                    return false;
                  }
                });
                if (existsAlready)
                  return;

                var scriptClone = document.createElement('script');
                if (scriptTag.text)
                  scriptClone.text = scriptTag.text;
                if (scriptTag.hasAttributes()) {
                  var attrs = scriptTag.attributes;
                  for (var i = attrs.length - 1; i >= 0; i--) {
                    scriptClone.setAttribute(attrs[i].name, attrs[i].value);
                  }
                }

                document.body.insertBefore(scriptClone, null);
                scriptTags.push(scriptClone);
              });

              modalContent.querySelectorAll('style').forEach(function(styleTag) {
                if (Array.from(document.head.querySelectorAll('style')).some(function(haystack) {
                  return haystack.innerText === styleTag.innerText;
                })) { return }

                document.head.insertBefore(styleTag, null);
              });

              modalContent.querySelectorAll('link').forEach(function(linkTag) {
                if (linkTag.getAttribute('rel') !== 'stylesheet')
                  return;

                if (Array.from(document.head.querySelectorAll('link')).some(function(haystack) {
                  return haystack.getAttribute('href') === linkTag.getAttribute('href');
                })) { return }


                document.head.insertBefore(linkTag, null);
              });

              var modalAlertsEl = modalContent.querySelector('#alerts');
              var alertsEl = document.body.querySelector('#alerts');
              if (alertsEl && modalAlertsEl) {
                var modalAlerts = Array.from(modalAlertsEl.childNodes);

                modalAlerts.forEach(function(alertEl) {
                  alertsEl.insertBefore(alertEl, alertsEl.querySelector('.alerts__toggler'));
                });

                if (modalAlerts.length !== 0)
                  document.dispatchEvent(new CustomEvent('setup', { detail: { scope: alertsEl } }));

                contentBody.removeChild(modalAlertsEl);
              }

              modalContent = contentBody;
            }
            modalContent.classList.add('modal__content');

            var nudgeAttr = function(attr, x) {
              var oldVal = x.getAttribute(attr);
              var newVal = modal.getAttribute('id') + '__' + oldVal;

              // console.log(oldVal, newVal);
              x.setAttribute(attr, newVal);
            };

            var idAttrs = ['id', 'for', 'data-conditional-id'];
            idAttrs.map(function(attr) {
              modalContent.querySelectorAll('[' + attr + ']').forEach(function(x) { nudgeAttr(attr, x); });
            });

            modal.querySelectorAll('.modal__content').forEach(function(prev) { modal.removeChild(prev); });
            modal.insertBefore(modalContent, null);

            var triggerContentLoad = function() {
              console.log('contentReady', modal);

              document.dispatchEvent(new CustomEvent('setup', {
                detail: { scope: modal },
                bubbles: true,
                cancelable: true
              }));
            }

            scriptTags.forEach(function(t) { t.addEventListener('load', triggerContentLoad); });
            triggerContentLoad();

            return 'html';
          }

          function responseJson(data) {
            var alertsEl = document.querySelector('#alerts');
            if (!alertsEl)
              return null;

            for (var i = 0; i < data.length; i++) {
              var alert = document.createElement('div');
              alert.classList.add('alert', 'alert-' + data[i].class);
              var alertContent = document.createElement('div');
              alertContent.classList.add('alert__content');
              alertContent.innerHTML = data[i].content;
              alert.appendChild(alertContent);

              alertsEl.insertBefore(alert, alertsEl.querySelector('.alerts__toggler'));
            }

            document.dispatchEvent(new CustomEvent('setup', { detail: { scope: alertsEl }, bubbles: true, cancelable: true }));

            return 'json';
          }


          return fetch(url, init).then(function(response) {
            var contentType = response.headers.get('Content-Type')
            if (contentType && contentType.includes('text/html')) {
              return response.text().then(responseHtml);
            } else if (contentType && contentType.includes('application/json')) {
              return response.json().then(responseJson);
            } else {
              console.log(response);
              return null;
            }
          });
        };

        modal.addEventListener('modal-fetch', function(event) {
          var dynamicContentURL = (event.detail && event.detail.url) || trigger.getAttribute('href');

          var fetchInit = (event.detail && event.detail.init) || {
            credentials: 'same-origin',
            headers: {
              #{String (toPathPiece HeaderIsModal)}: 'True'
            }
          };

          if (dynamicContentURL.length > 0) {
            fetchModal(dynamicContentURL, fetchInit).then((event.detail && event.detail.then) || (function(){}));
          }
        });
        modal.dispatchEvent(new CustomEvent('modal-fetch', {
          detail: {
            then: (function() {
              if (!trigger)
                return;

              trigger.classList.add('modal__trigger');
              trigger.addEventListener('click', open, false);
            })
          }
        }));
      } else if (trigger) { // if modal has trigger assigned to it open modal on click
        trigger.classList.add('modal__trigger');
        trigger.addEventListener('click', open, false);
      }


      // tell further modals, that this one already got initialized
      modal.classList.add('js-modal-initialized');

      modal.addEventListener('modal-close', close);
    }

    setup();
  };

  window.utils.ajaxSubmit = function(modal, form) {
    function doSubmit(event) {
      event.preventDefault();

      var modalContent = modal.querySelector('.modal__content');
      modalContent.style.pointerEvents = 'none';
      modalContent.style.opacity = 0.5;

      modal.dispatchEvent(new CustomEvent('modal-fetch', {
        detail: {
          url: form.target,
          init: {
            credentials: 'same-origin',
            headers: {
              #{String (toPathPiece HeaderIsModal)}: 'True'
            },
            method: form.method,
            body: new FormData(form)
          },
          then: (function(typ) {
            modal.dispatchEvent(new CustomEvent('modal-close'));

            modalContent.style.pointerEvents = 'auto';
            modalContent.style.opacity = 1;

            if (typ === 'json') {
              modal.dispatchEvent(new CustomEvent('modal-fetch'));
            }
          })
        },
        bubbles: true,
        cancelable: true
      }));
    };

    form.addEventListener('submit', doSubmit);
    form.classList.add('js-ajax-initialized');
  };
})();

document.addEventListener('setup', function(e) {
  if (e.detail.module && e.detail.module !== 'modal')
    return;

  Array.from(e.detail.scope.querySelectorAll('.js-modal:not(.js-modal-initialized)')).forEach(function(modal) {
    window.utils.modal(modal);
  });

  if (e.detail.scope.classList.contains('js-modal')) {
    Array.from(e.detail.scope.querySelectorAll('form[data-ajax-submit]:not(.js-ajax-initialized)')).forEach(function(form) {
      window.utils.ajaxSubmit(e.detail.scope, form);
    });
  } else {
    Array.from(e.detail.scope.querySelectorAll('.js-modal')).map(function(modal) {
      Array.from(modal.querySelectorAll('form[data-ajax-submit]:not(.js-ajax-initialized)')).forEach(function(form) {
        window.utils.ajaxSubmit(modal, form);
      });
    });
  };
}, false);

document.addEventListener('DOMContentLoaded', function() {
  document.dispatchEvent(new CustomEvent('setup', { detail: { scope: document.body, module: 'modal' }, bubbles: true, cancelable: true }))
});
