(function (global) {
  global.ARQ = global.ARQ || {};
  ARQ.dialog = {
    open: function (opts) {
      var $root = $('#arq-modal-root');
      $root.empty();
      var $b = $('<div class="arq-modal-backdrop"/>');
      var $m = $('<div class="arq-modal"/>');
      $m.append($('<div class="arq-modal-header"/>').text(opts.title || ''));
      $m.append($('<div class="arq-modal-body"/>').append(opts.body));
      var $f = $('<div class="arq-modal-footer"/>');
      (opts.buttons || []).forEach(function (bt) {
        var $btn = $('<button type="button" class="arq-btn"/>').text(bt.label).addClass(bt.primary ? 'arq-btn--primary' : 'arq-btn--secondary');
        $btn.on('click', function () { bt.onClick && bt.onClick(); });
        $f.append($btn);
      });
      $m.append($f);
      $b.append($m);
      $root.append($b);
      $b.on('click', function (e) { if (e.target === $b[0]) opts.onCancel && opts.onCancel(); });
      return { close: function () { $root.empty(); } };
    },

    _tail: Promise.resolve(),
    _queue: function (fn) {
      var next = ARQ.dialog._tail.then(fn);
      ARQ.dialog._tail = next.catch(function () {});
      return next;
    },

    alert: function (message, opts) {
      return ARQ.dialog._queue(function () {
        return ARQ.dialog._openNative('alert', String(message || ''), opts || {});
      });
    },

    confirm: function (message, opts) {
      return ARQ.dialog._queue(function () {
        return ARQ.dialog._openNative('confirm', String(message || ''), opts || {});
      });
    },

    prompt: function (message, defaultValue, opts) {
      return ARQ.dialog._queue(function () {
        var o = Object.assign({}, opts || {}, { defaultValue: defaultValue != null ? String(defaultValue) : '' });
        return ARQ.dialog._openNative('prompt', String(message || ''), o);
      });
    },

    _openNative: function (mode, message, opts) {
      opts = opts || {};
      return new Promise(function (resolve) {
        var dlg = document.getElementById('arqNativeDialog');
        if (!dlg) {
          dlg = document.createElement('dialog');
          dlg.id = 'arqNativeDialog';
          dlg.className = 'arq-native-dialog';
          dlg.setAttribute('aria-modal', 'true');
          dlg.innerHTML =
            '<div class="arq-modal arq-native-dialog__panel">' +
            '<div class="arq-modal-header arq-native-dialog__header">' +
            '<span class="arq-native-dialog__icon" id="arqNativeDialogIcon" aria-hidden="true"><i class="fas fa-info-circle"></i></span>' +
            '<span class="arq-native-dialog__title" id="arqNativeDialogTitleText"></span>' +
            '<button type="button" class="arq-native-dialog__close" id="arqNativeDialogClose" data-arq-native="close" aria-label="Cerrar" title="Cerrar">' +
            '<i class="fas fa-times" aria-hidden="true"></i>' +
            '</button>' +
            '</div>' +
            '<div class="arq-modal-body">' +
            '<p class="arq-native-dialog__msg" id="arqNativeDialogMsg"></p>' +
            '<div id="arqNativeDialogField" hidden>' +
            '<label class="arq-label" for="arqNativeDialogInput" id="arqNativeDialogLabel"></label>' +
            '<input type="text" class="arq-input" id="arqNativeDialogInput" autocomplete="off" />' +
            '</div></div>' +
            '<div class="arq-modal-footer">' +
            '<button type="button" class="arq-btn arq-btn--secondary" data-arq-native="cancel">Cancelar</button>' +
            '<button type="button" class="arq-btn arq-btn--primary" data-arq-native="ok">Aceptar</button>' +
            '</div></div>';
          document.body.appendChild(dlg);
        }
        var titleTextEl = document.getElementById('arqNativeDialogTitleText');
        var iconEl = document.getElementById('arqNativeDialogIcon');
        var msgEl = document.getElementById('arqNativeDialogMsg');
        var fieldWrap = document.getElementById('arqNativeDialogField');
        var inputEl = document.getElementById('arqNativeDialogInput');
        var okBtn = dlg.querySelector('[data-arq-native="ok"]');
        var cancelBtn = dlg.querySelector('[data-arq-native="cancel"]');
        var closeBtn = dlg.querySelector('[data-arq-native="close"]');
        var finished = false;
        function closeDlg() {
          try {
            if (dlg.open) dlg.close();
          } catch (e) {}
        }
        function done(val) {
          if (finished) return;
          finished = true;
          closeDlg();
          resolve(val);
        }
        var resolvedType = opts.type || (ARQ.feedback && ARQ.feedback.detectType
          ? ARQ.feedback.detectType(message, mode)
          : 'info');
        dlg.dataset.type = resolvedType;
        if (iconEl) {
          var iconClass = (ARQ.feedback && ARQ.feedback.iconClass)
            ? ARQ.feedback.iconClass(resolvedType)
            : 'fas fa-info-circle';
          iconEl.innerHTML = '<i class="' + iconClass + '" aria-hidden="true"></i>';
        }
        if (titleTextEl) {
          var baseTitle = opts.title || (ARQ.feedback && ARQ.feedback.title
            ? ARQ.feedback.title(resolvedType)
            : (mode === 'alert' ? 'Aviso' : mode === 'confirm' ? 'Confirmar' : 'Entrada'));
          titleTextEl.textContent = baseTitle;
        }
        if (cancelBtn) cancelBtn.style.display = mode === 'alert' ? 'none' : '';
        if (okBtn) {
          var defaultOk = resolvedType === 'danger' ? 'Eliminar'
            : resolvedType === 'trash' ? 'Mover a papelera'
            : 'Aceptar';
          okBtn.textContent = opts.okLabel || (mode === 'alert' ? 'Aceptar' : defaultOk);
          okBtn.classList.remove('arq-btn--danger');
          okBtn.classList.remove('arq-btn--trash');
        }
        if (msgEl) {
          msgEl.textContent = message;
          msgEl.style.display = '';
        }
        if (fieldWrap) fieldWrap.hidden = mode !== 'prompt';
        if (inputEl && mode === 'prompt') {
          inputEl.value = opts.defaultValue || '';
        }
        function unbind() {
          dlg.removeEventListener('close', onClose);
          okBtn.removeEventListener('click', onOk);
          if (cancelBtn) cancelBtn.removeEventListener('click', onCancelClick);
          if (closeBtn) closeBtn.removeEventListener('click', onCancelClick);
        }
        function onOk() {
          unbind();
          if (mode === 'prompt') done(inputEl ? inputEl.value : '');
          else if (mode === 'confirm') done(true);
          else done(undefined);
        }
        function onCancelClick() {
          unbind();
          if (mode === 'confirm') done(false);
          else if (mode === 'prompt') done(null);
          else done(undefined);
        }
        function onClose() {
          okBtn.removeEventListener('click', onOk);
          if (cancelBtn) cancelBtn.removeEventListener('click', onCancelClick);
          if (closeBtn) closeBtn.removeEventListener('click', onCancelClick);
          if (finished) return;
          if (mode === 'confirm') done(false);
          else if (mode === 'prompt') done(null);
          else done(undefined);
        }
        okBtn.addEventListener('click', onOk);
        if (cancelBtn) cancelBtn.addEventListener('click', onCancelClick);
        if (closeBtn) closeBtn.addEventListener('click', onCancelClick);
        dlg.addEventListener('close', onClose, { once: true });
        try {
          if (typeof dlg.showModal === 'function') {
            dlg.showModal();
            if (mode === 'prompt' && inputEl) {
              setTimeout(function () {
                try {
                  inputEl.focus();
                  inputEl.select();
                } catch (e) {}
              }, 0);
            }
          } else {
            if (mode === 'confirm') done(global.confirm(message));
            else if (mode === 'prompt') done(global.prompt(message, opts.defaultValue));
            else {
              global.alert(message);
              done(undefined);
            }
          }
        } catch (e) {
          done(mode === 'confirm' ? false : mode === 'prompt' ? null : undefined);
        }
      });
    },
  };
})(typeof window !== 'undefined' ? window : this);
