<script lang="ts">
  import { fade } from 'svelte/transition';
  import { onMount } from 'svelte';

  export let effects: Array<{type: string, emoji: string, duration: number}> = [];
  export let flash: boolean = false;
  export let faint: boolean = false;
  
  // GBA-style flicker animation parameters (matching original Snaplings timing)
  const flickerCount = 19;
  const frameDelay = 2;
  const flickerDuration = 1000; // milliseconds - matches Snaplings original
  
  // Flicker state management
  let isFlickering = false;
  let flickerVisible = true;
  let flickerFrame = 0;
  let flickerInterval: number;
  
  // Faint animation state management
  let isFainting = false;
  let faintProgress = 0;
  let faintAnimationId: number;
  let hasFainted = false;
  
  // Particle system configuration
  const PARTICLES_PER_EFFECT = 6; // Number of emoji particles per effect
  const SPAWN_RADIUS = 45; // Radius around piclet where particles spawn (reduced for better containment)
  
  // Generate multiple particles for each effect
  $: particleList = effects.flatMap((effect, effectIndex) => {
    const particles = [];
    for (let i = 0; i < PARTICLES_PER_EFFECT; i++) {
      // More varied spawn positions for better coverage
      const angle = (Math.PI * 2 * i) / PARTICLES_PER_EFFECT + (Math.random() - 0.5) * 1.2;
      const distance = SPAWN_RADIUS * (0.4 + Math.random() * 0.6); // Tighter distance variation for better containment
      const x = Math.cos(angle) * distance;
      const y = Math.sin(angle) * distance;
      
      // Enhanced animation properties for more dynamic effects (no rotation)
      const scale = 0.7 + Math.random() * 0.5; // 0.7x to 1.2x initial size
      const duration = Math.max(effect.duration * 1.8, 1800) + (Math.random() - 0.5) * 400; // Longer base duration
      const delay = Math.random() * 200; // More staggered animation starts
      
      // Additional movement properties for more dynamic motion (reduced range)
      const moveDistance = 20 + Math.random() * 30; // Further reduced movement distance for better containment
      const moveAngle = angle + (Math.random() - 0.5) * Math.PI * 0.4; // Further reduced movement angle variation
      
      particles.push({
        id: `${effectIndex}-${i}`,
        type: effect.type,
        emoji: effect.emoji,
        x,
        y,
        scale,
        duration,
        delay,
        moveDistance,
        moveAngle
      });
    }
    return particles;
  });
  
  // Watch for flash changes to trigger flicker animation
  $: if (flash && !isFlickering) {
    startFlickerAnimation();
  }
  
  // Watch for faint changes to trigger faint animation
  $: if (faint && !isFainting && !hasFainted) {
    startFaintAnimation();
  }
  
  function startFlickerAnimation() {
    isFlickering = true;
    flickerFrame = 0;
    
    // Calculate frame duration based on total duration and frame count
    const totalFrames = flickerCount * (frameDelay + 1);
    const frameDuration = flickerDuration / totalFrames;
    
    flickerInterval = setInterval(() => {
      if (flickerFrame >= totalFrames) {
        // Animation finished, always visible
        clearInterval(flickerInterval);
        isFlickering = false;
        flickerVisible = true;
        return;
      }
      
      // Toggle visibility every frameDelay frames
      const flickerCycle = Math.floor(flickerFrame / (frameDelay + 1));
      flickerVisible = flickerCycle % 2 === 0;
      
      flickerFrame++;
    }, frameDuration);
  }
  
  function startFaintAnimation() {
    isFainting = true;
    faintProgress = 0;
    
    const faintDuration = 1200; // milliseconds - matches Snaplings original
    const startTime = performance.now();
    
    function updateFaintAnimation(currentTime: number) {
      const elapsed = currentTime - startTime;
      const progress = Math.min(elapsed / faintDuration, 1);
      
      // Use easeIn curve for acceleration as it falls away
      faintProgress = progress * progress;
      
      if (progress < 1) {
        faintAnimationId = requestAnimationFrame(updateFaintAnimation);
      } else {
        // Animation completed
        isFainting = false;
        faintProgress = 1; // Keep final state
        hasFainted = true; // Mark as permanently fainted
      }
    }
    
    faintAnimationId = requestAnimationFrame(updateFaintAnimation);
  }
  
  onMount(() => {
    return () => {
      if (flickerInterval) {
        clearInterval(flickerInterval);
      }
      if (faintAnimationId) {
        cancelAnimationFrame(faintAnimationId);
      }
    };
  });
</script>

<!-- Effects wrapper with relative positioning for particles -->
<div class="effects-wrapper">
  <!-- GBA-style flicker effect with faint animation -->
  <div 
    class="effects-container" 
    class:is-fainting={faint}
    style="
      opacity: {(flash && isFlickering) ? (flickerVisible ? 1 : 0) : (hasFainted || (faint && faintProgress >= 1) ? 0 : 1)};
      {faint || hasFainted ? `
        transform: 
          scale(1, ${Math.max(0, 1 - faintProgress)})
          matrix(1, 0, ${-faintProgress * 0.5}, 1, 0, 0);
        transform-origin: bottom center;
      ` : ''}
    "
  >
    <slot />
  </div>

  <!-- Multi-particle effects -->
  {#each particleList as particle (particle.id)}
    <div 
      class="effect-particle {particle.type}" 
      style="
        left: calc(50% + {particle.x}px); 
        top: calc(50% + {particle.y}px);
        animation-duration: {particle.duration}ms;
        animation-delay: {particle.delay}ms;
        --initial-scale: {particle.scale};
        --move-x: {Math.cos(particle.moveAngle) * particle.moveDistance}px;
        --move-y: {Math.sin(particle.moveAngle) * particle.moveDistance}px;
      "
    >
      <span class="effect-emoji">{particle.emoji}</span>
    </div>
  {/each}
</div>

<style>
  .effects-wrapper {
    position: relative;
    display: inline-block;
    /* Ensure wrapper contains particles even during resize */
    overflow: visible;
    /* Create a proper containing block for particles */
    width: 100%;
    height: 100%;
  }
  
  .effects-container {
    position: relative;
    display: inline-block;
    transition: opacity 0.05s ease;
    z-index: 2; /* Ensure effects appear above platform (z-index: 0) */
  }
  
  .effect-particle {
    position: absolute;
    pointer-events: none;
    z-index: 10;
    animation-fill-mode: forwards;
    transform-origin: center center;
    /* Position relative to the Piclet center */
  }
  
  .effect-emoji {
    font-size: 24px;
    display: block;
    filter: drop-shadow(0 0 6px rgba(0, 0, 0, 0.5));
    transform: scale(var(--initial-scale, 1));
    /* Remove rotation - emojis stay upright */
  }
  
  /* Status effects - floating with rotation */
  .effect-particle.burn {
    animation: statusBurn ease-in-out;
  }
  
  .effect-particle.poison {
    animation: statusPoison ease-in-out;
  }
  
  .effect-particle.paralyze {
    animation: statusParalyze linear;
  }
  
  .effect-particle.sleep {
    animation: statusSleep ease-in-out;
  }
  
  .effect-particle.freeze {
    animation: statusFreeze ease-out;
  }
  
  /* Stat increases - rising with spin */
  .effect-particle.attackUp,
  .effect-particle.defenseUp,
  .effect-particle.speedUp,
  .effect-particle.accuracyUp {
    animation: statIncrease ease-out;
  }
  
  /* Stat decreases - falling with wobble */
  .effect-particle.attackDown,
  .effect-particle.defenseDown,
  .effect-particle.speedDown,
  .effect-particle.accuracyDown {
    animation: statDecrease ease-in;
  }
  
  /* Special effects */
  .effect-particle.critical,
  .effect-particle.superEffective {
    animation: criticalBurst ease-out;
  }
  
  .effect-particle.notVeryEffective,
  .effect-particle.miss {
    animation: missSwirl ease-in-out;
  }
  
  .effect-particle.heal {
    animation: healRise ease-out;
  }
  
  /* Complex multi-property animations */
  @keyframes statusBurn {
    0% {
      transform: translate(-50%, -50%) scale(0.2);
      opacity: 0;
    }
    10% {
      transform: translate(-50%, -50%) scale(1.8);
      opacity: 1;
    }
    25% {
      transform: translate(calc(-50% + var(--move-x) * 0.3), calc(-50% + var(--move-y) * 0.3)) scale(var(--initial-scale));
      opacity: 0.95;
    }
    50% {
      transform: translate(calc(-50% + var(--move-x) * 0.6), calc(-50% + var(--move-y) * 0.6)) scale(calc(var(--initial-scale) * 1.3));
      opacity: 0.8;
    }
    75% {
      transform: translate(calc(-50% + var(--move-x) * 0.9), calc(-50% + var(--move-y) * 0.9)) scale(calc(var(--initial-scale) * 0.7));
      opacity: 0.5;
    }
    100% {
      transform: translate(calc(-50% + var(--move-x)), calc(-50% + var(--move-y))) scale(0.3);
      opacity: 0;
    }
  }
  
  @keyframes statusPoison {
    0% {
      transform: translate(-50%, -50%) scale(0.4);
      opacity: 0;
    }
    20% {
      transform: translate(-50%, -50%) scale(1.1);
      opacity: 1;
    }
    40% {
      transform: translate(-50%, -50%) scale(0.9);
      opacity: 0.8;
    }
    60% {
      transform: translate(-50%, -50%) scale(1.0);
      opacity: 0.6;
    }
    80% {
      transform: translate(-50%, -50%) scale(0.7);
      opacity: 0.3;
    }
    100% {
      transform: translate(-50%, -50%) scale(0.5);
      opacity: 0;
    }
  }
  
  @keyframes statusParalyze {
    0% {
      transform: translate(-50%, -50%) scale(0.2);
      opacity: 0;
    }
    10% {
      transform: translate(-50%, -50%) scale(1.3);
      opacity: 1;
    }
    20% {
      transform: translate(-50%, -50%) scale(1.1);
      opacity: 0.9;
    }
    30% {
      transform: translate(-50%, -50%) scale(1.2);
      opacity: 0.8;
    }
    40% {
      transform: translate(-50%, -50%) scale(1.0);
      opacity: 0.7;
    }
    50% {
      transform: translate(-50%, -50%) scale(0.9);
      opacity: 0.6;
    }
    100% {
      transform: translate(-50%, -50%) scale(0.3);
      opacity: 0;
    }
  }
  
  @keyframes statusSleep {
    0% {
      transform: translate(-50%, -50%) scale(0.5);
      opacity: 0;
    }
    25% {
      transform: translate(-50%, -55%) scale(1.1);
      opacity: 1;
    }
    50% {
      transform: translate(-50%, -45%) scale(1.0);
      opacity: 0.9;
    }
    75% {
      transform: translate(-50%, -55%) scale(0.9);
      opacity: 0.5;
    }
    100% {
      transform: translate(-50%, -60%) scale(0.4);
      opacity: 0;
    }
  }
  
  @keyframes statusFreeze {
    0% {
      transform: translate(-50%, -50%) scale(0.3);
      opacity: 0;
    }
    30% {
      transform: translate(-50%, -50%) scale(1.4);
      opacity: 1;
    }
    60% {
      transform: translate(-50%, -50%) scale(1.2);
      opacity: 0.8;
    }
    90% {
      transform: translate(-50%, -50%) scale(0.8);
      opacity: 0.3;
    }
    100% {
      transform: translate(-50%, -50%) scale(0.6);
      opacity: 0;
    }
  }
  
  @keyframes statIncrease {
    0% {
      transform: translate(-50%, -50%) scale(0.3);
      opacity: 0;
    }
    15% {
      transform: translate(-50%, -50%) scale(1.6);
      opacity: 1;
    }
    30% {
      transform: translate(calc(-50% + var(--move-x) * 0.2), calc(-50% + var(--move-y) * 0.2 - 20px)) scale(calc(var(--initial-scale) * 1.2));
      opacity: 0.95;
    }
    60% {
      transform: translate(calc(-50% + var(--move-x) * 0.7), calc(-50% + var(--move-y) * 0.7 - 60px)) scale(calc(var(--initial-scale) * 1.0));
      opacity: 0.7;
    }
    85% {
      transform: translate(calc(-50% + var(--move-x)), calc(-50% + var(--move-y) - 90px)) scale(calc(var(--initial-scale) * 0.6));
      opacity: 0.3;
    }
    100% {
      transform: translate(calc(-50% + var(--move-x)), calc(-50% + var(--move-y) - 120px)) scale(0.2);
      opacity: 0;
    }
  }
  
  @keyframes statDecrease {
    0% {
      transform: translate(-50%, -50%) scale(0.4);
      opacity: 0;
    }
    25% {
      transform: translate(-50%, -30%) scale(1.2);
      opacity: 1;
    }
    50% {
      transform: translate(-50%, -10%) scale(1.0);
      opacity: 0.8;
    }
    75% {
      transform: translate(-50%, 10%) scale(0.8);
      opacity: 0.4;
    }
    100% {
      transform: translate(-50%, 30%) scale(0.6);
      opacity: 0;
    }
  }
  
  @keyframes criticalBurst {
    0% {
      transform: translate(-50%, -50%) scale(0.1);
      opacity: 0;
    }
    8% {
      transform: translate(-50%, -50%) scale(2.2);
      opacity: 1;
    }
    20% {
      transform: translate(calc(-50% + var(--move-x) * 0.1), calc(-50% + var(--move-y) * 0.1)) scale(calc(var(--initial-scale) * 1.8));
      opacity: 0.95;
    }
    40% {
      transform: translate(calc(-50% + var(--move-x) * 0.4), calc(-50% + var(--move-y) * 0.4)) scale(calc(var(--initial-scale) * 1.5));
      opacity: 0.8;
    }
    70% {
      transform: translate(calc(-50% + var(--move-x) * 0.8), calc(-50% + var(--move-y) * 0.8)) scale(calc(var(--initial-scale) * 1.1));
      opacity: 0.4;
    }
    100% {
      transform: translate(calc(-50% + var(--move-x)), calc(-50% + var(--move-y))) scale(0.2);
      opacity: 0;
    }
  }
  
  @keyframes missSwirl {
    0% {
      transform: translate(-50%, -50%) scale(0.6);
      opacity: 0;
    }
    25% {
      transform: translate(-50%, -50%) scale(1.2);
      opacity: 0.7;
    }
    50% {
      transform: translate(-50%, -50%) scale(1.0);
      opacity: 0.5;
    }
    75% {
      transform: translate(-50%, -50%) scale(0.8);
      opacity: 0.3;
    }
    100% {
      transform: translate(-50%, -50%) scale(0.4);
      opacity: 0;
    }
  }
  
  @keyframes healRise {
    0% {
      transform: translate(-50%, -30%) scale(0.4);
      opacity: 0;
    }
    12% {
      transform: translate(-50%, -35%) scale(1.5);
      opacity: 1;
    }
    25% {
      transform: translate(calc(-50% + var(--move-x) * 0.2), calc(-50% + var(--move-y) * 0.2 - 40px)) scale(calc(var(--initial-scale) * 1.3));
      opacity: 0.95;
    }
    50% {
      transform: translate(calc(-50% + var(--move-x) * 0.5), calc(-50% + var(--move-y) * 0.5 - 70px)) scale(calc(var(--initial-scale) * 1.1));
      opacity: 0.8;
    }
    75% {
      transform: translate(calc(-50% + var(--move-x) * 0.8), calc(-50% + var(--move-y) * 0.8 - 100px)) scale(calc(var(--initial-scale) * 0.8));
      opacity: 0.5;
    }
    100% {
      transform: translate(calc(-50% + var(--move-x)), calc(-50% + var(--move-y) - 130px)) scale(0.3);
      opacity: 0;
    }
  }
</style>