import { Utility } from '../../core/utility';
import * as defer from 'lodash.defer';
import { EventManager, EventWrapper, EVENT_TYPE } from '../../lib/event-manager/event-manager';

const FORM_ERROR_REPORTER_INITIALIZED_CLASS = 'form-error-remover--initialized';

@Utility({
  selector: 'input, textarea, select',
})
export class FormErrorReporter {
  _element;
  _err;

  _eventManager;

  constructor(element) {
    if (!element)
      throw new Error('Form Error Reporter utility needs to be passed an element!');

    this._element = element;

    this._eventManager = new EventManager();

    if (this._element.classList.contains(FORM_ERROR_REPORTER_INITIALIZED_CLASS))
      return;

    this._element.classList.add(FORM_ERROR_REPORTER_INITIALIZED_CLASS);
  }

  start() {
    if (this._element.willValidate) {
      let invalidElementEvent = new EventWrapper(EVENT_TYPE.INVALID, this.report.bind(this), this._element);
      this._eventManager.registerNewListener(invalidElementEvent);

      let changedElementEvent = new EventWrapper(EVENT_TYPE.CHANGE, () => { defer(this.report.bind(this)); }, this._element);
      this._eventManager.registerNewListener(changedElementEvent);
    }
  }

  destroy() {
    this._eventManager.removeAllEventListenersFromUtil();

    this._removeError();

    if(this._element.classList.contains(FORM_ERROR_REPORTER_INITIALIZED_CLASS))
      this._element.classList.remove(FORM_ERROR_REPORTER_INITIALIZED_CLASS);
  }

  report() {
    const msg = this._element.validity.valid ? null : this._element.validationMessage;

    const target = this._element.closest('.standalone-field, .form-group');

    if (!target)
      return;

    this._removeError();

    if (!msg) {
      target.classList.remove('standalone-field--has-error', 'form-group--has-error');
    } else {
      if (target.classList.contains('form-group')) {
        target.classList.add('form-group--has-error');

        const container = target.querySelector('.form-group__input');
        if (container) {
          this._err = document.createElement('div');
          this._err.classList.add('form-error');
          this._err.innerText = msg;
          container.appendChild(this._err);
        }
      } else {
        target.classList.add('standalone-field--has-error');

        this._err = document.createElement('div');
        this._err.classList.add('standalone-field__error');
        this._err.innerText = msg;
        target.appendChild(this._err);
      }
    }
  }

  _removeError() {
    if (this._err && this._err.parentNode) {
      this._err.parentNode.removeChild(this._err);
      this._err = undefined;
    }
  }
}
