(() => {
  'use strict';

  /**
   * Widgets Page Settings - Master switch
   */
  const masterSwitchId = 'widget_enabled_masterswitch';
  const masterSwitch = document.querySelector(`#${masterSwitchId}`);

  // console.log('Master Switch: ', masterSwitch);

  if (masterSwitch) {
    const masterSwitchFormId = masterSwitch.getAttribute('form');

    // console.log('Master Switch - Form Id: ', masterSwitchFormId);

    if (masterSwitchFormId) {
      const masterSwitchForm = document.querySelector(`#${masterSwitchFormId}`);

      // console.log('Master Switch - Form: ', masterSwitchForm);

      if (masterSwitchForm) {
        // console.log('Master Switch - Form Elements: ', masterSwitchForm.elements);

        function toggleFormCheckboxes(form, masterSwitch) {
          for (const element of form.elements) {
            if ((element.getAttribute('type') === 'checkbox') && (element.getAttribute('id') !== masterSwitch.getAttribute('id'))) {
              element.checked = masterSwitch.checked;
            }
          }
        }

        masterSwitch.addEventListener('click', (e) => {
          toggleFormCheckboxes(masterSwitchForm, masterSwitch);
        });
      }
    }
  }

  /**
   * Setting Pages - Forms
   */
  function getSettingValidIds() {
    const validIds = [];

    for (const sectionId in orokublocksAdminConstants.settings) {
      const sectionSettings = orokublocksAdminConstants.settings[sectionId];

      for (const settingId in sectionSettings) {
        const validId = `${sectionId}_${settingId}`;

        validIds.push(validId);
      }
    }

    return validIds;
  }

  const settingValidIds = getSettingValidIds();

  // console.log(`Settings - valid ids:`, settingValidIds);

  function updateDatabaseSettings(settings) {
    const data = {
      action: 'updateSettingsAjax',
      data: settings,
      _ajax_nonce: orokublocksAdminConstants.ajax_nonce
    };

    return jQuery.post(orokublocksAdminConstants.ajax_url, data);
  }

  function SettingsForm(formId) {
    const formElement = document.querySelector(`#${formId}`);
    const formButtonElement = document.querySelector(`button[form=${formId}]`);

    if (formElement && formButtonElement) {
      const formButtonTextElement = formButtonElement.querySelector('span');

      // console.log(`Form ${formId}:`, formElement);
      // console.log(`Form ${formId} - elements:`, formElement.elements);
      // console.log(`Form ${formId} - button:`, formButtonElement);

      const settings = {
        saved: {
          ...orokublocksAdminConstants.settings
        },
        current: {
          ...orokublocksAdminConstants.settings
        },
        saving: false
      };

      function settingIsDifferent(currentSetting, newSetting) {
        for (const settingSectionId in newSetting) {
          for (const settingId in newSetting[settingSectionId]) {
            const currentSettingValue = currentSetting[settingSectionId][settingId];
            const newSettingValue = newSetting[settingSectionId][settingId];

            if (currentSettingValue !== newSettingValue) {
              return true;
            }
          }
        }
    
        return false;
      }

      function getSettingDifference(currentSetting, newSetting) {
        const settingDifference = {};

        for (const settingSectionId in newSetting) {
          for (const settingId in newSetting[settingSectionId]) {
            const currentSettingValue = currentSetting[settingSectionId][settingId];
            const newSettingValue = newSetting[settingSectionId][settingId];
            
            if (currentSettingValue !== newSettingValue) {
              if (typeof settingDifference[settingSectionId] === 'undefined') {
                settingDifference[settingSectionId] = {};
              }

              settingDifference[settingSectionId][settingId] = newSettingValue;
            }
          }
        }

        return settingDifference;
      }

      function getSettingFormStatus(form) {
        const settings = {};

        for (const settingControl of form.elements) {
          if (settingValidIds.includes(settingControl.id)) {
            // console.log(`Form ${formId} - control: `, settingControl.id, settingControl, settingControl.value);

            const settingSectionId = settingControl.getAttribute('data-setting-section-id');

            if (typeof settings[settingSectionId] === 'undefined') {
              settings[settingSectionId] = {};
            }

            const settingId = settingControl.id.replace(`${settingSectionId}_`, '');

            if (settingControl.type === 'checkbox') {
              settings[settingSectionId][settingId] = settingControl.checked;
            } else {
              settings[settingSectionId][settingId] = settingControl.value;
            }
          }
        }


        return settings;
      }

      function updateSettings(e) {
        // console.log(`Form ${formId} - control changed:`, e.target);

        const formSettings = getSettingFormStatus(e.target.form);

        // console.log('New settings: ', formSettings); 

        if (settingIsDifferent(settings.current, formSettings)) {
          settings.current = Object.assign(settings.current, formSettings);
        }

        if (settingIsDifferent(settings.saved, settings.current)) {
          formButtonElement.disabled = false;
        } else {
          formButtonElement.disabled = true;
        }

        // console.log(`Form ${formId} - settings:`, settings);
      }

      function saveSettings(e) {
        e.preventDefault();

        // console.log(`Form ${formId} - elements:`, this.elements);
        // console.log(`Form ${formId} - settings:`, settings);

        if (settings.saving) {
          return;
        }

        settings.saving = true;
        formButtonElement.classList.add('oroku-button--style--loading');
        formButtonTextElement.innerText = orokublocksAdminConstants.translation.saving;

        if (settingIsDifferent(settings.saved, settings.current)) {
          const settingsToSave = getSettingDifference(settings.saved, settings.current);

          // console.log(`Form ${formId} - settings that are sent for saving:`, settingsToSave);

          // save
          updateDatabaseSettings(settingsToSave)
          .done((result) => {
            // console.log(`Form ${formId} - settings updated - result:`, result);

            if (formId === 'oroku-license-settings') {
              window.location.reload();
            } else {
              // update saved status if save was successful
              settings.saved = Object.assign(settings.saved, settings.current);
              formButtonElement.disabled = true;
            }
          })
          .fail((error) => {
            // console.log(`Form ${formId} - settings not updated - error:`, error);
          })
          .always(() => {
            if (formId !== 'oroku-license-settings') {
              settings.saving = false;
              formButtonElement.classList.remove('oroku-button--style--loading');
              formButtonTextElement.innerText = orokublocksAdminConstants.translation.save_changes;
            }
          });
          
          // console.log(`Form ${formId} - settings:`, settings);

        } else {
          // console.log(`Form ${formId} - saved settings is same as current settings`);
          settings.saving = false;
          formButtonElement.classList.remove('oroku-button--style--loading');
          formButtonTextElement.innerText = orokublocksAdminConstants.translation.save_changes;
        }
      }

      for (const settingControl of formElement.elements) {
        // console.log(`Form ${formId} - control id:`, settingControl.id);
        if ((settingControl.id === masterSwitchId) || settingValidIds.includes(settingControl.id)) {
          // console.log(`Form ${formId} - control:`, settingControl);
          settingControl.addEventListener('input', updateSettings);
        }
      }

      formElement.addEventListener('submit', saveSettings);
    }
  }

  // console.log('Setting form ids: ', orokublocksAdminConstants.settingFormIds);

  for (const formId of orokublocksAdminConstants.settingFormIds) {
    SettingsForm(formId);
  }

})();