---
import LoadingIndicator from "./LoadingIndicator.astro";

interface Props {
  message?: string;
  subMessage?: string;
  className?: string;
}

const {
  message = "This is taking longer than expected...",
  subMessage = "Still working on loading your content",
  className = ""
} = Astro.props;
---

<div 
  class={`loading-overlay fixed inset-0 flex flex-col items-center justify-center z-50 bg-opacity-90 zag-bg ${className}`}
  role="alert"
  aria-live="polite"
>
  <div class="loading-content text-center p-8 rounded-lg">
    <!-- Enhanced loading indicator -->
    <div class="mb-6 flex justify-center">
      <LoadingIndicator type="dots" size="large" color="var(--color-zag-accent-dark)" />
    </div>
    
    <!-- Messages with animation -->
    <div class="messages-container">
      <p class="text-xl font-semibold mb-2 zag-text message-animate">{message}</p>
      <p class="text-base zag-text-muted message-animate-delay">{subMessage}</p>
    </div>
  </div>
</div>

<style>
  .loading-overlay {
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.3s ease, visibility 0.3s ease;
  }
  
  .loading-overlay.visible {
    opacity: 1;
    visibility: visible;
  }
  
  /* Message animations */
  .message-animate {
    animation: fadeSlideUp 0.6s ease-out both;
  }
  
  .message-animate-delay {
    animation: fadeSlideUp 0.6s ease-out 0.2s both;
  }
  
  @keyframes fadeSlideUp {
    from {
      opacity: 0;
      transform: translateY(10px);
    }
    to {
      opacity: 1;
      transform: translateY(0);
    }
  }
  
  @media (prefers-reduced-motion: reduce) {
    .spinner {
      animation-duration: 3s;
    }
  }
</style>

<script>
  // This script will be executed client-side
  class LoadingManager {
    overlay: HTMLElement | null = null;
    timeoutId: ReturnType<typeof setTimeout> | null = null;
    longLoadingTimeoutId: ReturnType<typeof setTimeout> | null = null;
    
    constructor() {
      this.overlay = document.querySelector('.loading-overlay');
      this.setupNavigationListeners();
    }
    
    setupNavigationListeners() {
      // Listen for navigation events if the Navigation API is supported
      if ('navigation' in window) {
        // @ts-ignore - Navigation API might not be recognized by TypeScript
        window.navigation.addEventListener('navigate', (event) => {
          // Only handle same-origin navigations
          if (new URL(event.destination.url).origin === window.location.origin) {
            this.showLoading();
          }
        });
        
        // @ts-ignore
        window.navigation.addEventListener('navigatesuccess', () => {
          this.hideLoading();
        });
        
        // @ts-ignore
        window.navigation.addEventListener('navigateerror', () => {
          this.hideLoading();
        });
      } else {
        // Fallback for browsers without Navigation API
        window.addEventListener('beforeunload', () => {
          this.showLoading();
        });
        
        // For SPA navigation (if using client-side routing)
        document.addEventListener('astro:page-load', () => {
          this.hideLoading();
        });
      }
      
      // For Astro's view transitions
      document.addEventListener('astro:before-swap', () => {
        this.showLoading();
      });
      
      document.addEventListener('astro:after-swap', () => {
        this.hideLoading();
      });
    }
    
    showLoading() {
      // Clear any existing timeouts
      if (this.timeoutId) {
        clearTimeout(this.timeoutId);
        this.timeoutId = null;
      }
      
      if (this.longLoadingTimeoutId) {
        clearTimeout(this.longLoadingTimeoutId);
        this.longLoadingTimeoutId = null;
      }
      
      // Check connection speed if available
      const showDelay = this.getConnectionBasedDelay();
      
      // Only show loading UI after a short delay to avoid flashing on fast loads
      this.timeoutId = setTimeout(() => {
        // Set loading state in Alpine.js components if they exist
        document.querySelectorAll('[x-data]').forEach(el => {
          // @ts-ignore
          if (el.__x && typeof el.__x.$data.loading !== 'undefined') {
            // @ts-ignore
            el.__x.$data.loading = true;
          }
        });
      }, showDelay);
      
      // Show the overlay for long loading times (5+ seconds)
      this.longLoadingTimeoutId = setTimeout(() => {
        if (this.overlay) {
          this.overlay.classList.add('visible');
        }
      }, 5000);
    }
    
    hideLoading() {
      // Clear timeouts
      if (this.timeoutId) {
        clearTimeout(this.timeoutId);
        this.timeoutId = null;
      }
      
      if (this.longLoadingTimeoutId) {
        clearTimeout(this.longLoadingTimeoutId);
        this.longLoadingTimeoutId = null;
      }
      
      // Hide the overlay
      if (this.overlay) {
        this.overlay.classList.remove('visible');
      }
      
      // Reset loading state in Alpine.js components after a short delay
      // This ensures transitions look smooth
      setTimeout(() => {
        document.querySelectorAll('[x-data]').forEach(el => {
          // @ts-ignore
          if (el.__x && typeof el.__x.$data.loading !== 'undefined') {
            // @ts-ignore
            el.__x.$data.loading = false;
          }
        });
      }, 100);
    }
    
    getConnectionBasedDelay() {
      // Use Network Information API if available
      // @ts-ignore - Navigator connection API might not be recognized
      const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
      
      if (connection) {
        const type = connection.effectiveType;
        
        // Adjust delay based on connection type
        switch (type) {
          case '4g':
            return 100; // Fast connection - short delay
          case '3g':
            return 200; // Medium connection
          case '2g':
          case 'slow-2g':
            return 0; // Slow connection - show immediately
          default:
            return 100; // Default delay
        }
      }
      
      // Default delay if Network Information API is not available
      return 100;
    }
  }
  
  // Initialize the loading manager when the DOM is ready
  document.addEventListener('DOMContentLoaded', () => {
    new LoadingManager();
  });
</script>