// Define global variables to track music files and the current index.
let currentMusicFiles = []; // Array of objects with at least { path, index }
let currentMusicIndex = -1; // Index of the current music file
let currentTrackPath  = "";

// Helper function: decode each segment then re-encode to avoid double encoding.
function encodeSubpath(subpath) {
  if (!subpath) return '';
  return subpath
    .split('/')
    .map(segment => encodeURIComponent(decodeURIComponent(segment)))
    .join('/');
}

// Global variable for gallery images (updated from current folder)
let currentGalleryImages = [];


function paintFile() {
    // Highlight the currently playing file
    if (currentTrackPath) {
      const currentMusicFile = currentMusicFiles.find(file => file.path === currentTrackPath);
      if (currentMusicFile) {
        const currentMusicFileElement = document.querySelector(`.play-file[data-url="${currentMusicFile.path}"]`);
        if (currentMusicFileElement) {
          currentMusicFileElement.closest('.file-item').classList.add('currently-playing');
        }
      }
    }
  }

function renderContent(data) {

  // Render breadcrumbs, directories (grid view when appropriate), and files.
  let breadcrumbHTML = '';
  data.breadcrumbs.forEach((crumb, index) => {
    breadcrumbHTML += `<a href="#" class="breadcrumb-link" data-path="${crumb.path}">${crumb.name}</a>`;
    if (index < data.breadcrumbs.length - 1) {
      breadcrumbHTML += `<span class="separator">&#8203;&gt;</span>`;
    }
  });
  document.getElementById('breadcrumbs').innerHTML = breadcrumbHTML;


  // Render directories.
  let contentHTML = '';
  if (data.directories.length > 0) {
    contentHTML += '<ul>';
    // Check if every directory name is short (≤15 characters) and no files are present
    const areAllShort = data.directories.every(dir => dir.name.length <= 15) && data.files.length === 0;
    if (areAllShort) {
      contentHTML += '<div class="directories-grid">';
      data.directories.forEach(dir => {
        contentHTML += `<div class="directory-item">📁 <a href="#" class="directory-link" data-path="${dir.path}">${dir.name}</a></div>`;
      });
      contentHTML += '</div>';
    } else {
      contentHTML += '<ul>';
      data.directories.forEach(dir => {
        contentHTML += `<li class="directory-item">📁 <a href="#" class="directory-link" data-path="${dir.path}">${dir.name}</a></li>`;
      });
      contentHTML += '</ul>';
    }
  }

  // Render files.
  currentMusicFiles = []; // Reset the music files array.
  if (data.files.length > 0) {
    contentHTML += '<ul>';
    data.files.forEach((file, idx) => {
      let symbol = '📄';
      if (file.file_type === 'music') {
        symbol = '🔊';
        currentMusicFiles.push({ path: file.path, index: idx, title: file.name.replace('.mp3', '') });
      } else if (file.file_type === 'image') {
        symbol = '🖼️';
      }
      const indexAttr = file.file_type === 'music' ? ` data-index="${currentMusicFiles.length - 1}"` : '';
      contentHTML += `<li class="file-item">
                <a href="#" class="play-file"${indexAttr} data-url="${file.path}" data-file-type="${file.file_type}">${symbol} ${file.name.replace('.mp3', '')}</a>`;
      if (file.has_transcript) {
        contentHTML += `<a href="#" class="show-transcript" data-url="${file.transcript_url}" title="Show Transcript">&#128196;</a>`;
      }
      contentHTML += `</li>`;
    });
    contentHTML += '</ul>';
  }

  // Insert the generated HTML into a container in the DOM.
  document.getElementById('content').innerHTML = contentHTML;

  // Now attach the event listeners for directories.
  document.querySelectorAll('div.directory-item').forEach(li => {
    li.addEventListener('click', function(e) {
      // Only trigger if the click did not start on an <a>.
      if (!e.target.closest('a')) {
        const anchor = li.querySelector('a.directory-link');
        if (anchor) {
          anchor.click();
        }
      }
    });
  });

  // Now attach the event listeners for directories.
  document.querySelectorAll('li.directory-item').forEach(li => {
    li.addEventListener('click', function(e) {
      // Only trigger if the click did not start on an <a>.
      if (!e.target.closest('a')) {
        const anchor = li.querySelector('a.directory-link');
        if (anchor) {
          anchor.click();
        }
      }
    });
  });

  // Now attach the event listeners for files.
  document.querySelectorAll('li.file-item').forEach(li => {
    li.addEventListener('click', function(e) {
      // Only trigger if the click did not start on an <a>.
      if (!e.target.closest('a')) {
        const anchor = li.querySelector('a.play-file');
        if (anchor) {
          anchor.click();
        }
      }
    });
  });
  
  // Update global variable for gallery images (only image files).
  currentGalleryImages = data.files
    .filter(f => f.file_type === 'image')
    .map(f => f.path);

  attachEventListeners(); // Reattach event listeners for newly rendered elements.
}

// Fetch directory data from the API.
function loadDirectory(subpath) {
  const encodedPath = encodeSubpath(subpath);
  const apiUrl = '/api/path/' + encodedPath;
  return fetch(apiUrl)
    .then(response => response.json())
    .then(data => {
      renderContent(data);
      paintFile();
      return data; // return data for further chaining
    })
    .catch(error => {
      console.error('Error loading directory:', error);
      document.getElementById('content').innerHTML = `<p>Error loading directory!</p><p>${error}</p>`;
      throw error; // Propagate the error
    });
}

// preload the next audio file
function preload_audio() {
  // Prefetch the next file by triggering the backend diskcache.
  if (currentMusicIndex >= 0 && currentMusicIndex < currentMusicFiles.length - 1) {
    const nextFile = currentMusicFiles[currentMusicIndex + 1];
    const nextMediaUrl = '/media/' + nextFile.path;
    // Use a HEAD request so that the backend reads and caches the file without returning the full content.
    fetch(nextMediaUrl, { method: 'HEAD' })
      // .then(response => {
      //   console.log('Backend diskcache initiated for next file:', nextFile.path);
      // })
      // .catch(error => console.error('Error initiating backend diskcache for next file:', error));
  }
}

// Attach event listeners for directory, breadcrumb, file, and transcript links.
function attachEventListeners() {
  // Directory link clicks.
  document.querySelectorAll('.directory-link').forEach(link => {
    link.addEventListener('click', function (event) {
      event.preventDefault();
      const newPath = this.getAttribute('data-path');
      loadDirectory(newPath);
      history.pushState({ subpath: newPath }, '', newPath ? '/path/' + newPath : '/');
      // Scroll to the top of the page after click:
      window.scrollTo({ top: 0, behavior: 'smooth' });
    });
  });

  // Breadcrumb link clicks.
  document.querySelectorAll('.breadcrumb-link').forEach(link => {
    link.addEventListener('click', function (event) {
      event.preventDefault();
      const newPath = this.getAttribute('data-path');
      loadDirectory(newPath);
      history.pushState({ subpath: newPath }, '', newPath ? '/path/' + newPath : '/');
    });
  });

// Cache common DOM elements
const nowPlayingInfo = document.getElementById('nowPlayingInfo');
const audioPlayer = document.getElementById('globalAudio');
const playerButton = document.querySelector('.player-button');
const audioPlayerContainer = document.getElementById('audioPlayerContainer');
const footer = document.querySelector('footer');

// Global variable to store the current fetch's AbortController.
let currentFetchController = null;

document.querySelectorAll('.play-file').forEach(link => {
  link.addEventListener('click', async function (event) {
    event.preventDefault();

    const { fileType, url: relUrl, index } = this.dataset;
    
    // Remove the class from all file items.
    document.querySelectorAll('.file-item').forEach(item => {
      item.classList.remove('currently-playing');
    });

    if (fileType === 'music') {
      // Update the current music index.
      currentMusicIndex = index !== undefined ? parseInt(index) : -1;
      
      // Display the audio player container.
      audioPlayerContainer.style.display = "block";
      
      // Mark the clicked item as currently playing.
      this.closest('.file-item').classList.add('currently-playing');

      // Abort any previous fetch if still running.
      if (currentFetchController) {
        currentFetchController.abort();
      }
      currentFetchController = new AbortController();

      // Pause the audio and clear its source.
      audioPlayer.pause();
      audioPlayer.src = '';

      // Set a timeout to display a loader message if needed.
      const loaderTimeout = setTimeout(() => {
        playerButton.innerHTML = playIcon;
        nowPlayingInfo.textContent = "Wird geladen...";
      }, 500);
      
      footer.style.display = 'flex';

      const mediaUrl = `/media/${relUrl}`;

      try {
        // Perform a HEAD request to verify media availability.
        const response = await fetch(mediaUrl, { method: 'HEAD', signal: currentFetchController.signal });
        clearTimeout(loaderTimeout);

        if (response.status === 403) {
          nowPlayingInfo.textContent = "Fehler: Zugriff verweigert.";
          window.location.href = '/';
          return;
        } else if (!response.ok) {
          nowPlayingInfo.textContent = `Fehler: Unerwarteter Status (${response.status}).`;
          console.error('Unexpected response status:', response.status);
          return;
        }
        
        // Set the media URL, load, and play the audio.
        audioPlayer.src = mediaUrl;
        audioPlayer.load();
        await audioPlayer.play();
        currentTrackPath = relUrl;
        playerButton.innerHTML = pauseIcon;

        // Process file path for display.
        const pathParts = relUrl.split('/');
        const folderName = pathParts[pathParts.length - 2];
        const fileName = pathParts.pop();
        const pathStr = pathParts.join('/');
        
        // Update Media Session metadata if available.
        if ('mediaSession' in navigator) {
          navigator.mediaSession.metadata = new MediaMetadata({
            title: currentMusicFiles[currentMusicIndex].title,
            artist: folderName,
            artwork: [
              { src: '/static/icons/logo-192x192.png', sizes: '192x192', type: 'image/png' }
            ]
          });
        }
        
        nowPlayingInfo.innerHTML = pathStr.replace(/\//g, ' > ') +
          '<br><span style="font-size: larger; font-weight: bold;">' +
          fileName.replace('.mp3', '') + '</span>';
        
        // Delay preloading to avoid blocking playback.
        setTimeout(preload_audio, 1000);
      } catch (error) {
        if (error.name === 'AbortError') {
          console.log('Previous fetch aborted.');
        } else {
          console.error('Error fetching media:', error);
          nowPlayingInfo.textContent = "Fehler: Netzwerkproblem oder ungültige URL.";
        }
      }
    } else if (fileType === 'image') {
      // Open the gallery modal for image files.
      openGalleryModal(relUrl);
    } else {
      // serve like a download
      window.location.href = `/media/${relUrl}`;
    }
  });
});


  // Transcript icon clicks.
  document.querySelectorAll('.show-transcript').forEach(link => {
    link.addEventListener('click', function (event) {
      event.preventDefault();
      const url = this.getAttribute('data-url');
      fetch(url)
        .then(response => {
          if (!response.ok) {
            throw new Error('Network response was not ok');
          }
          return response.text();
        })
        .then(data => {
          document.getElementById('transcriptContent').innerHTML = marked.parse(data);
          document.getElementById('transcriptModal').style.display = 'block';
        })
        .catch(error => {
          document.getElementById('transcriptContent').innerHTML = '<p>Error loading transcription.</p>';
          document.getElementById('transcriptModal').style.display = 'block';
        });
    });
  });
}

// Modal close logic for transcript modal.
document.addEventListener('DOMContentLoaded', function () {
  const closeBtn = document.querySelector('#transcriptModal .close');
  closeBtn.addEventListener('click', function () {
    document.getElementById('transcriptModal').style.display = 'none';
  });
  window.addEventListener('click', function (event) {
    if (event.target == document.getElementById('transcriptModal')) {
      document.getElementById('transcriptModal').style.display = 'none';
    }
  });

  // Load initial directory based on URL.
  let initialSubpath = '';
  if (window.location.pathname.indexOf('/path/') === 0) {
    initialSubpath = window.location.pathname.substring(6); // remove "/path/"
  }
  loadDirectory(initialSubpath);
});

// Handle back/forward navigation.
window.addEventListener('popstate', function (event) {
  const subpath = event.state ? event.state.subpath : '';
  loadDirectory(subpath);
});


let isReloadButtonVisible = true; // Boolean to track the visibility of the reload button.

function reloadDirectory() {
  if (!isReloadButtonVisible) return Promise.resolve();

  // Extract the current path from the URL.
  let currentSubpath = '';
  if (window.location.pathname.indexOf('/path/') === 0) {
    currentSubpath = window.location.pathname.substring(6);
  }
  
  // Return the promise so that we can chain actions after the directory has reloaded.
  return loadDirectory(currentSubpath)
    .then(() => {
      // Animate the reload button as before.
      const reloadBtn = document.querySelector('#reload-button');
      const reloadBtnSVG = document.querySelector('#reload-button svg');

      void reloadBtnSVG.offsetWidth; // Force reflow to reset the animation
      reloadBtnSVG.classList.add("rotate");
      isReloadButtonVisible = false;

      setTimeout(() => {
        reloadBtnSVG.classList.remove("rotate");
        reloadBtn.style.transition = 'opacity 0.5s ease';
        reloadBtn.style.opacity = '1';
        reloadBtn.style.pointer = 'cursor';
        isReloadButtonVisible = true;
      }, 10000);
    });
}



if ('mediaSession' in navigator) {

  // Handler for the play action
  navigator.mediaSession.setActionHandler('play', () => {
    document.getElementById('globalAudio').play();
  });

  // Handler for the pause action
  navigator.mediaSession.setActionHandler('pause', () => {
    document.getElementById('globalAudio').pause();
  });

  // Handler for the previous track action
  navigator.mediaSession.setActionHandler('previoustrack', () => {
    if (currentMusicIndex > 0) {
      const prevFile = currentMusicFiles[currentMusicIndex - 1];
      const prevLink = document.querySelector(`.play-file[data-url="${prevFile.path}"]`);
      if (prevLink) {
        prevLink.click();
      }
    }
  });

  // Handler for the next track action
  navigator.mediaSession.setActionHandler('nexttrack', () => {
    if (currentMusicIndex >= 0 && currentMusicIndex < currentMusicFiles.length - 1) {
      const nextFile = currentMusicFiles[currentMusicIndex + 1];
      const nextLink = document.querySelector(`.play-file[data-url="${nextFile.path}"]`);
      if (nextLink) {
        nextLink.click();
      }
    }
  });
}

document.getElementById('globalAudio').addEventListener('ended', () => {
  
  reloadDirectory().then(() => {
    
    // If we had a track playing, try to find it in the updated list.
    if (currentTrackPath) {
      const newIndex = currentMusicFiles.findIndex(file => file.path === currentTrackPath);
      currentMusicIndex = newIndex;
    }
    
    // Now, if there's a next track, auto-play it.
    if (currentMusicIndex >= 0 && currentMusicIndex < currentMusicFiles.length - 1) {
      const nextFile = currentMusicFiles[currentMusicIndex + 1];
      const nextLink = document.querySelector(`.play-file[data-url="${nextFile.path}"]`);
      if (nextLink) {
        nextLink.click();
      }
    }
  }).catch(error => {
    console.error('Error during reload:', error);
  });
});

// document.addEventListener("DOMContentLoaded", function() {
//   // Automatically reload every 5 minutes (300,000 milliseconds)
//   setInterval(reloadDirectory, 300000);
// });