/**
 * @file
 * Video preview JavaScript.
 */

(function (Drupal, once) {
  'use strict';

  /**
   * Handles video preview functionality.
   */
  Drupal.behaviors.ffmpegVideoPreview = {
    attach: function (context) {
      const previews = once('ffmpeg-video-preview', '.ffmpeg-video-preview', context);

      if (!previews.length) {
        return;
      }

      previews.forEach(function (preview) {
        const video = preview.querySelector('video');
        const tabs = preview.querySelectorAll('.ffmpeg-output-tab');
        const panel = preview.querySelector('[role="tabpanel"]');

        if (!video) {
          return;
        }

        // Handle output tab switching.
        tabs.forEach(function (tab) {
          const activateTab = function (targetTab) {
            tabs.forEach(function (t) {
              t.classList.remove('active');
              t.setAttribute('aria-selected', 'false');
              t.setAttribute('tabindex', '-1');
            });

            targetTab.classList.add('active');
            targetTab.setAttribute('aria-selected', 'true');
            targetTab.setAttribute('tabindex', '0');

            if (panel && targetTab.id) {
              panel.setAttribute('aria-labelledby', targetTab.id);
            }
          };

          tab.addEventListener('click', function () {
            var src = tab.getAttribute('data-src');

            if (!src) {
              return;
            }

            activateTab(tab);

            var currentTime = Number.isFinite(video.currentTime) ? video.currentTime : 0;
            var shouldResumePlayback = !video.paused && !video.ended;

            video.src = src;
            video.load();

            var restorePlaybackPosition = function () {
              if (currentTime > 0 && Number.isFinite(video.duration) && video.duration > 0) {
                try {
                  video.currentTime = Math.min(currentTime, video.duration);
                }
                catch (error) {
                  // Some browsers block currentTime jumps before ready states settle.
                }
              }

              if (shouldResumePlayback) {
                var playPromise = video.play();
                if (playPromise && typeof playPromise.catch === 'function') {
                  playPromise.catch(function () {
                    // Ignore autoplay interruption; controls remain available.
                  });
                }
              }
            };

            if (video.readyState >= 1) {
              restorePlaybackPosition();
            }
            else {
              video.addEventListener('loadedmetadata', restorePlaybackPosition, { once: true });
            }
          });

          // Arrow key navigation between tabs.
          tab.addEventListener('keydown', function (e) {
            var tabArray = Array.from(tabs);
            var index = tabArray.indexOf(tab);

            if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {
              e.preventDefault();
              var next = tabArray[(index + 1) % tabArray.length];
              next.click();
              next.focus();
            }
            else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {
              e.preventDefault();
              var prev = tabArray[(index - 1 + tabArray.length) % tabArray.length];
              prev.click();
              prev.focus();
            }
            else if (e.key === 'Home') {
              e.preventDefault();
              tabArray[0].click();
              tabArray[0].focus();
            }
            else if (e.key === 'End') {
              e.preventDefault();
              tabArray[tabArray.length - 1].click();
              tabArray[tabArray.length - 1].focus();
            }
          });
        });

        // Update time display.
        const timeDisplay = preview.querySelector('.ffmpeg-video-time');
        if (timeDisplay) {
          video.addEventListener('timeupdate', function () {
            const current = formatTime(video.currentTime);
            const total = formatTime(video.duration || 0);
            timeDisplay.textContent = current + ' / ' + total;
          });
        }
      });

      /**
       * Formats seconds to MM:SS or HH:MM:SS.
       */
      function formatTime(seconds) {
        const h = Math.floor(seconds / 3600);
        const m = Math.floor((seconds % 3600) / 60);
        const s = Math.floor(seconds % 60);

        if (h > 0) {
          return h + ':' + padZero(m) + ':' + padZero(s);
        }

        return m + ':' + padZero(s);
      }

      function padZero(num) {
        return num < 10 ? '0' + num : num;
      }
    }
  };

  /**
   * Opens a native dialog with the full-size video player on thumbnail click.
   *
   * Includes focus management: traps focus within the dialog while open,
   * focuses the close button on open, and restores focus to the trigger
   * element on close.
   */
  Drupal.behaviors.ffmpegVideoThumbnail = {
    attach: function (context) {
      var thumbnails = once('ffmpeg-video-thumbnail', '.ffmpeg-video-thumbnail[data-dialog-target]', context);

      if (!thumbnails.length) {
        return;
      }

      thumbnails.forEach(function (thumbnail) {
        var dialogId = thumbnail.getAttribute('data-dialog-target');

        if (!dialogId) {
          return;
        }

        var dialog = document.getElementById(dialogId);

        if (!dialog) {
          return;
        }

        var video = dialog.querySelector('.ffmpeg-video-dialog__video');
        var closeBtn = dialog.querySelector('.ffmpeg-video-dialog__close');
        var triggerElement = null;

        function openDialog() {
          triggerElement = thumbnail;

          // Lazy-load video source on first open.
          if (video && !video.src && video.getAttribute('data-src')) {
            video.src = video.getAttribute('data-src');
          }

          if (typeof dialog.showModal === 'function') {
            dialog.showModal();
          }
          else {
            dialog.setAttribute('open', '');
          }

          thumbnail.setAttribute('aria-expanded', 'true');

          // Mark all other body children as inert so focus stays within the dialog.
          Array.from(document.body.children).forEach(function (child) {
            if (child !== dialog) {
              child.inert = true;
            }
          });

          // Focus the close button as the first focusable element.
          if (closeBtn) {
            closeBtn.focus();
          }

          if (video) {
            var playPromise = video.play();
            if (playPromise && typeof playPromise.catch === 'function') {
              playPromise.catch(function () {
                // Autoplay may be blocked; controls remain available.
              });
            }
          }
        }

        function resetDialogState() {
          Array.from(document.body.children).forEach(function (child) {
            child.inert = false;
          });

          thumbnail.setAttribute('aria-expanded', 'false');

          if (video) {
            video.pause();
          }
        }

        function closeDialog() {
          resetDialogState();

          if (typeof dialog.close === 'function') {
            dialog.close();
          }
          else {
            dialog.removeAttribute('open');
          }

          // Restore focus to the trigger element.
          if (triggerElement && typeof triggerElement.focus === 'function') {
            triggerElement.focus();
          }
          triggerElement = null;
        }

        // Thumbnail click.
        thumbnail.addEventListener('click', openDialog);

        // Close button.
        if (closeBtn) {
          closeBtn.addEventListener('click', closeDialog);
        }

        // Backdrop click (click on dialog element itself, outside __content).
        dialog.addEventListener('click', function (e) {
          if (e.target === dialog) {
            closeDialog();
          }
        });

        // Escape key (browser fires cancel event before closing).
        dialog.addEventListener('cancel', function () {
          resetDialogState();

          // Restore focus to the trigger element.
          if (triggerElement && typeof triggerElement.focus === 'function') {
            triggerElement.focus();
          }
          triggerElement = null;
        });
      });
    }
  };

})(Drupal, once);
