import { Utility } from '../../core/utility';
import './modal.sass';

const MODAL_HEADERS = {
  'Is-Modal': 'True',
};

const MODAL_INITIALIZED_CLASS = 'modal--initialized';
const MODAL_CLASS = 'modal';
const MODAL_OPEN_CLASS = 'modal--open';
const MODAL_TRIGGER_CLASS = 'modal__trigger';
const MODAL_CONTENT_CLASS = 'modal__content';
const MODAL_OVERLAY_CLASS = 'modal__overlay';
const MODAL_OVERLAY_OPEN_CLASS = 'modal__overlay--open';
const MODAL_CLOSER_CLASS = 'modal__closer';

const MAIN_CONTENT_CLASS = 'main__content-body';

// one singleton wrapper to keep all the modals to avoid CSS bug
// with blurry text due to `transform: translate(-50%, -50%)`
// will be created (and reused) for the first modal that gets initialized
const MODALS_WRAPPER_CLASS = 'modals-wrapper';
const MODALS_WRAPPER_SELECTOR = '.' + MODALS_WRAPPER_CLASS;
const MODALS_WRAPPER_OPEN_CLASS = 'modals-wrapper--open';

@Utility({
  selector: '[uw-modal]',
})
export class Modal {

  _element;
  _app;

  _modalsWrapper;
  _modalOverlay;
  _modalUrl;

  constructor(element, app) {
    if (!element) {
      throw new Error('Modal utility cannot be setup without an element!');
    }

    this._element = element;
    this._app = app;

    if (this._element.classList.contains(MODAL_INITIALIZED_CLASS)) {
      return false;
    }

    this._ensureModalWrapper();

    // param modalTrigger
    if (!this._element.dataset.modalTrigger) {
      throw new Error('Modal utility cannot be setup without a trigger element!');
    } else {
      this._setupTrigger();
    }

    // param modalCloseable
    if (this._element.dataset.modalCloseable !== undefined) {
      this._setupCloser();
    }

    // mark as initialized and add modal class for styling
    this._element.classList.add(MODAL_INITIALIZED_CLASS, MODAL_CLASS);
  }

  destroy() {
    // TODO
  }

  _ensureModalWrapper() {
    this._modalsWrapper = document.querySelector(MODALS_WRAPPER_SELECTOR);
    if (!this._modalsWrapper) {
      // create modal wrapper
      this._modalsWrapper = document.createElement('div');
      this._modalsWrapper.classList.add(MODALS_WRAPPER_CLASS);
      document.body.appendChild(this._modalsWrapper);
    }

    this._modalOverlay = this._modalsWrapper.querySelector('.' + MODAL_OVERLAY_CLASS);
    if (!this._modalOverlay) {
      // create modal overlay
      this._modalOverlay = document.createElement('div');
      this._modalOverlay.classList.add(MODAL_OVERLAY_CLASS);
      this._modalsWrapper.appendChild(this._modalOverlay);
    }
  }

  _setupTrigger() {
    let triggerSelector = this._element.dataset.modalTrigger;
    if (!triggerSelector.startsWith('#')) {
      triggerSelector = '#' + triggerSelector;
    }
    const triggerElement = document.querySelector(triggerSelector);

    if (!triggerElement) {
      throw new Error('Trigger element for Modal not found: "' + triggerSelector + '"');
    }

    triggerElement.classList.add(MODAL_TRIGGER_CLASS);
    triggerElement.addEventListener('click', this._onTriggerClicked, false);
    this._modalUrl = triggerElement.getAttribute('href');
  }

  _setupCloser() {
    const closerElement = document.createElement('div');
    this._element.insertBefore(closerElement, null);
    closerElement.classList.add(MODAL_CLOSER_CLASS);
    closerElement.addEventListener('click', this._onCloseClicked, false);
    this._modalOverlay.addEventListener('click', this._onCloseClicked, false);
  }

  _onTriggerClicked = (event) => {
    event.preventDefault();
    this._open();
  }

  _onCloseClicked = (event) => {
    event.preventDefault();
    this._close();
  }

  _onKeyUp = (event) => {
    if (event.key === 'Escape') {
      this._close();
    }
  }

  _open() {
    this._element.classList.add(MODAL_OPEN_CLASS);
    this._modalOverlay.classList.add(MODAL_OVERLAY_OPEN_CLASS);
    this._modalsWrapper.classList.add(MODALS_WRAPPER_OPEN_CLASS);
    this._modalsWrapper.appendChild(this._element);

    if (this._modalUrl) {
      this._fillModal(this._modalUrl);
    }

    document.addEventListener('keyup', this._onKeyUp);
  }

  _close() {
    this._modalOverlay.classList.remove(MODAL_OVERLAY_OPEN_CLASS);
    this._element.classList.remove(MODAL_OPEN_CLASS);
    this._modalsWrapper.classList.remove(MODALS_WRAPPER_OPEN_CLASS);

    document.removeEventListener('keyup', this._onKeyUp);
  };

  _fillModal(url) {
    this._app.httpClient.get({
      url: url,
      headers: MODAL_HEADERS,
    }).then(
      (response) => this._app.htmlHelpers.parseResponse(response)
    ).then(
      (response) => this._processResponse(response.element)
    );
  }

  _processResponse(responseElement) {
    const modalContent = document.createElement('div');
    modalContent.classList.add(MODAL_CONTENT_CLASS);

    const contentBody = responseElement.querySelector('.' + MAIN_CONTENT_CLASS);

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

    const previousModalContent = this._element.querySelector('.' + MODAL_CONTENT_CLASS);
    if (previousModalContent) {
      previousModalContent.remove();
    }

    this._element.insertBefore(modalContent, null);

    // setup any newly arrived utils
    this._app.utilRegistry.initAll(this._element);
  }
}
