class Repeat {
  constructor(element, index) {
    this.element = element;
    this.index = index;
    this.length = element.children.length;
    this.getClone(element);
    this.checkEmpty();
  }

  getName(name) {
    const regex = /\[(\d+)\]/g;
    const matches = name.matchAll(regex);
    let index = 0;
    for (const match of matches) {
      if (this.index === index) {
        const before = name.substring(0, match.index);
        const after = name.substring(match.index + match[0].length);
        return before + "[{{INDEX}}]" + after;
      }
      index++;
    }
  }

  length() {
    return this.length;
  }

  setDisplay(el, selected, unselected) {
    var selectedElements = el.querySelectorAll(selected);
    var unselectedElements = el.querySelectorAll(unselected);

    selectedElements.forEach(function (element) {
      element.classList.add('d-none');
    });

    unselectedElements.forEach(function (element) {
      element.classList.remove('d-none');
    });
  }

  getClone(element) {
    let model = element.parentElement.querySelector('.o2-repeat-item-model');

    if (model) {
      let aux = document.createElement('div');
      aux.innerHTML = model.value;
      let item = aux.firstElementChild;

      var elements = item.querySelectorAll('[name]');
      Array.prototype.forEach.call(elements, (el) => {
        if (el.tagName === 'INPUT') {
          if (['radio', 'checkbox'].indexOf(el.type) === -1)
            el.setAttribute('value', '');
        } else if (el.tagName === 'TEXTAREA')
          el.innerHTML = "";
        el.name = this.getName(el.name);
      });

      var elements = item.querySelectorAll('.o2-repeat');
      Array.prototype.forEach.call(elements, (el) => {
        var childrens = el.querySelectorAll('.o2-repeat-wrapper > .o2-repeat-item');
        for (let index = 1; index < childrens.length; index++) {
          childrens[index].remove();
        }
      });

      var labelElements = item.querySelectorAll('.o2-repeat-set-label');
      if (labelElements != null)
        Array.prototype.forEach.call(labelElements, (el) => {
          try {
            let config = JSON.parse(el.value);
            config.name = this.getName(config.name);
            el.value = JSON.stringify(config);
          } catch (error) {

          }
        });

      this.setDisplay(item, '.o2-image-field-selected', '.o2-image-field-unselected');
      this.setDisplay(item, '.o2-link-field-selected', '.o2-link-field-unselected');
      this.setDisplay(item, '.o2-file-field-selected', '.o2-file-field-unselected');

      var elements = item.querySelectorAll('.o2-conditional-display');
      Array.prototype.forEach.call(elements, (el) => {
        var condinationKey = el.dataset.conditionalKey;
        el.dataset.conditionalKey = this.getName(condinationKey);
      });

      this.clone = item.outerHTML;
    }
  }

  renameItem() {
    let length = 0;
    Array.prototype.forEach.call(this.element.childNodes, (el) => {
      if (el.classList && el.classList.contains('o2-repeat-item'))
        length++;
    });
    return this.clone.replaceAll('{{INDEX}}', length);
  }

  renameItens(elements, index) {
    for (const el of elements) {
      el.name = this.getName(el.name).replace('{{INDEX}}', index);
    }
  }

  addItem(index = -1) {
    let tempElement = document.createElement('div');
    tempElement.innerHTML = this.renameItem(this.clone)
    let item = tempElement.firstChild;

    /* inserindo item */
    if (index != -1) {
      let referenceNode = this.element.children[index];
      if (referenceNode && referenceNode.nextSibling)
        this.element.insertBefore(item, referenceNode.nextSibling);
      else
        this.element.appendChild(item);
    } else
      this.element.appendChild(item);

    this.length++;
    this.checkEmpty();
    var event = new CustomEvent('RepeatAdd', { detail: { repeat: this.element.parentNode, el: item } });
    document.dispatchEvent(event);
    return item;
  }

  removeItem(el) {
    var siblings = [];

    var previousSibling = el.previousSibling;
    while (previousSibling) {
      if (previousSibling.nodeType === 1) {
        siblings.push(previousSibling);
      }
      previousSibling = previousSibling.previousSibling;
    }
    const index = siblings.length;
    siblings = [];

    var nextSibling = el.nextSibling;
    while (nextSibling) {
      if (nextSibling.nodeType === 1) {
        siblings.push(nextSibling);
      }
      nextSibling = nextSibling.nextSibling;
    }

    let i = index;
    for (const item of siblings) {
      var elements = item.querySelectorAll('[name]');
      this.renameItens(elements, i++);
    }

    this.length--;
    this.element.removeChild(el);
    this.checkEmpty();
    var event = new CustomEvent('RepeatRemove', { detail: { repeat: this.element.parentNode, el: el } });
    document.dispatchEvent(event);
  }

  update() {
    var childrens = this.element.childNodes;
    let i = 0;
    for (const item of childrens) {
      if (item.querySelectorAll !== undefined) {
        var elements = item.querySelectorAll('[name]');
        this.renameItens(elements, i++);
      }
    }
    var event = new CustomEvent('RepeatUpdate', { detail: { repeat: this.element.parentNode } });
    document.dispatchEvent(event);
  }

  checkEmpty() {
    if (this.length > 0) {
      let elementEmpty = this.element.querySelector('.o2-repeat-empty');
      elementEmpty && elementEmpty.remove();
    } else {
      let elementEmpty = document.createElement('div');
      elementEmpty.classList.add('o2-repeat-empty');
      elementEmpty.innerHTML = 'Nenhum item foi adicionado ainda. <button type="button">Clique aqui</button> para adicionar um novo item';

      let button = elementEmpty.querySelector('button');
      button.addEventListener('click', () => this.addItem(0));

      this.element.appendChild(elementEmpty);
    }
  }




}

export default Repeat;