<script>
  import { parseBuffer } from 'music-metadata';
  import { onMount } from 'svelte';
  import { Play, Pause, Volume2, Volume1, VolumeX, Music, SkipForward, SkipBack, List } from 'lucide-svelte';
  import './AudioPlayer.css';

  let audioElement;
  let isPlaying = false;
  let currentTime = 0;
  let duration = 0;
  let volume = 0.7;
  let loading = true;
  let loadingProgress = 0;
  let error = null;
  let showPlaylist = false;
  
  let tracks = [];
  let currentTrackIndex = 0;
  let currentTrack = null;
  let randomType = 'unknown';

  function getSecureRandomIntExclusive(max) {
    if (!max || max <= 0) return { value: 0, type: 'invalid' };
    const cryptoObj = typeof window !== 'undefined' && (window.crypto || window.msCrypto);
    if (cryptoObj && cryptoObj.getRandomValues) {
      console.log('Using cryptographically secure randomness');
      const maxUint32 = 4294967296;
      const threshold = maxUint32 - (maxUint32 % max);
      const buf = new Uint32Array(1);
      for (;;) {
        cryptoObj.getRandomValues(buf);
        const r = buf[0];
        if (r < threshold) return { value: r % max, type: 'crypto' };
      }
    }
    console.warn('Fallback to Math.random() - cryptographic randomness unavailable');
    return { value: Math.floor(Math.random() * max), type: 'math' };
  }

  function shuffleInPlace(arr) {
    console.log('Starting track shuffling...');
    for (let i = arr.length - 1; i > 0; i--) {
      const result = getSecureRandomIntExclusive(i + 1);
      const j = result.value;
      randomType = result.type;
      const tmp = arr[i];
      arr[i] = arr[j];
      arr[j] = tmp;
    }
    console.log('Tracks shuffled:', arr);
    console.log(`Type of randomness used: ${randomType === 'crypto' ? 'Cryptographic' : 'Math.random()'}`);
  }

  onMount(async () => {
    await loadTracks();
  });

  async function loadTracks() {
    const timeoutId = setTimeout(() => {
      if (loading) {
        error = 'Loading timeout';
        loading = false;
      }
    }, 120000);

    try {
      loadingProgress = 10;
      
      const trackFiles = ['mgxleepe.flac', 'jifmachinecd.flac', 'psshvec.flac', 'zimaooes.flac'];
      shuffleInPlace(trackFiles);
      tracks = [];
      
      for (let i = 0; i < trackFiles.length; i++) {
        const filename = trackFiles[i];
        loadingProgress = 20 + (i * 60 / trackFiles.length);
        
        try {
          const url = `/music/${filename}`;
          const response = await fetch(url, { cache: 'force-cache' });
          if (!response.ok) continue;
          
          const arrayBuffer = await response.arrayBuffer();
          const metadata = await parseBuffer(new Uint8Array(arrayBuffer));
          
          tracks.push({
            filename,
            src: url,
            metadata,
            title: metadata.common.title || filename.replace('.flac', ''),
            artist: metadata.common.artist || 'Unknown Artist',
            album: metadata.common.album,
            year: metadata.common.year,
            duration: metadata.format.duration
          });
        } catch (trackError) {
          console.warn(`Failed to load ${filename}:`, trackError);
        }
      }
      
      if (tracks.length === 0) {
        throw new Error('No audio files found');
      }
      
      loadingProgress = 90;
      const result = getSecureRandomIntExclusive(tracks.length);
      currentTrackIndex = result.value;
      randomType = result.type;
      currentTrack = tracks[currentTrackIndex];
      console.log(`Initial track selected: ${currentTrackIndex + 1}/${tracks.length} - "${currentTrack.title}"`);
      console.log(`Type of randomness for track selection: ${randomType === 'crypto' ? 'Cryptographic' : 'Math.random()'}`);
      loadingProgress = 100;
      
      setTimeout(() => {
        loading = false;
        clearTimeout(timeoutId);
        console.log('Loading complete!');
        console.log(`Final randomness statistics:`);
        console.log(`Track shuffling: ${randomType === 'crypto' ? 'Cryptographic' : 'Math.random()'}`);
        console.log(`Initial track selection: ${randomType === 'crypto' ? 'Cryptographic' : 'Math.random()'}`);
        if (randomType !== 'crypto') {
          console.warn('WARNING: Fallback to Math.random() was used! Randomness may be predictable.');
        }
      }, 200);
      
    } catch (err) {
      console.error('Error loading tracks:', err);
      error = err.message || 'Failed to load tracks';
      loading = false;
      clearTimeout(timeoutId);
    }
  }

  function togglePlay() {
    if (isPlaying) {
      audioElement.pause();
    } else {
      audioElement.play();
    }
    isPlaying = !isPlaying;
  }

  function nextTrack() {
    if (tracks.length === 0) return;
    currentTrackIndex = (currentTrackIndex + 1) % tracks.length;
    switchToTrack(currentTrackIndex);
  }

  function prevTrack() {
    if (tracks.length === 0) return;
    currentTrackIndex = currentTrackIndex === 0 ? tracks.length - 1 : currentTrackIndex - 1;
    switchToTrack(currentTrackIndex);
  }

  function switchToTrack(index) {
    if (index < 0 || index >= tracks.length) return;
    
    const wasPlaying = isPlaying;
    if (isPlaying) {
      audioElement.pause();
      isPlaying = false;
    }
    
    currentTrackIndex = index;
    currentTrack = tracks[index];
    currentTime = 0;
    
    if (wasPlaying) {
      setTimeout(() => {
        audioElement.play();
        isPlaying = true;
      }, 100);
    }
  }

  function updateTime() {
    currentTime = audioElement.currentTime;
    duration = audioElement.duration || 0;
  }

  function seek(event) {
    const rect = event.target.getBoundingClientRect();
    const percent = (event.clientX - rect.left) / rect.width;
    audioElement.currentTime = percent * duration;
  }

  function formatTime(seconds) {
    if (!seconds || isNaN(seconds)) return '0:00';
    const mins = Math.floor(seconds / 60);
    const secs = Math.floor(seconds % 60);
    return `${mins}:${secs.toString().padStart(2, '0')}`;
  }

  function onVolumeChange() {
    audioElement.volume = volume;
  }

  function arrayBufferToBase64(buffer) {
    try {
      const uint8Array = new Uint8Array(buffer);
      const binaryString = uint8Array.reduce((str, byte) => str + String.fromCharCode(byte), '');
      return btoa(binaryString);
    } catch (error) {
      console.error('Error converting image to base64:', error);
      return null;
    }
  }
</script>

<div class="audio-player">
  <audio 
    bind:this={audioElement}
    src={currentTrack?.src}
    on:timeupdate={updateTime}
    on:loadedmetadata={updateTime}
    on:ended={nextTrack}
    preload="auto"
  ></audio>

  {#if loading}
    <div class="loading-state">
      <div class="loading-spinner"></div>
      <div class="loading-text">Loading tracks... {loadingProgress}%</div>
      <div class="loading-bar">
        <div class="loading-fill" style="width: {loadingProgress}%"></div>
      </div>
    </div>
  {:else if error}
    <div class="error-state">
      <div class="error-icon">⚠</div>
      <div class="error-text">{error}</div>
    </div>
  {:else if currentTrack}
    <div class="metadata">
      <div class="track-info">
        <div class="title-row">
          <div class="title">{currentTrack.title}</div>
          <div class="format-badge">FLAC</div>
          <div class="track-counter">{currentTrackIndex + 1}/{tracks.length}</div>
        </div>
        <div class="artist">{currentTrack.artist}</div>
        {#if currentTrack.album}
          <div class="album">[Album] {currentTrack.album}</div>
        {/if}
        {#if currentTrack.year}
          <div class="year">[Year] {currentTrack.year}</div>
        {/if}
        {#if currentTrack.metadata.format}
          <div class="tech-info">
            {Math.round(currentTrack.metadata.format.sampleRate / 1000)}kHz • {currentTrack.metadata.format.bitsPerSample}bit • {currentTrack.metadata.format.bitrate ? Math.round(currentTrack.metadata.format.bitrate / 1000) + 'kbps' : 'Lossless'}
          </div>
        {/if}
      </div>
            {#if currentTrack.metadata.common.picture && currentTrack.metadata.common.picture[0]}
        {@const base64Image = arrayBufferToBase64(currentTrack.metadata.common.picture[0].data)}
        {#if base64Image}
          <div class="artwork">
            <img 
              src={`data:${currentTrack.metadata.common.picture[0].format};base64,${base64Image}`}
              alt="Album artwork"
              class="artwork-img"
            />
            <div class="artwork-glow"></div>
          </div>
        {:else}
          <div class="artwork-placeholder">
            <Music size={24} />
          </div>
        {/if}
      {:else}
        <div class="artwork-placeholder">
          <Music size={24} />
        </div>
      {/if}
    </div>
  {/if}

  <div class="controls">
    <button class="control-btn" on:click={prevTrack} disabled={loading || error || tracks.length <= 1}>
      <SkipBack size={14} />
    </button>
    
    <button class="play-btn {isPlaying ? 'playing' : ''}" on:click={togglePlay} disabled={loading || error}>
      <div class="btn-content">
        {#if isPlaying}
          <Pause size={16} />
        {:else}
          <Play size={16} />
        {/if}
      </div>
    </button>
    
    <button class="control-btn" on:click={nextTrack} disabled={loading || error || tracks.length <= 1}>
      <SkipForward size={14} />
    </button>

    <div class="time-control">
      <div class="time-display">
        <span class="current-time">{formatTime(currentTime)}</span>
        <span class="separator">/</span>
        <span class="total-time">{formatTime(duration)}</span>
      </div>
      {#if duration > 0}
        <div class="time-remaining">-{formatTime(duration - currentTime)}</div>
      {/if}
    </div>

    <div class="volume-control">
      <button class="volume-btn" on:click={() => volume = volume > 0 ? 0 : 0.7}>
        {#if volume === 0}
          <VolumeX size={14} />
        {:else if volume < 0.5}
          <Volume1 size={14} />
        {:else}
          <Volume2 size={14} />
        {/if}
      </button>
      <div class="volume-slider-container">
        <input 
          type="range" 
          bind:value={volume} 
          on:input={onVolumeChange}
          min="0" 
          max="1" 
          step="0.05"
          class="volume-slider"
        />
        <div class="volume-percentage">{Math.round(volume * 100)}%</div>
      </div>
    </div>

    <button class="playlist-btn" on:click={() => showPlaylist = !showPlaylist} disabled={loading || error || tracks.length <= 1}>
      <List size={14} />
    </button>
  </div>

  <div 
    class="progress-container" 
    on:click={seek}
    on:keydown={(e) => e.key === 'Enter' && seek(e)}
    role="slider"
    tabindex="0"
    aria-label="Seek audio position"
    aria-valuenow={duration ? Math.round((currentTime / duration) * 100) : 0}
    aria-valuemin="0"
    aria-valuemax="100"
  >
    <div class="progress-bar">
      <div 
        class="progress-fill" 
        style="width: {duration ? (currentTime / duration) * 100 : 0}%"
      ></div>
    </div>
  </div>

  {#if showPlaylist && tracks.length > 1}
    <div class="playlist">
      <div class="playlist-header">Playlist ({tracks.length} tracks)</div>
      <div class="playlist-items">
        {#each tracks as track, index}
          <div 
            class="playlist-item {index === currentTrackIndex ? 'active' : ''}"
            on:click={() => switchToTrack(index)}
            on:keydown={(e) => e.key === 'Enter' && switchToTrack(index)}
            role="button"
            tabindex="0"
            aria-label="Switch to track {track.title}"
          >
            <div class="track-number">{index + 1}</div>
            <div class="track-details">
              <div class="track-title">{track.title}</div>
              <div class="track-artist">{track.artist}</div>
            </div>
            <div class="track-duration">{formatTime(track.duration || 0)}</div>
          </div>
        {/each}
      </div>
    </div>
  {/if}
</div>
