/**
 * Vereinfachter Neuronales Netzwerk Hintergrund
 * Verwendet Canvas 2D anstelle von WebGL für bessere Leistung
 */

class NeuralNetworkBackground {
  constructor() {
    // Canvas einrichten
    this.canvas = document.createElement('canvas');
    this.canvas.id = 'neural-network-background';
    this.canvas.style.position = 'fixed';
    this.canvas.style.top = '0';
    this.canvas.style.left = '0';
    this.canvas.style.width = '100%';
    this.canvas.style.height = '100%';
    this.canvas.style.zIndex = '-10';
    this.canvas.style.pointerEvents = 'none';
    this.canvas.style.opacity = '1';
    this.canvas.style.transition = 'opacity 3.5s ease-in-out';
    
    // Falls Canvas bereits existiert, entfernen
    const existingCanvas = document.getElementById('neural-network-background');
    if (existingCanvas) {
      existingCanvas.remove();
    }
    
    // An body anhängen als erstes Kind
    if (document.body.firstChild) {
      document.body.insertBefore(this.canvas, document.body.firstChild);
    } else {
      document.body.appendChild(this.canvas);
    }
    
    // 2D Context
    this.ctx = this.canvas.getContext('2d');
    
    // Eigenschaften
    this.nodes = [];
    this.connections = [];
    this.activeConnections = new Set();
    this.animationFrameId = null;
    this.isDestroying = false;
    
    // Farben - Lila Farbpalette
    this.colors = {
      background: '#040215',
      nodeColor: '#6a5498',
      nodePulse: '#9c7fe0',
      connectionColor: '#4a3870',
      flowColor: '#b47fea'
    };
    
    // Konfiguration
    this.config = {
      nodeCount: 80,            // Anzahl der Knoten
      nodeSize: 2.5,            // Größe der Knoten
      connectionDistance: 150,  // Maximale Verbindungsdistanz
      connectionOpacity: 0.5,   // Erhöht von 0.3 auf 0.5 - Deckkraft der ständigen Verbindungen
      animationSpeed: 0.15,     // Geschwindigkeit der Animation
      flowDensity: 2,           // Anzahl aktiver Verbindungen
      maxFlowsPerNode: 2,       // Maximale Anzahl aktiver Verbindungen pro Knoten
      flowDuration: [2000, 5000], // Min/Max Dauer des Flows in ms
      nodePulseFrequency: 0.01  // Wie oft Knoten pulsieren
    };
    
    // Initialisieren
    this.init();
    
    // Event-Listener
    window.addEventListener('resize', this.resizeCanvas.bind(this));
    
    console.log('Vereinfachter Neural Network Background initialized');
  }
  
  init() {
    this.resizeCanvas();
    this.createNodes();
    this.createConnections();
    this.startAnimation();
  }
  
  resizeCanvas() {
    const pixelRatio = window.devicePixelRatio || 1;
    const width = window.innerWidth;
    const height = window.innerHeight;
    
    this.canvas.style.width = width + 'px';
    this.canvas.style.height = height + 'px';
    this.canvas.width = width * pixelRatio;
    this.canvas.height = height * pixelRatio;
    
    if (this.ctx) {
      this.ctx.scale(pixelRatio, pixelRatio);
    }
    
    // Neuberechnung der Knotenpositionen nach Größenänderung
    if (this.nodes.length) {
      this.createNodes();
      this.createConnections();
    }
  }
  
  createNodes() {
    this.nodes = [];
    const width = this.canvas.width / (window.devicePixelRatio || 1);
    const height = this.canvas.height / (window.devicePixelRatio || 1);
    
    // Cluster-Zentren für realistisches neuronales Netzwerk
    const clusterCount = Math.floor(6 + Math.random() * 4);
    const clusters = [];
    
    for (let i = 0; i < clusterCount; i++) {
      clusters.push({
        x: Math.random() * width,
        y: Math.random() * height,
        radius: 100 + Math.random() * 150
      });
    }
    
    // Knoten erstellen
    for (let i = 0; i < this.config.nodeCount; i++) {
      // Wähle zufällig ein Cluster
      const cluster = clusters[Math.floor(Math.random() * clusters.length)];
      
      // Erstelle einen Knoten innerhalb des Clusters mit zufälligem Offset
      const angle = Math.random() * Math.PI * 2;
      const distance = Math.random() * cluster.radius;
      
      const node = {
        id: i,
        x: cluster.x + Math.cos(angle) * distance,
        y: cluster.y + Math.sin(angle) * distance,
        size: this.config.nodeSize * (0.8 + Math.random() * 0.4),
        speed: {
          x: (Math.random() - 0.5) * 0.2,
          y: (Math.random() - 0.5) * 0.2
        },
        lastPulse: 0,
        pulseInterval: 5000 + Math.random() * 10000, // Zufälliges Pulsieren
        connections: []
      };
      
      this.nodes.push(node);
    }
  }
  
  createConnections() {
    this.connections = [];
    
    // Verbindungen zwischen Knoten erstellen
    for (let i = 0; i < this.nodes.length; i++) {
      const nodeA = this.nodes[i];
      
      for (let j = i + 1; j < this.nodes.length; j++) {
        const nodeB = this.nodes[j];
        
        const dx = nodeA.x - nodeB.x;
        const dy = nodeA.y - nodeB.y;
        const distance = Math.sqrt(dx * dx + dy * dy);
        
        if (distance < this.config.connectionDistance) {
          const connection = {
            id: `${i}-${j}`,
            from: i,
            to: j,
            distance: distance,
            opacity: Math.max(0.05, 1 - (distance / this.config.connectionDistance)),
            active: false,
            flowProgress: 0,
            flowDuration: 0,
            flowStart: 0
          };
          
          this.connections.push(connection);
          nodeA.connections.push(connection);
          nodeB.connections.push(connection);
        }
      }
    }
  }
  
  startAnimation() {
    this.animate();
  }
  
  animate() {
    this.animationFrameId = requestAnimationFrame(this.animate.bind(this));
    
    const now = Date.now();
    this.updateNodes(now);
    this.updateConnections(now);
    this.render(now);
  }
  
  updateNodes(now) {
    const width = this.canvas.width / (window.devicePixelRatio || 1);
    const height = this.canvas.height / (window.devicePixelRatio || 1);
    
    // Knoten bewegen
    for (let i = 0; i < this.nodes.length; i++) {
      const node = this.nodes[i];
      
      node.x += node.speed.x;
      node.y += node.speed.y;
      
      // Begrenzung am Rand
      if (node.x < 0 || node.x > width) {
        node.speed.x *= -1;
      }
      
      if (node.y < 0 || node.y > height) {
        node.speed.y *= -1;
      }
      
      // Zufällig Richtung ändern
      if (Math.random() < 0.01) {
        node.speed.x = (Math.random() - 0.5) * 0.2;
        node.speed.y = (Math.random() - 0.5) * 0.2;
      }
      
      // Zufälliges Pulsieren
      if (Math.random() < this.config.nodePulseFrequency && now - node.lastPulse > node.pulseInterval) {
        node.lastPulse = now;
      }
    }
  }
  
  updateConnections(now) {
    // Update aktive Verbindungen
    for (const connectionId of this.activeConnections) {
      const connection = this.connections.find(c => c.id === connectionId);
      if (!connection) continue;
      
      // Aktualisiere den Flow-Fortschritt
      const elapsed = now - connection.flowStart;
      const progress = elapsed / connection.flowDuration;
      
      if (progress >= 1) {
        // Flow beenden
        connection.active = false;
        this.activeConnections.delete(connectionId);
      } else {
        connection.flowProgress = progress;
      }
    }
    
    // Neue Flows starten, wenn unter dem Limit
    if (this.activeConnections.size < this.config.flowDensity) {
      // Wähle eine zufällige Verbindung
      const availableConnections = this.connections.filter(c => !c.active);
      
      if (availableConnections.length > 0) {
        const randomIndex = Math.floor(Math.random() * availableConnections.length);
        const connection = availableConnections[randomIndex];
        
        // Aktiviere die Verbindung
        connection.active = true;
        connection.flowProgress = 0;
        connection.flowStart = now;
        connection.flowDuration = this.config.flowDuration[0] + 
                                 Math.random() * (this.config.flowDuration[1] - this.config.flowDuration[0]);
        
        this.activeConnections.add(connection.id);
      }
    }
  }
  
  render(now) {
    const colors = this.colors;
    const width = this.canvas.width / (window.devicePixelRatio || 1);
    const height = this.canvas.height / (window.devicePixelRatio || 1);
    
    // Hintergrund löschen
    this.ctx.fillStyle = colors.background;
    this.ctx.fillRect(0, 0, width, height);
    
    // Verbindungen zeichnen (statisch)
    this.ctx.strokeStyle = colors.connectionColor;
    this.ctx.lineWidth = 1.2;
    
    for (const connection of this.connections) {
      const fromNode = this.nodes[connection.from];
      const toNode = this.nodes[connection.to];
      
      this.ctx.globalAlpha = connection.opacity * 0.5;
      
      this.ctx.beginPath();
      this.ctx.moveTo(fromNode.x, fromNode.y);
      this.ctx.lineTo(toNode.x, toNode.y);
      this.ctx.stroke();
    }
    
    // Aktive Verbindungen zeichnen (Flows)
    this.ctx.strokeStyle = colors.flowColor;
    this.ctx.lineWidth = 2.5;
    
    for (const connectionId of this.activeConnections) {
      const connection = this.connections.find(c => c.id === connectionId);
      if (!connection) continue;
      
      const fromNode = this.nodes[connection.from];
      const toNode = this.nodes[connection.to];
      
      // Glühen-Effekt
      this.ctx.globalAlpha = Math.sin(connection.flowProgress * Math.PI) * 0.8;
      
      // Linie zeichnen
      this.ctx.beginPath();
      this.ctx.moveTo(fromNode.x, fromNode.y);
      this.ctx.lineTo(toNode.x, toNode.y);
      this.ctx.stroke();
      
      // Fließendes Partikel
      const progress = connection.flowProgress;
      const x = fromNode.x + (toNode.x - fromNode.x) * progress;
      const y = fromNode.y + (toNode.y - fromNode.y) * progress;
      
      this.ctx.globalAlpha = 0.9;
      this.ctx.fillStyle = colors.flowColor;
      
      this.ctx.beginPath();
      this.ctx.arc(x, y, 2, 0, Math.PI * 2);
      this.ctx.fill();
    }
    
    // Knoten zeichnen
    for (const node of this.nodes) {
      // Pulsierende Knoten
      const timeSinceLastPulse = now - node.lastPulse;
      const isPulsing = timeSinceLastPulse < 800;
      const pulseProgress = isPulsing ? timeSinceLastPulse / 800 : 0;
      
      // Knoten selbst
      this.ctx.globalAlpha = 1;
      this.ctx.fillStyle = isPulsing 
        ? colors.nodePulse 
        : colors.nodeColor;
      
      this.ctx.beginPath();
      this.ctx.arc(node.x, node.y, node.size + (isPulsing ? 1 * Math.sin(pulseProgress * Math.PI) : 0), 0, Math.PI * 2);
      this.ctx.fill();
      
      // Wenn pulsierend, füge einen Glow-Effekt hinzu
      if (isPulsing) {
        this.ctx.globalAlpha = 0.5 * (1 - pulseProgress);
        this.ctx.beginPath();
        this.ctx.arc(node.x, node.y, node.size + 5 * pulseProgress, 0, Math.PI * 2);
        this.ctx.fill();
      }
    }
    
    this.ctx.globalAlpha = 1;
  }
  
  destroy() {
    if (this.isDestroying) return;
    this.isDestroying = true;
    
    // Animation stoppen
    if (this.animationFrameId) {
      cancelAnimationFrame(this.animationFrameId);
    }
    
    // Canvas ausblenden
    this.canvas.style.opacity = '0';
    
    // Nach Übergang entfernen
    setTimeout(() => {
      if (this.canvas && this.canvas.parentNode) {
        this.canvas.parentNode.removeChild(this.canvas);
      }
    }, 3500);
  }
  
  hexToRgb(hex) {
    const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
    return result ? {
      r: parseInt(result[1], 16),
      g: parseInt(result[2], 16),
      b: parseInt(result[3], 16)
    } : null;
  }
}

// Initialisiert den Hintergrund, sobald die Seite geladen ist
document.addEventListener('DOMContentLoaded', () => {
  window.neuralBackground = new NeuralNetworkBackground();
  
  // Sicherstellen, dass die Seite immer im Dark Mode ist
  document.documentElement.classList.add('dark');
  document.body.classList.add('dark');
}); 