/*
 * This file is part of the Sylius package.
 *
 * (c) Paweł Jędrzejewski
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/* eslint-env browser */

const getProvinceInputValue = function getProvinceInputValue(valueSelector) {
  const val = valueSelector ? valueSelector.value : null;
  return !val || val === undefined ? '' : `value="${val}"`;
};

const SyliusProvinceField = function SyliusProvinceField(beforeCallback = () => {}, afterCallback = () => {}) {
  const countrySelect = document.querySelectorAll('select[name$="[countryCode]"]');
  const changeEvent = new Event('change');

  countrySelect.forEach((countrySelectItem) => {
    countrySelectItem.addEventListener('change', (event) => {
      const select = event.currentTarget;
      const addressContainer = select.closest('#sylius-shipping-address, #sylius-billing-address, form[name="sylius_address"]');
      if (!addressContainer) {
        return;
      }

      const provinceContainer = addressContainer.querySelector('.province-container');
      if (!provinceContainer) {
        return;
      }

      const provinceSelectFieldName = select.getAttribute('name').replace('country', 'province');
      const provinceInputFieldName = select.getAttribute('name').replace('countryCode', 'provinceName');

      const provinceSelectFieldId = select.getAttribute('id').replace('country', 'province');
      const provinceInputFieldId = select.getAttribute('id').replace('countryCode', 'provinceName');

      if (select.value === '' || select.value === undefined) {
        provinceContainer.innerHTML = '';
        return;
      }

      provinceContainer.setAttribute('data-loading', '');

      beforeCallback();

      let url = `${provinceContainer.getAttribute('data-url')}?countryCode=${select.value}`;

      const provinceErrorContainer = provinceContainer.querySelector('.invalid-feedback');
      if (provinceErrorContainer && !addressContainer.dataset.hideProvinceError) {
        url = `${url}&error=${provinceErrorContainer.innerHTML}`;
        addressContainer.dataset.hideProvinceError = true;
      }

      fetch(url)
        .then((response) => {
          if (!String(response.status).match(/^2.*/)) {
            return null;
          }

          return response.json();
        })
        .then((response) => {
          if (!response) {
            provinceContainer.removeAttribute('data-loading');
            provinceContainer.innerHTML = '';
          } else if (response.content.indexOf('select') !== -1) {
            const provinceSelectValue = getProvinceInputValue((
              provinceContainer.querySelector('select > option[selected$="selected"]')
            ));

            provinceContainer.innerHTML = response.content
              .replace('name="sylius_address_province"', `name="${provinceSelectFieldName}"${provinceSelectValue}`)
              .replace('id="sylius_address_province"', `id="${provinceSelectFieldId}"`)
              .replace('option value="" selected="selected"', 'option value=""')
              .replace(`option ${provinceSelectValue}`, `option ${provinceSelectValue}" selected="selected"`);

            provinceContainer.querySelector('select').classList.add('form-control');
            provinceContainer.removeAttribute('data-loading');
          } else {
            const provinceInputValue = getProvinceInputValue(provinceContainer.querySelector('input'));

            provinceContainer.innerHTML = response.content
              .replace('name="sylius_address_province"', `name="${provinceInputFieldName}"${provinceInputValue}`)
              .replace('id="sylius_address_province"', `id="${provinceInputFieldId}"`);

            provinceContainer.querySelector('input').classList.add('form-control');
            provinceContainer.removeAttribute('data-loading');
          }

          afterCallback(response);
        });
    });

    if (countrySelectItem.value !== '') {
      countrySelectItem.dispatchEvent(changeEvent);
    }
  });
};

export default SyliusProvinceField;
