/**
 * @copyright   (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
Joomla = window.Joomla || {};
((Joomla, document) => {

  Joomla.hideAssociation = (formControl, languageCode) => {
    const controlGroup = [].slice.call(document.querySelectorAll('#associations .control-group'));
    controlGroup.forEach(element => {
      // Current selected language. Hide it
      const el = element.querySelector('.control-label label');
      if (el) {
        const attribute = el.getAttribute('for');
        if (attribute.replace(/_name$/, '') === `${formControl}_associations_${languageCode.replace('-', '_')}`) {
          element.classList.add('hidden');
        }
      }
    });
  };
  Joomla.showAssociationMessage = () => {
    const controlGroup = [].slice.call(document.querySelectorAll('#associations .control-group'));
    const associations = document.getElementById('associations');
    if (associations) {
      const html = document.createElement('joomla-alert');
      html.innerText = Joomla.Text._('JGLOBAL_ASSOC_NOT_POSSIBLE');
      associations.insertAdjacentElement('afterbegin', html);
    }
    controlGroup.forEach(element => {
      element.classList.add('hidden');
    });
  };

  /**
   * Inject associations into other association fields
   *
   * This function is called whenever the Ajax request within propagateAssociation() completes
   * successfully.
   * Its purpose is to inject the associations which have been returned in the Ajax response into
   * the other association fields in the form.
   * It does this by invoking the various callback functions of those association fields (i.e. the
   * function which gets called whenever the administrator selects an association via the modal),
   * and passing the appropriate associated record details.
   *
   * @param   result                  The response from the Ajax request.
   *                                  Its structure is that generated by the JResponseJson class,
   *                                  with the data field containing the associations
   * @param   callbackFunctionPrefix  The name of the callback function which the modal window uses
   *                                  to set the selected item as the association, but minus the
   *                                  language tag at the end
   *
   * @return  boolean
   *
   * @since   3.9.0
   */
  Joomla.injectAssociations = (result, callbackFunctionPrefix) => {
    let functionName;
    if (result.success) {
      if (result.data.length !== 0) {
        [].slice.call(Object.keys(result.data)).forEach(lang => {
          functionName = callbackFunctionPrefix + lang.replace('-', '_');
          window[functionName](result.data[lang].id, result.data[lang].title, result.data[lang].catid, null, null, lang);
        });
      }
      if (result.message) {
        Joomla.renderMessages({
          notice: [result.message]
        });
      }
    } else {
      Joomla.renderMessages({
        warning: [Joomla.Text._('JGLOBAL_ASSOCIATIONS_PROPAGATE_FAILED')]
      });
    }
  };

  /**
   * Propagate associations from this field into other association fields
   *
   * This function is called whenever an administrator populates an association (in the association
   * modal field) and then clicks on the Propagate button.
   * The purpose of this function is to find what other records (if any) are associated with the
   * one which the administrator has selected, and populate the other association fields with these
   * records. (Otherwise, if the administrator just clicks on Save without clicking on Propagate,
   * those other associations will be deleted). It does this by finding the id of the selected
   * associated record (from a hidden field) and makes an Ajax call to the server to find the other
   * associations, also passing up the language of the record currently being edited, as it should
   * be excluded. Once it has received from the server the other associations it calls
   * injectAssociations to inject them into the other association fields within the form.
   *
   * @param   fieldPrefix             The stem of the html ids for the elements comprising the
   *                                  modal field
   * @param   callbackFunctionPrefix  The name of the callback function which the modal window uses
   *                                  to set the selected item as the association, but minus the
   *                                  language tag at the end
   *
   * @return  boolean
   *
   * @since   3.9.0
   */
  Joomla.propagateAssociation = (fieldPrefix, callbackFunctionPrefix) => {
    // Find the id of the record which has been set as an association
    const assocId = document.getElementById(`${fieldPrefix}_id`).value;

    // Find the language of the record being edited
    const languageField = document.getElementById('jform_language');
    const currentLang = languageField.options[languageField.selectedIndex].value;
    const data = {
      task: 'ajax.fetchAssociations',
      format: 'json',
      assocId,
      excludeLang: currentLang
    };
    data[Joomla.getOptions('csrf.token', '')] = 1;
    const queryString = Object.keys(data).reduce((a, k) => {
      a.push(`${k}=${encodeURIComponent(data[k])}`);
      return a;
    }, []).join('&');
    const url = `${document.forms.adminForm.action}&${queryString}`;
    Joomla.request({
      // Find the action url associated with the form - we need to add the token to this
      url,
      method: 'GET',
      data: JSON.stringify(data),
      headers: {
        'Content-Type': 'application/json'
      },
      onSuccess: response => {
        Joomla.injectAssociations(JSON.parse(response), callbackFunctionPrefix);
      },
      onError: () => {
        Joomla.renderMessages({
          warning: [Joomla.Text._('JGLOBAL_ASSOCIATIONS_PROPAGATE_FAILED')]
        });
      }
    });
    return false;
  };
  document.addEventListener('DOMContentLoaded', () => {
    const associationsEditOptions = Joomla.getOptions('system.associations.edit');
    const formControl = associationsEditOptions.formControl || 'jform';
    const formControlLanguage = document.getElementById(`${formControl}_language`);

    // Hide the associations tab if needed
    if (parseInt(associationsEditOptions.hidden, 10) === 1) {
      Joomla.showAssociationMessage();
    } else if (formControlLanguage) {
      // Hide only the associations for the current language
      Joomla.hideAssociation(formControl, formControlLanguage.value);
    }

    // When changing the language
    if (formControlLanguage) {
      formControlLanguage.addEventListener('change', ({
        target
      }) => {
        // Remove message if any
        Joomla.removeMessages();
        let existsAssociations = false;

        /** For each language, remove the associations, ie,
         *  empty the associations fields and reset the buttons to Select/Create
         */
        const controlGroup = [].slice.call(document.querySelectorAll('#associations .control-group'));
        controlGroup.forEach(element => {
          const attribute = element.querySelector('.control-label label').getAttribute('for');
          const languageCode = attribute.replace('_name', '').replace('jform_associations_', '');

          // Show the association fields
          element.classList.remove('hidden');

          // Check if there was an association selected for this language
          if (!existsAssociations && document.getElementById(`${formControl}_associations_${languageCode}_id`).value !== '') {
            existsAssociations = true;
          }

          // Call the modal clear button
          const clear = document.getElementById(`${formControl}_associations_${languageCode}_clear`);
          if (clear.onclick) {
            clear.onclick();
          } else if (clear.click) {
            clear.click();
          }
        });

        // If associations existed, send a warning to the user
        if (existsAssociations) {
          Joomla.renderMessages({
            warning: [Joomla.Text._('JGLOBAL_ASSOCIATIONS_RESET_WARNING')]
          });
        }

        // If the selected language is All hide the fields and add a message
        const selectedLanguage = target.value;
        if (selectedLanguage === '*') {
          Joomla.showAssociationMessage();
        } else {
          // Else show the associations fields/buttons and hide the current selected language
          Joomla.hideAssociation(formControl, selectedLanguage);
        }
      });
    }
  });
})(Joomla, document);
