import './style.css';

const focusHeaderByKey = (headers, index, keyCode) => {
  if (headers.length === 0) {
    return;
  }

  let nextIndex = index;

  if (keyCode === 36) {
    nextIndex = 0;
  } else if (keyCode === 35) {
    nextIndex = headers.length - 1;
  } else if (keyCode === 37 || keyCode === 38) {
    nextIndex = index <= 0 ? headers.length - 1 : index - 1;
  } else if (keyCode === 39 || keyCode === 40) {
    nextIndex = index >= headers.length - 1 ? 0 : index + 1;
  }

  headers[nextIndex]?.focus();
};

const fallbackSetState = (header, panel, isOpen) => {
  header.classList.toggle('show-this', isOpen);
  header.classList.toggle('active', isOpen);
  header.setAttribute('aria-expanded', isOpen ? 'true' : 'false');

  if (!panel) {
    return;
  }

  panel.style.display = isOpen ? 'block' : 'none';
  panel.classList.toggle('active', isOpen);
  panel.setAttribute('aria-hidden', isOpen ? 'false' : 'true');
};

const fallbackInit = (roots, options = {}) => {
  const force = Boolean(options.force);
  const hashTagRaw = window.location.hash ? window.location.hash.substring(1) : '';
  const hashTag = hashTagRaw === 'safari' ? 'calio-safari' : hashTagRaw;

  roots.forEach((root) => {
    if (!force && root.dataset.calioAccordionInit === 'yes') {
      return;
    }

    root.dataset.calioAccordionInit = 'yes';

    const headers = Array.from(root.querySelectorAll('.calio-accordion-header'));
    const isAccordion = (root.dataset.accordionType || 'accordion') === 'accordion';

    if (headers.length === 0) {
      return;
    }

    let defaultHeader = null;

    headers.forEach((header, index) => {
      if (hashTag && header.id === hashTag) {
        defaultHeader = header;
      } else if (!defaultHeader && header.classList.contains('active-default')) {
        defaultHeader = header;
      } else if (!defaultHeader && index === 0) {
        defaultHeader = header;
      }
    });

    headers.forEach((header, index) => {
      const panel = header.nextElementSibling;
      const isDefault = header === defaultHeader;

      fallbackSetState(header, panel, isDefault);

      header.onclick = (event) => {
        event.preventDefault();

        const opened = header.classList.contains('show-this');
        const nextState = !opened;

        if (isAccordion && nextState) {
          headers.forEach((other) => {
            if (other === header) {
              return;
            }

            fallbackSetState(other, other.nextElementSibling, false);
          });
        }

        fallbackSetState(header, panel, nextState);
      };

      header.onkeydown = (event) => {
        if (event.key === 'Enter' || event.key === ' ') {
          event.preventDefault();
          header.click();
          return;
        }

        if ([35, 36, 37, 38, 39, 40].includes(event.keyCode)) {
          event.preventDefault();
          focusHeaderByKey(headers, index, event.keyCode);
        }
      };
    });
  });
};

const initAccordionScope = (scope = document, options = {}) => {
  const force = Boolean(options.force);
  const isEditor = Boolean(options.isEditor);

  const roots = Array.from(scope.querySelectorAll('.calio-adv-accordion'));
  if (roots.length === 0) {
    return;
  }

  const $ = window.jQuery;
  if (typeof $ !== 'function') {
    fallbackInit(roots, { force });
    return;
  }

  let hashTag = window.location.hash ? window.location.hash.substring(1) : '';
  hashTag = hashTag === 'safari' ? 'calio-safari' : hashTag;

  const setOpenState = ($header, $panel, speed, animate = true) => {
    $header.addClass('show-this active');
    $header.attr('aria-expanded', 'true');

    const onOpen = () => {
      $panel.addClass('active');
      $panel.attr('aria-hidden', 'false');
    };

    if (!animate || speed <= 0) {
      $panel.stop(true, true).show();
      onOpen();
      return;
    }

    $panel.stop(true, true).slideDown(speed, onOpen);
  };

  const setClosedState = ($header, $panel, speed, animate = true) => {
    $header.removeClass('show-this active');
    $header.attr('aria-expanded', 'false');

    const onClose = () => {
      $panel.removeClass('active');
      $panel.attr('aria-hidden', 'true');
    };

    if (!animate || speed <= 0) {
      $panel.stop(true, true).hide();
      onClose();
      return;
    }

    $panel.stop(true, true).slideUp(speed, onClose);
  };

  roots.forEach((root) => {
    if (!force && root.dataset.calioAccordionInit === 'yes') {
      return;
    }

    root.dataset.calioAccordionInit = 'yes';

    const $accordion = $(root);
    const $accordionHeader = $accordion.find('.calio-accordion-header');

    if ($accordionHeader.length === 0) {
      return;
    }

    const accordionType = String($accordion.data('accordion-type') || 'accordion');
    const accordionSpeed = Number.parseInt(String($accordion.data('toogle-speed') || '300'), 10) || 300;
    const customIdOffset = Number.parseFloat(String($accordion.data('custom-id-offset') || '0')) || 0;
    const scrollOnClick = String($accordion.data('scroll-on-click') || 'no');
    const scrollSpeed = Number.parseInt(String($accordion.data('scroll-speed') || '300'), 10) || 300;
    const initSpeed = isEditor ? 0 : accordionSpeed;

    let $targetHeader = null;

    $accordionHeader.each(function primeInitialState(index) {
      const $header = $(this);
      const $panel = $header.next('.calio-accordion-content');

      setClosedState($header, $panel, 0, false);

      if (scrollOnClick === 'yes') {
        $header.attr('data-scroll', $header.offset().top);
      }

      if (hashTag && $header.attr('id') === hashTag) {
        $targetHeader = $header;
      } else if ($targetHeader === null && $header.hasClass('active-default')) {
        $targetHeader = $header;
      } else if ($targetHeader === null && index === 0) {
        $targetHeader = $header;
      }
    });

    if (!$targetHeader || $targetHeader.length === 0) {
      $targetHeader = $accordionHeader.first();
    }

    if ($targetHeader && $targetHeader.length) {
      const $targetPanel = $targetHeader.next('.calio-accordion-content');
      setOpenState($targetHeader, $targetPanel, initSpeed, initSpeed > 0);
    }

    $accordionHeader.off('click.calioAccordion');
    $accordionHeader.on('click.calioAccordion', function onAccordionClick(event) {
      event.preventDefault();

      const $this = $(this);
      const $content = $this.next('.calio-accordion-content');

      window.setTimeout(() => {
        $accordionHeader.removeClass('triggered');
      }, 70);

      if ($this.hasClass('triggered')) {
        return;
      }

      if (accordionType === 'accordion') {
        if ($this.hasClass('show-this')) {
          setClosedState($this, $content, accordionSpeed, true);
        } else {
          $accordion.find('.calio-accordion-header').each(function closeOthers() {
            const $header = $(this);
            if ($header.is($this)) {
              return;
            }

            const $panel = $header.next('.calio-accordion-content');
            setClosedState($header, $panel, accordionSpeed, true);
          });

          setOpenState($this, $content, accordionSpeed, true);
        }
      } else if ($this.hasClass('show-this')) {
        setClosedState($this, $content, accordionSpeed, true);
      } else {
        setOpenState($this, $content, accordionSpeed, true);
      }

      if (scrollOnClick === 'yes' && $this.hasClass('active')) {
        $this.attr('data-scroll', $this.offset().top);
        const targetScroll = (Number.parseFloat(String($this.attr('data-scroll') || '0')) || 0) - customIdOffset;
        $('html, body').stop(true).animate({ scrollTop: targetScroll }, scrollSpeed);
      }

      window.setTimeout(() => {
        $this.addClass('triggered');
      }, 50);
    });

    $accordionHeader.off('keydown.calioAccordion');
    $accordionHeader.on('keydown.calioAccordion', function onAccordionKeydown(event) {
      if (event.which === 13 || event.which === 32) {
        event.preventDefault();
        $(this).trigger('click');
        return;
      }

      if ([35, 36, 37, 38, 39, 40].includes(event.which)) {
        event.preventDefault();
        const $this = $(this);
        const currentIndex = $accordionHeader.index($this);
        focusHeaderByKey($accordionHeader.toArray(), currentIndex, event.which);
      }
    });

    $accordion.find('.calio-accordion-header a').off('click.calioAccordion');
    $accordion.find('.calio-accordion-header a').on('click.calioAccordion', (event) => {
      event.stopPropagation();
    });
  });
};

document.addEventListener('DOMContentLoaded', () => {
  initAccordionScope(document);
});

let calioAccordionHookBound = false;
const bindElementorAccordion = () => {
  if (calioAccordionHookBound) {
    return true;
  }

  if (!window.elementorFrontend?.hooks) {
    return false;
  }

  window.elementorFrontend.hooks.addAction('frontend/element_ready/calio-accordion.default', ($scope) => {
    const root = $scope?.[0] || null;
    if (root) {
      initAccordionScope(root, {
        force: true,
        isEditor: Boolean(window.elementorFrontend?.isEditMode?.()),
      });
    }
  });

  calioAccordionHookBound = true;
  return true;
};

window.addEventListener('elementor/frontend/init', bindElementorAccordion);
if (!bindElementorAccordion()) {
  let attempts = 0;
  const timer = window.setInterval(() => {
    attempts += 1;
    if (bindElementorAccordion() || attempts >= 40) {
      window.clearInterval(timer);
    }
  }, 250);
}
