(function() {
  'use strict';

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

  var JS_INITIALIZED_CLASS = 'js-modal-initialized';
  var MODAL_OPEN_CLASS = 'modal--open';
  var MODAL_TRIGGER_CLASS = 'modal__trigger';
  var MODAL_CONTENT_CLASS = 'modal__content';
  var MAIN_CONTENT_CLASS = 'main__content-body'
  var MODAL_CLOSABLE_FLAG = 'closeable';
  var MODAL_DYNAMIC_FLAG = 'dynamic';
  var MODAL_HEADERS = {
    'Is-Modal': 'True',
  };
  var OVERLAY_CLASS = 'modal__overlay';
  var OVERLAY_OPEN_CLASS = 'modal__overlay--open';
  var CLOSER_CLASS = 'modal__closer';

  window.utils.modal = function(modalElement, options) {

    if (!modalElement || modalElement.classList.contains(JS_INITIALIZED_CLASS)) {
      return;
    }

    var utilInstances = [];

    var overlayElement = document.createElement('div');
    var closerElement = document.createElement('div');
    var triggerElement = document.querySelector('#' + modalElement.dataset.trigger);

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

      setupForm();
      setupCloser();

      triggerElement.classList.add(MODAL_TRIGGER_CLASS);
      triggerElement.addEventListener('click', openHandler, false);

      modalElement.classList.add(JS_INITIALIZED_CLASS);
    }

    function openHandler(event) {
      event.preventDefault();
      open();
    }

    function open() {
      modalElement.classList.add(MODAL_OPEN_CLASS);
      overlayElement.classList.add(OVERLAY_CLASS);
      document.body.insertBefore(overlayElement, modalElement);
      overlayElement.classList.add(OVERLAY_OPEN_CLASS);

      var modalUrl = triggerElement.getAttribute('href');
      if (modalUrl && MODAL_DYNAMIC_FLAG in modalElement.dataset) {
        fillModal(modalUrl);
      }

      document.addEventListener('keyup', keyupHandler);
    }

    function closeHandler(event) {
      event.preventDefault();
      close();
    }

    function close() {
      overlayElement.classList.remove(OVERLAY_OPEN_CLASS);
      modalElement.classList.remove(MODAL_OPEN_CLASS);

      document.removeEventListener('keyup', keyupHandler);
    };

    function setupForm() {
      var form = modalElement.querySelector('form');
      if (form) {
        utilInstances.push(window.utils.setup('form', form, { headers: MODAL_HEADERS, force: true }));
      }
    }

    function setupCloser() {
      if (MODAL_CLOSABLE_FLAG in modalElement.dataset) {
        modalElement.insertBefore(closerElement, null);
        closerElement.classList.add(CLOSER_CLASS);
        closerElement.addEventListener('click', closeHandler, false);
        overlayElement.addEventListener('click', closeHandler, false);
      }
    }

    function fillModal(url) {
      if (!window.utils.httpClient) {
        throw new Error('httpClient not found! Can\' fetch modal content from ' + url);
      }

      window.utils.httpClient.get(url, MODAL_HEADERS)
        .then(function(response) {
          response.text().then(processResponse);
        });
    }

    function processResponse(reponseBody) {
      var modalContent = document.createElement('div');
      modalContent.classList.add(MODAL_CONTENT_CLASS);
      modalContent.innerHTML = reponseBody;

      var contentBody = modalContent.querySelector('.' + MAIN_CONTENT_CLASS);

      if (contentBody) {
        modalContent.innerHTML = contentBody.innerHTML;
      }

      var previousModalContent = modalElement.querySelector('.' + MODAL_CONTENT_CLASS);
      if (previousModalContent) {
        previousModalContent.remove();
      }

      modalContent = withPrefixedInputIDs(modalContent);
      modalElement.insertBefore(modalContent, null);
      setupForm();
    }

    function withPrefixedInputIDs(modalContent) {
      var idAttrs = ['id', 'for', 'data-conditional-id'];
      idAttrs.forEach(function(attr) {
        modalContent.querySelectorAll('[' + attr + ']').forEach(function(input) {
          var value = modalElement.id + '__' + input.getAttribute(attr);
          input.setAttribute(attr, value);
        });
      });
      return modalContent;
    }

    function keyupHandler(event) {
      if (event.key === 'Escape') {
        close();
      }
    }

    setup();

    function destroyUtils() {
      utilInstances.filter(function(utilInstance) {
        return !!utilInstance;
      }).forEach(function(utilInstance) {
        utilInstance.destroy();
      });
    }

    return {
      scope: modalElement,
      destroy: destroyUtils,
    };
  };
})();
