import "@hotwired/turbo-rails"
import { Application } from "@hotwired/stimulus"

import LocaleController from "locale_controller"
import ImageController from "image_controller"

const application = Application.start()

application.register("locale", LocaleController)
application.register("image", ImageController)

// Configure Stimulus development experience
application.debug = false
window.Stimulus = application

export { application }

var animationElements
var originalHeights


document.addEventListener('turbo:render', (event) => {
  console.info('turbo:render')
  
  let errorElements = document.querySelectorAll('.field_with_errors')

  if (errorElements.length > 0) {
    animationElements = document.querySelectorAll('.animation-element');
    gsap.set(animationElements, {
      opacity: 1    
    })  
  }
});


// document.addEventListener("turbo:before-stream-render", animateElements)
document.addEventListener("turbo:load", animateElements)


function animateElements(event) {

  console.info(event.type)
  
  // Copy link to clipboard
  document.querySelectorAll('[data-share-title]').forEach((share_btn) => {  
    share_btn.addEventListener('click', (e) => {        

      if (navigator.share) {
        navigator.share({
            title: e.currentTarget.getAttribute('data-share-title'),
            text:  e.currentTarget.getAttribute('data-share-text'),
            url: e.currentTarget.getAttribute('data-share-url'),
        }).then(() => {
            console.log('Thanks for sharing!');
        })
        .catch(console.error);
      } else {
        navigator.clipboard.writeText(window.location.href)
        alert('URL copied to clipboard!')
      }      
    })
  })
  
  originalHeights = []
  animationElements = document.querySelectorAll('.animation-element');

  animationElements.forEach((animationElement, index) => {
    const height = animationElement.offsetHeight
    originalHeights.push(height)    
    // console.log(`Element ${index + 1} height: ${height}px`)
  })

  gsap.set(animationElements, {
    height: 0,
    opacity: 0,
    overflow: 'hidden'
  })

  let typewriterElements = document.querySelectorAll('.typewriter-text');
  if (typewriterElements.length > 0) {
    gsap.set(typewriterElements, {
      opacity: 0
    })
  }

  // Start the sequential animation
  animateElementsSequentially();

}




function animateElementsSequentially(index = 0) {
  
  if (index >= animationElements.length) {
    console.log('All animations complete');
    return;
  }

  // 'margin-top': (index == (animationElements.length-1) ? "12px" : "8px"),

  gsap.to(animationElements[index], {
    height: originalHeights[index],
    opacity: 1,
    duration: (0.004 * originalHeights[index]),        
    delay: (index > 0 ? 0.4 : 0),
    ease: "power2.out",
    onComplete: () => {
      
      // Typewriter
      const typewriterTexts = animationElements[index].querySelectorAll('.typewriter-text')      
      if (typewriterTexts.length > 0) {
        const typewriter = typeWriterConsoleSequential(typewriterTexts[0].parentElement, {
          baseSpeed: 20,
          onAllComplete: () => {
            // Start next element after typewriter finishes
            animateElementsSequentially(index + 1);
          }
        })
        typewriter.start()
        return
      }

      // % Answer Distributions
      const answerDistributions = animationElements[index].querySelectorAll('.answer-distribution')
      if (answerDistributions.length > 0 ) {

        const containerHeight = animationElements[index].offsetHeight - 8; // - padding

        const percentages = Array.from(answerDistributions).map(bar => parseInt(bar.dataset.value));
        const maxPercentage = Math.max(...percentages);
        
        console.info(maxPercentage)
        
        answerDistributions.forEach((bar, i) => {
          const percentage = parseInt(bar.dataset.value);
          const relativePercentage = (percentage / maxPercentage) * 100;
          const calculatedHeight = (relativePercentage / 100) * containerHeight;
        
          
          const computedStyle = window.getComputedStyle(bar);
          const minHeight = parseInt(computedStyle.minHeight) || 0;

          const targetHeight = Math.max(calculatedHeight, minHeight);

          gsap.to(bar, {
            height: targetHeight,
            duration: 0.4,
            ease: "power2.out",
            delay: index * 0.1,
            onAllComplete: () => {

              if (bar.dataset.answered != undefined) {
                bar.classList.add('answered')
              }

              gsap.to(bar.querySelectorAll('.percentage'), {
                opacity: 1,
                duration: 0.4,
                onAllComplete: function() {
                  const explanationElement = this.targets()[0].nextElementSibling
                  if (explanationElement) {
                    explanationElement.style.display = 'block'
                  }                  
                }
              })
              

              if (i == (answerDistributions.length - 1)) {
                setTimeout(() => animateElementsSequentially(index + 1), 1000);
                
              }
            }
          });
          
        })
        return
      }

      
      animateElementsSequentially(index + 1);
      
      
    }
  });
}







function typeWriterConsoleSequential(container, options = {}) {
  const {
    selector = '.typewriter-text',
    baseSpeed = 60,
    divDelay = 600,
    showCursor = true,
    onDivComplete = null,
    onAllComplete = null
  } = options;

  const textDivs = container.querySelectorAll(selector);
  if (textDivs.length === 0) return null;

  let currentDivIndex = 0;
  let isActive = false;
  let animationId = null;
  let timeoutIds = new Set(); // Track all timeouts for cleanup

  // Cleanup function for Turbo navigation
  function cleanup() {
    isActive = false;
    if (animationId) {
      cancelAnimationFrame(animationId);
      animationId = null;
    }
    // Clear all timeouts
    timeoutIds.forEach(id => clearTimeout(id));
    timeoutIds.clear();
  }

  // Set up Turbo event listeners for cleanup
  function setupTurboListeners() {
    const turboEvents = ['turbo:before-visit', 'turbo:before-cache', 'beforeunload'];
    
    turboEvents.forEach(eventName => {
      document.addEventListener(eventName, cleanup, { once: false });
    });

    // Store cleanup function on container for manual cleanup
    container._typewriterCleanup = cleanup;
  }

  // Enhanced setTimeout that tracks IDs
  function safeSetTimeout(callback, delay) {
    const id = setTimeout(() => {
      timeoutIds.delete(id);
      if (isActive) callback();
    }, delay);
    timeoutIds.add(id);
    return id;
  }

  // Store original text and prepare divs
  function initializeDivs() {  
    // Set container height to prevent layout shifts
    const containerHeight = container.offsetHeight;
    container.style.minHeight = `${containerHeight}px`;
    
    textDivs.forEach(div => {
      if (!div.dataset.originalText) {
        div.dataset.originalText = div.textContent.trim();
      }
      // Use visibility instead of blanking content to maintain layout
      div.style.visibility = 'hidden';
      div.innerHTML = '';
      div.style.opacity = '1';
    });
    
    // Force reflow to ensure styles are applied
    container.offsetHeight;
  }

  function createCursorSpan() {
    // No longer needed - cursor is now handled via CSS
    return null;
  }

  function updateDivContent(div, text, withCursor = false) {
    // Use textContent for better performance
    div.textContent = text;
    
    // Toggle cursor class instead of adding DOM element
    if (withCursor && showCursor) {
      div.classList.add('typewriter-cursor');
    } else {
      div.classList.remove('typewriter-cursor');
    }
  }

  function animateNextDiv() {
    if (currentDivIndex >= textDivs.length || !isActive) {
      isActive = false;
      if (onAllComplete) {
        // Use setTimeout to avoid potential timing issues
        requestAnimationFrame(() => {
          safeSetTimeout(() => onAllComplete(container), 200);
        });
      }
      return;
    }

    const currentDiv = textDivs[currentDivIndex];
    const originalText = currentDiv.dataset.originalText;
    const isLastDiv = currentDivIndex === textDivs.length - 1;

    // Make div visible and prepare for typing
    currentDiv.style.visibility = 'visible';
    updateDivContent(currentDiv, '', showCursor);
    currentDiv.classList.add('typing-active');

    let charIndex = 0;
    let nextCharTime = performance.now() + 200; // Initial delay

    function typeFrame(currentTime) {
      if (!isActive) {
        if (animationId) {
          cancelAnimationFrame(animationId);
          animationId = null;
        }
        return;
      }

      if (currentTime >= nextCharTime && charIndex < originalText.length) {
        charIndex++;
        const currentText = originalText.substring(0, charIndex);
        updateDivContent(currentDiv, currentText, true);

        // Calculate delay for next character
        let delay = baseSpeed + Math.random() * 30;
        const char = originalText.charAt(charIndex - 1);

        if (char === '.' || char === '!' || char === '?') {
          delay += 250;
        } else if (char === ',' || char === ';') {
          delay += 120;
        } else if (char === ' ') {
          delay += 60;
        }

        nextCharTime = currentTime + delay;
      }

      // Check if current div is complete
      if (charIndex >= originalText.length) {
        currentDiv.classList.remove('typing-active');

        // Final content update
        updateDivContent(currentDiv, originalText, showCursor);

        if (onDivComplete) {
          onDivComplete(currentDiv, currentDivIndex, container);
        }

        currentDivIndex++;

        if (isActive && currentDivIndex < textDivs.length) {
          // Move to next div after delay
          safeSetTimeout(() => {
            if (isActive) {
              // Remove cursor from previous div (except last one)
              if (!isLastDiv) {
                updateDivContent(currentDiv, originalText, false);
              }
              animateNextDiv();
            }
          }, divDelay);
        } else if (isActive) {
          // This was the last div
          safeSetTimeout(() => {
            if (onAllComplete) {
              onAllComplete(container);
            }
          }, 200);
        }
        return;
      }

      // Continue animation
      if (isActive) {
        animationId = requestAnimationFrame(typeFrame);
      }
    }

    // Start the animation
    animationId = requestAnimationFrame(typeFrame);
  }

  // Initialize Turbo listeners
  setupTurboListeners();

  // Add required CSS for cursor pseudo-element
  function addCursorStyles() {
    const styleId = 'typewriter-cursor-styles';
    if (!document.getElementById(styleId)) {
      const style = document.createElement('style');
      style.id = styleId;
      style.textContent = `
        .typewriter-cursor::after {
          content: '|';
          animation: typewriter-blink 1s infinite;
          color: currentColor;
        }
        
        @keyframes typewriter-blink {
          0%, 50% { opacity: 1; }
          51%, 100% { opacity: 0; }
        }
      `;
      document.head.appendChild(style);
    }
  }

  // Initialize styles
  addCursorStyles();

  return {
    start: () => {
      if (isActive) return; // Prevent multiple starts
      
      initializeDivs();
      isActive = true;
      currentDivIndex = 0;
      
      // Use requestAnimationFrame for smoother start
      requestAnimationFrame(() => {
        if (isActive) {
          animateNextDiv();
        }
      });
    },
    
    stop: () => {
      cleanup();
    },
    
    reset: () => {
      cleanup();
      
      textDivs.forEach(div => {
        if (div.dataset.originalText) {
          div.style.visibility = 'visible';
          updateDivContent(div, div.dataset.originalText, false);
          div.classList.remove('typing-active');
          div.classList.remove('typewriter-cursor');
        }
      });
      currentDivIndex = 0;
    },
    
    // Manual cleanup method for explicit cleanup
    destroy: () => {
      cleanup();
      // Remove Turbo event listeners
      const turboEvents = ['turbo:before-visit', 'turbo:before-cache', 'beforeunload'];
      turboEvents.forEach(eventName => {
        document.removeEventListener(eventName, cleanup);
      });
      // Remove cleanup reference
      delete container._typewriterCleanup;
    },
    
    get isActive() { return isActive; }
  };
}