// The Conscious Being - Main Controller
import { Renderer } from './Renderer.js';
import { ParticleSystem } from './ParticleSystem.js';
import { FlockingBehavior, BreathingBehavior, FollowBehavior } from './Behaviors.js';

export class Being {
  constructor(canvas) {
    this.canvas = canvas;
    this.renderer = null;
    this.particleSystem = null;
    this.behaviors = [];

    this.mousePosition = { x: 0.5, y: 0.5 }; // Normalized 0-1
    this.target = null;
    this.mode = 'idle'; // idle, aware, engaged, background
    this.isRunning = false;
    this.lastTime = 0;
    this.initialized = false;

    // Store bound handlers for cleanup
    this._resizeHandler = this.handleResize.bind(this);

    this.init();
  }

  init() {
    try {
      // Initialize renderer with WebGL error handling
      this.renderer = new Renderer(this.canvas);

      // Initialize particle system
      this.particleSystem = new ParticleSystem(800);

      // Initialize behaviors
      this.behaviors = [
        new BreathingBehavior(),
        new FlockingBehavior(),
        new FollowBehavior()
      ];

      // Add particle system to scene
      this.renderer.add(this.particleSystem.mesh);

      // Handle resize
      window.addEventListener('resize', this._resizeHandler);

      this.initialized = true;
    } catch (error) {
      console.error('[Being] WebGL initialization failed:', error);
      this.showFallback();
    }
  }

  showFallback() {
    // Show CSS-based fallback animation when WebGL is unavailable
    if (this.canvas) {
      this.canvas.style.display = 'none';
      const fallback = document.createElement('div');
      fallback.className = 'conscious-fallback';
      fallback.innerHTML = `
        <div class="fallback-orb"></div>
        <div class="fallback-ring"></div>
        <div class="fallback-ring fallback-ring--delayed"></div>
      `;
      this.canvas.parentNode?.insertBefore(fallback, this.canvas);
    }
  }

  start() {
    if (this.isRunning || !this.initialized) return;
    this.isRunning = true;
    this.lastTime = performance.now();
    this.animate();
    console.log('[Being] Started');
  }

  stop() {
    this.isRunning = false;
    console.log('[Being] Stopped');
  }

  animate() {
    if (!this.isRunning) return;

    const currentTime = performance.now();
    const deltaTime = (currentTime - this.lastTime) / 1000; // Convert to seconds
    this.lastTime = currentTime;

    this.update(deltaTime, currentTime);
    this.renderer.render();

    requestAnimationFrame(() => this.animate());
  }

  update(deltaTime, time) {
    // Apply behaviors based on mode
    const params = {
      time,
      deltaTime,
      mousePosition: this.mousePosition,
      target: this.target,
      mode: this.mode
    };

    // Apply each behavior
    this.behaviors.forEach(behavior => {
      behavior.apply(this.particleSystem, params);
    });

    // Update particle system
    this.particleSystem.update(deltaTime);

    // Update uniforms
    this.particleSystem.material.uniforms.uTime.value = time * 0.001;
    this.particleSystem.material.uniforms.uMouse.value.set(
      this.mousePosition.x,
      this.mousePosition.y
    );
  }

  updateMousePosition(x, y) {
    // Normalize to 0-1
    this.mousePosition = {
      x: x / window.innerWidth,
      y: 1 - (y / window.innerHeight) // Flip Y for WebGL
    };

    // Update mode based on mouse activity
    if (this.mode === 'idle') {
      this.setMode('aware');
    }
  }

  setTarget(element) {
    if (!element) {
      this.target = null;
      return;
    }

    const rect = element.getBoundingClientRect();
    this.target = {
      x: (rect.left + rect.width / 2) / window.innerWidth,
      y: 1 - ((rect.top + rect.height / 2) / window.innerHeight),
      width: rect.width / window.innerWidth,
      height: rect.height / window.innerHeight
    };

    this.setMode('engaged');
  }

  clearTarget() {
    this.target = null;
    if (this.mode === 'engaged') {
      this.setMode('aware');
    }
  }

  setMode(mode) {
    if (this.mode === mode) return;

    const oldMode = this.mode;
    this.mode = mode;

    console.log(`[Being] Mode: ${oldMode} -> ${mode}`);

    // Adjust behaviors based on mode
    this.behaviors.forEach(behavior => {
      behavior.onModeChange(mode, oldMode);
    });

    // Adjust particle appearance
    if (mode === 'background') {
      this.particleSystem.setOpacity(0.3);
    } else {
      this.particleSystem.setOpacity(1.0);
    }
  }

  handleResize() {
    this.renderer.handleResize();
  }

  dispose() {
    this.stop();

    // Remove event listeners
    window.removeEventListener('resize', this._resizeHandler);

    // Dispose of WebGL resources
    if (this.renderer) {
      this.renderer.dispose();
    }
    if (this.particleSystem) {
      this.particleSystem.dispose();
    }

    this.initialized = false;
  }
}

export default Being;
