// performance-manager.ts — Performance monitoring and optimization system
// TypeScript rewrite with proper type safety

import { PerformanceStats } from './types';

class PerformanceManager {
  private frameTimes: number[] = [];
  private maxFrameHistory: number = 60;
  private lastFrameTime: number = 0;
  private fps: number = 60;
  private memoryWarnings: number = 0;
  private renderQuality: number = 1.0;
  private adaptiveMode: boolean = false;

  constructor() {
    this.setupMonitoring();
  }

  private setupMonitoring(): void {
    let lastTime = performance.now();
    let frameCount = 0;

    const monitorLoop = (currentTime: number) => {
      frameCount++;

      if (frameCount % 10 === 0) {
        const delta = currentTime - lastTime;
        const avgFrameTime = delta / 10;
        this.fps = Math.round(1000 / avgFrameTime);

        this.frameTimes.push(avgFrameTime);
        if (this.frameTimes.length > this.maxFrameHistory) {
          this.frameTimes.shift();
        }

        this.analyzePerformance();
        lastTime = currentTime;
      }

      requestAnimationFrame(monitorLoop);
    };

    requestAnimationFrame(monitorLoop);

    if (window.performance && (performance as any).memory) {
      setInterval(() => this.checkMemory(), 2000);
    }
  }

  private analyzePerformance(): void {
    if (this.frameTimes.length < 10) return;

    const sorted = [...this.frameTimes].sort((a, b) => a - b);
    const avgFrameTime = sorted.reduce((a, b) => a + b, 0) / sorted.length;
    const p90FrameTime = sorted[Math.floor(sorted.length * 0.9)];

    const frameBudget = 16; // 16ms for 60fps

    if (p90FrameTime > frameBudget * 1.5) {
      this.setRenderQuality(Math.max(0.5, this.renderQuality - 0.2));
      this.adaptiveMode = true;
    } else if (p90FrameTime > frameBudget * 1.2) {
      this.setRenderQuality(Math.max(0.7, this.renderQuality - 0.1));
    } else if (avgFrameTime < frameBudget * 0.8 && this.adaptiveMode) {
      this.setRenderQuality(Math.min(1.0, this.renderQuality + 0.05));

      if (this.renderQuality >= 0.95) {
        this.adaptiveMode = false;
      }
    }
  }

  private checkMemory(): void {
    try {
      // Use type assertion for non-standard memory API
      const perf = performance as { memory?: { usedJSHeapSize: number; jsHeapSizeLimit: number } };
      const memory = perf.memory;
      
      if (!memory) {
        throw new Error('Memory API not available');
      }
      
      const usedHeap = memory.usedJSHeapSize;
      const heapLimit = memory.jsHeapSizeLimit;
      const usageRatio = usedHeap / heapLimit;

      if (usageRatio > 0.8) {
        this.memoryWarnings++;

        if (this.memoryWarnings > 3) {
          this.triggerMemoryCleanup();
          this.memoryWarnings = 0;
        }

        this.setRenderQuality(Math.max(0.6, this.renderQuality - 0.1));
      } else {
        this.memoryWarnings = Math.max(0, this.memoryWarnings - 0.5);
      }
    } catch (e) {
      console.warn('Memory monitoring not available:', e);
    }
  }

  private triggerMemoryCleanup(): void {
    if (window.gc) {
      window.gc();
    }
  }

  setRenderQuality(quality: number): void {
    this.renderQuality = Math.max(0.3, Math.min(1.0, quality));
    console.debug(`[Perf] Render quality adjusted to: ${(this.renderQuality * 100).toFixed(0)}%`);
  }

  getCurrentQuality(): number {
    return this.renderQuality;
  }

  isPerformanceCritical(): boolean {
    return this.adaptiveMode || this.fps < 45;
  }

  getPerformanceStats(): PerformanceStats {
    return {
      fps: this.fps,
      avgFrameTime: this.frameTimes.length > 0
        ? this.frameTimes.reduce((a, b) => a + b, 0) / this.frameTimes.length
        : 0,
      renderQuality: this.renderQuality,
      adaptiveMode: this.adaptiveMode
    };
  }

  cleanup(): void {
    this.frameTimes = [];
  }
}

export { PerformanceManager };