import { Utility } from '../../core/utility';

const MASS_INPUT_SELECTOR = '.massinput';
const RECIPIENT_CATEGORIES_SELECTOR = '.recipient-categories';
const RECIPIENT_CATEGORY_SELECTOR = '.recipient-category';
const RECIPIENT_CATEGORY_CHECKBOX_SELECTOR = '.recipient-category__checkbox';
const RECIPIENT_CATEGORY_OPTIONS_SELECTOR = '.recipient-category__options';
const RECIPIENT_CATEGORY_TOGGLE_ALL_SELECTOR = '.recipient-category__toggle-all [type="checkbox"]';
const RECIPIENT_CATEGORY_CHECKED_COUNTER_SELECTOR = '.recipient-category__checked-counter';


@Utility({
  selector: RECIPIENT_CATEGORIES_SELECTOR,
})
export class CommunicationRecipients {
  massInputElement;

  constructor(element) {
    if (!element) {
      throw new Error('Communication Recipient utility cannot be setup without an element!');
    }
    
    this.massInputElement = element.closest(MASS_INPUT_SELECTOR);

    this.setupRecipientCategories();

    const recipientObserver = new MutationObserver(this.setupRecipientCategories.bind(this));
    recipientObserver.observe(this.massInputElement, { childList: true });
  }

  setupRecipientCategories() {
    Array.from(this.massInputElement.querySelectorAll(RECIPIENT_CATEGORY_SELECTOR)).forEach(setupRecipientCategory);
  }
}

function setupRecipientCategory(recipientCategoryElement) {
  const categoryCheckbox = recipientCategoryElement.querySelector(RECIPIENT_CATEGORY_CHECKBOX_SELECTOR);
  const categoryOptions = recipientCategoryElement.querySelector(RECIPIENT_CATEGORY_OPTIONS_SELECTOR);

  if (categoryOptions) {
    const categoryCheckboxes = Array.from(categoryOptions.querySelectorAll('[type="checkbox"]'));
    const toggleAllCheckbox = recipientCategoryElement.querySelector(RECIPIENT_CATEGORY_TOGGLE_ALL_SELECTOR);

    // setup category checkbox to toggle all child checkboxes if changed
    categoryCheckbox.addEventListener('change', () => {
      categoryCheckboxes.filter(checkbox => !checkbox.disabled).forEach(checkbox => {
        checkbox.checked = categoryCheckbox.checked;
      });
      updateCheckedCounter(recipientCategoryElement, categoryCheckboxes);
      updateToggleAllCheckbox(toggleAllCheckbox, categoryCheckboxes);
    });

    // update counter and toggle checkbox initially
    updateCheckedCounter(recipientCategoryElement, categoryCheckboxes);
    updateToggleAllCheckbox(toggleAllCheckbox, categoryCheckboxes);

    // register change listener for individual checkboxes
    categoryCheckboxes.forEach(checkbox => {
      checkbox.addEventListener('change', () => {
        updateCheckedCounter(recipientCategoryElement, categoryCheckboxes);
        updateToggleAllCheckbox(toggleAllCheckbox, categoryCheckboxes);
      });
    });

    // register change listener for toggle all checkbox
    if (toggleAllCheckbox) {
      toggleAllCheckbox.addEventListener('change', () => {
        categoryCheckboxes.filter(checkbox => !checkbox.disabled).forEach(checkbox => {
          checkbox.checked = toggleAllCheckbox.checked;
        });
        updateCheckedCounter(recipientCategoryElement, categoryCheckboxes);
      });
    }
  }
}

// update checked state of toggle all checkbox based on all other checkboxes
function updateToggleAllCheckbox(toggleAllCheckbox, categoryCheckboxes) {
  const allChecked = categoryCheckboxes.reduce((acc, checkbox) => acc && checkbox.checked, true);
  toggleAllCheckbox.checked = allChecked;
}

// update value of checked counter
function updateCheckedCounter(recipientCategoryElement, categoryCheckboxes) {
  const checkedCounter = recipientCategoryElement.querySelector(RECIPIENT_CATEGORY_CHECKED_COUNTER_SELECTOR);
  const checkedCheckboxes = categoryCheckboxes.reduce((acc, checkbox) => checkbox.checked ? acc + 1 : acc, 0);
  checkedCounter.innerHTML = checkedCheckboxes + '/' + categoryCheckboxes.length;
}
