// +-------------------------------------------------+
// © 2002-2004 PMB Services / www.sigb.net pmb@sigb.net et contributeurs (voir www.sigb.net)
// +-------------------------------------------------+
// $Id: RmcForm.js,v 1.1 2026/08/04 08:00:57 qvarin Exp $

// Champ d'amorce "Recherche externe" du panneau de preremplissage : ouvre la RMC
// (recherche multicriteres externe) dans une modale Dojo, puis en rapatrie la human
// query et la recherche serialisee. Meme patron que apps/import_export/ImportExportForm.js
// et apps/search_dsi/DsiForm.js, avec deux differences :
//  - la recherche est conservee sous sa forme JSON (search::json_encode_search()) et non
//    serialisee : voir OrchestratorController::rmcDataAction() ;
//  - bindLegacySelector()/refreshFields() couvrent le cas
//    $pmb_extended_search_dnd_interface = 0, ou le formulaire natif ajoute et supprime
//    ses criteres par un submit classique, impossible dans un ContentPane.

define([
  'dojo/_base/declare',
  'dojo/_base/lang',
  'dojo/dom',
  'dojo/dom-attr',
  'dojo/dom-construct',
  'dojo/on',
  'dojo/query',
  'dojo/request',
  'dijit/registry',
  'apps/pmb/PMBDojoxDialogSimple',
  'apps/pmb/pmbEventsHandler'
], function(declare, lang, dom, domAttr, domConstruct, on, query, request, registry, DialogSimple, pmbEventsHandler) {
  const DIALOG_ID = 'prefillingform_rmc_dialog';
  const AJAX_BASE = './ajax.php?module=catalog';

  return declare(null, {
    className: null,
    dialog: null,
    signals: null,

    constructor: function(params) {
      lang.mixin(this, params);
      this.signals = [];
      pmbEventsHandler.initEvents(this);
    },

    loadSetDialog: function(params) {
      // Recherche deja definie : sa forme JSON est portee par le champ cache
      // idRMCSelector_data_<uid> (RmcField.vue), transmise en search_data pour
      // pre-remplir le formulaire natif (cf. OrchestratorController::rmcFormAction()).
      const node = dom.byId('idRMCSelector_data_' + params.uniqueId);
      const data = (node && node.value) ? node.value : '';

      let path = AJAX_BASE + '&categ=prefillingform&action=rmcForm';
      path += '&id_champ=' + encodeURIComponent(params.uniqueId);
      if (data) {
        path += '&search_data=' + encodeURIComponent(data);
      }

      this.destroyDialog();
      this.dialog = new DialogSimple({
        title: pmbDojo.messages.getMessage('prefillingform_panel', 'prefillingform_panel_rmc_title'),
        executeScripts: true,
        id: DIALOG_ID,
        style: {
          width: '85%'
        }
      });
      this.signals.push(on(this.dialog, 'load', () => {
        // Accroche le bouton "Enregistrer" (data-pmb-evt pose par search.tpl.php)
        // et neutralise les submits natifs du formulaire de recherche.
        pmbEventsHandler.initEvents(this, this.dialog.domNode);
        pmbEventsHandler.formToAjax(this.dialog.domNode);
        ajax_parse_elements();
        this.bindLegacySelector();
      }));
      this.signals.push(on(this.dialog, 'hide', () => this.destroyDialog()));

      this.dialog.attr('href', path);
      this.dialog.startup();
      this.dialog.resize();
      this.dialog.show();
    },

    saveAdvancedSearch: function(params) {
      const form = dom.byId(params.formId);
      if (!form) {
        return;
      }
      this.enableOperators();
      request.post(AJAX_BASE + '&categ=prefillingform&action=rmcData', {
        data: this.prepareData(form),
        handleAs: 'json'
      }).then((response) => {
        this.updateField(params.id_champ, response);
        this.dialog.hide();
      }, () => {
        alert(pmbDojo.messages.getMessage('prefillingform_panel', 'prefillingform_panel_rmc_not_saved'));
      });
    },

    updateField: function(uniqueId, response) {
      const human = dom.byId('idRMCSelector_human_' + uniqueId);
      const data = dom.byId('idRMCSelector_data_' + uniqueId);
      if (human) {
        human.innerHTML = response.human_query;
      }
      if (data) {
        data.value = response.search;
      }
      // RmcField.vue ecoute cet evenement pour remonter la valeur a PanelApp.
      window.dispatchEvent(new CustomEvent('changeRMCData_' + uniqueId, {
        detail: {
          data: {
            search: response.search,
            human_query: response.human_query
          }
        }
      }));
    },

    /**
     * Sans interface drag'n'drop ($pmb_extended_search_dnd_interface = 0), le selecteur
     * de champs (search::get_field_selector()) et les boutons de suppression
     * (search::get_already_selected_fields()) appellent search_form.submit(), ce qui
     * navigue la page entiere depuis un ContentPane. On remplace donc les deux par un
     * rafraichissement Ajax du tableau des criteres.
     */
    bindLegacySelector: function() {
      if (query('[id$="_extended_search_dnd_container"]', this.dialog.domNode).length) {
        return;
      }
      // Un seul point de remplacement suffit : les deux variantes du selecteur
      // (onChange inline si $pmb_extended_search_auto, sinon le bouton "Ajouter")
      // resolvent getFormInfos au moment de l'appel.
      window.getFormInfos = lang.hitch(this, this.refreshFields);

      const form = query('form[name="search_form"]', this.dialog.domNode)[0];
      if (!form) {
        return;
      }
      const deleteField = query('input[name="delete_field"]', form)[0];
      query('input[id^="delete_field_button_"]', form).forEach((button) => {
        domAttr.set(button, 'onclick', '');
        on(button, 'click', () => {
          domAttr.set(deleteField, 'value', domAttr.get(button, 'id').replace('delete_field_button_', ''));
          this.refreshFields();
          domAttr.set(deleteField, 'value', '');
        });
      });
    },

    refreshFields: function() {
      const form = query('form[name="search_form"]', this.dialog.domNode)[0];
      if (!form) {
        return;
      }
      this.enableOperators();
      request.post(AJAX_BASE + '&categ=extended_search&sub=get_already_selected_fields', {
        data: this.prepareData(form)
      }).then((data) => {
        const container = query('table', form)[0].parentNode;
        domConstruct.place(data, container, 'only');
        // domConstruct n'execute pas les <script> injectes : on les recree.
        query('script', container).forEach((node) => {
          domConstruct.create('script', {
            innerHTML: node.innerHTML,
            type: 'text/javascript'
          }, node, 'replace');
        });
        ajax_parse_elements();
        this.bindLegacySelector();
      });
    },

    /**
     * Ne pas utiliser domForm.toJson() : l'operateur AUTHORITY et les select multiples
     * ne sont pas transmis (cf. apps/pmb/tab/tabContainer.js). Les champs desactives
     * doivent aussi etre relus, d'ou la collecte a chaque appel plutot qu'un
     * new FormData(form).
     */
    prepareData: function(form) {
      const data = new FormData();
      query('input, select, textarea', form).forEach((element) => {
        if (!element.name) {
          return;
        }
        if ('INPUT' === element.nodeName && 'button' === element.type) {
          return;
        }
        if ('SELECT' === element.nodeName && element.multiple) {
          for (const option of element.selectedOptions) {
            data.append(element.name, option.value);
          }
        } else if ('INPUT' === element.nodeName && ['checkbox', 'radio'].includes(element.type)) {
          if (element.checked) {
            data.append(element.name, element.value);
          }
        } else {
          data.append(element.name, element.value);
        }
      });

      return data;
    },

    // enable_operators() est definie par le script que show_form() injecte dans la modale.
    enableOperators: function() {
      if ('function' === typeof enable_operators) {
        enable_operators();
      }
    },

    destroyDialog: function() {
      this.signals.forEach((signal) => signal.remove());
      this.signals = [];

      const dialog = registry.byId(DIALOG_ID);
      if (dialog) {
        dialog.destroyDescendants();
        dialog.destroy();
      }
      this.dialog = null;
    }
  });
});
