/**
 * RSS/Atom Feed Preview for Links Table
 */

(function() {
    const existingPreviews = document.querySelectorAll('#rss-feed-preview');
    existingPreviews.forEach(el => el.remove());
  
    const CORS_PROXY = 'https://cors-anywhere.mayx.eu.org/?';
  
    const createPreviewElement = () => {
      const existingPreview = document.getElementById('rss-feed-preview');
      if (existingPreview) {
        return existingPreview;
      }
  
      const previewEl = document.createElement('div');
      previewEl.id = 'rss-feed-preview';
      previewEl.style.cssText = `
        position: fixed;
        display: none;
        width: 300px;
        max-height: 400px;
        overflow-y: auto;
        background-color: white;
        border: 1px solid #ccc;
        border-radius: 5px;
        padding: 10px;
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
        z-index: 1000;
        font-size: 14px;
        line-height: 1.4;
      `;
      document.body.appendChild(previewEl);
      return previewEl;
    };
  
    const parseRSS = (xmlText) => {
      const parser = new DOMParser();
      const xml = parser.parseFromString(xmlText, 'text/xml');
  
      const rssItems = xml.querySelectorAll('item');
      if (rssItems.length > 0) {
        return Array.from(rssItems).slice(0, 5).map(item => {
          return {
            title: item.querySelector('title')?.textContent || 'No title',
            date: item.querySelector('pubDate')?.textContent || 'No date',
          };
        });
      }
  
      const atomItems = xml.querySelectorAll('entry');
      if (atomItems.length > 0) {
        return Array.from(atomItems).slice(0, 5).map(item => {
          return {
            title: item.querySelector('title')?.textContent || 'No title',
            date: item.querySelector('updated')?.textContent || 'No date',
          };
        });
      }
  
      return null;
    };
  
    const checkFeed = async (url) => {
      try {
        const response = await fetch(CORS_PROXY + url);
        if (!response.ok) {
          return null;
        }
  
        const text = await response.text();
        return parseRSS(text);
      } catch (error) {
        return null;
      }
    };
  
    const findFeedUrl = async (siteUrl, linkElement) => {
      if (linkElement && linkElement.hasAttribute('data-feed')) {
        const dataFeedUrl = linkElement.getAttribute('data-feed');
        if (dataFeedUrl) {
          const feedItems = await checkFeed(dataFeedUrl);
          if (feedItems) {
            return { url: dataFeedUrl, items: feedItems };
          }
        }
      }
  
      return null;
    };
  
    const escapeHTML = (str) => {
      return String(str).replace(/[&<>"'/]/g, (c) => ({
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;',
        '"': '&quot;',
        "'": '&#39;',
        '/': '&#x2F;'
      }[c]));
    };

    const renderFeedItems = (previewEl, items, siteName) => {
      if (!items || items.length === 0) {
        previewEl.innerHTML = '<p>No feed items found.</p>';
        return;
      }
  
      let html = `<h3>Latest from ${siteName}</h3><ul style="list-style: none; padding: 0; margin: 0;">`;
  
      items.forEach(item => {
        const safeTitle = escapeHTML(item.title);
        const safeDate = escapeHTML(new Date(item.date).toLocaleDateString());
        html += `
          <li style="margin-bottom: 10px; padding-bottom: 10px; border-bottom: 1px solid #eee;">
            <div style="color: #24292e; font-weight: bold;">
              ${safeTitle}
            </div>
            <div style="color: #586069; font-size: 12px; margin: 3px 0;">
              ${safeDate}
            </div>
          </li>
        `;
      });
  
      html += '</ul>';
      previewEl.innerHTML = html;
    };
  
    const positionPreview = (previewEl, event) => {
      const viewportWidth = window.innerWidth;
      const viewportHeight = window.innerHeight;
  
      let left = event.clientX + 20;
      let top = event.clientY + 20;
  
      const rect = previewEl.getBoundingClientRect();
  
      if (left + rect.width > viewportWidth) {
        left = event.clientX - rect.width - 20;
      }
  
      if (top + rect.height > viewportHeight) {
        top = event.clientY - rect.height - 20;
      }
  
      left = Math.max(10, left);
      top = Math.max(10, top);
  
      previewEl.style.left = `${left}px`;
      previewEl.style.top = `${top}px`;
    };
  
    const initFeedPreview = () => {
      const previewEl = createPreviewElement();
  
      const tableLinks = document.querySelectorAll('main table tbody tr td a');
  
      const feedCache = {};
  
      let currentLink = null;
      let loadingTimeout = null;
  
      tableLinks.forEach(link => {
        link.addEventListener('mouseenter', async (event) => {
          currentLink = link;
          const url = link.getAttribute('href');
          const siteName = link.textContent;
  
          previewEl.innerHTML = '<p>Checking for RSS/Atom feed...</p>';
          previewEl.style.display = 'block';
          positionPreview(previewEl, event);
  
          if (loadingTimeout) {
            clearTimeout(loadingTimeout);
          }
  
          loadingTimeout = setTimeout(async () => {
            if (feedCache[url]) {
              renderFeedItems(previewEl, feedCache[url].items, siteName);
              positionPreview(previewEl, event); // Reposition after content is loaded
              return;
            }
  
            const feedData = await findFeedUrl(url, link);
  
            if (currentLink === link) {
              if (feedData) {
                feedCache[url] = feedData;
                renderFeedItems(previewEl, feedData.items, siteName);
                positionPreview(previewEl, event); // Reposition after content is loaded
              } else {
                previewEl.style.display = 'none';
              }
            }
          }, 300);
        });
  
        link.addEventListener('mousemove', (event) => {
          if (previewEl.style.display === 'block') {
            window.requestAnimationFrame(() => {
              positionPreview(previewEl, event);
            });
          }
        });
  
        link.addEventListener('mouseleave', () => {
          if (loadingTimeout) {
            clearTimeout(loadingTimeout);
            loadingTimeout = null;
          }
  
          currentLink = null;
          previewEl.style.display = 'none';
        });
      });
  
      document.addEventListener('click', (event) => {
        if (!previewEl.contains(event.target)) {
          previewEl.style.display = 'none';
        }
      });
    };
  
    if (!window.rssFeedPreviewInitialized) {
      window.rssFeedPreviewInitialized = true;
  
      if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initFeedPreview);
      } else {
        initFeedPreview();
      }
    }
  })();
  