/**
 * SIM-05: Treibhauseffekt — Canvas Renderer
 *
 * Visualisiert:
 * - Sonne → Sonnenstrahlen → Erdoberfläche
 * - Wärmestrahlung von der Erde nach oben
 * - CO₂-Schicht fängt Wärmestrahlung ab (je dicker, desto mehr)
 * - Temperaturanzeige
 * - Auswirkungen (Meeresspiegel, Eis, Extremereignisse)
 *
 * Stil: Skandinavisch minimal — gedeckte Farben, sanfte Animationen
 */

import { TreibhausSimulation, computeTemperature, computeEffects } from './logic'

interface Particle {
  x: number; y: number; vx: number; vy: number
  type: 'solar' | 'heat' | 'reflected'
  life: number; maxLife: number
  absorbed: boolean
}

export class TreibhausRenderer {
  private canvas: HTMLCanvasElement
  private ctx: CanvasRenderingContext2D
  private sim: TreibhausSimulation
  private W = 0
  private H = 0
  private t = 0
  private particles: Particle[] = []
  private animId = 0

  // Layout zones (ratios of height)
  private sunY = 0
  private atmoTop = 0
  private atmoBot = 0
  private groundY = 0
  private seaY = 0

  // Colors — skandinavisch
  private col = {
    sky:      '#dde3da',
    space:    '#c5cdc2',
    sun:      '#e8c84a',
    sunGlow:  'rgba(232,200,74,0.15)',
    solar:    '#e8c84a',
    heat:     '#c07a6b',
    reflected:'#8ab0b8',
    co2:      'rgba(180,160,130,VAR)',  // opacity varies
    ground:   '#8a9a82',
    groundDark:'#6a7a62',
    sea:      '#9ab5b8',
    ice:      '#d8e0dc',
    text:     '#1a1a1a',
    muted:    '#6a6a6a',
  }

  constructor(container: HTMLElement, sim: TreibhausSimulation) {
    this.sim = sim

    this.canvas = document.createElement('canvas')
    this.canvas.style.cssText = 'width:100%;height:100%;display:block;border-radius:12px;'
    container.appendChild(this.canvas)

    const ctx = this.canvas.getContext('2d')
    if (!ctx) throw new Error('Canvas not supported')
    this.ctx = ctx

    this.resize()
    window.addEventListener('resize', () => this.resize())
  }

  private resize(): void {
    const rect = this.canvas.parentElement!.getBoundingClientRect()
    const dpr = window.devicePixelRatio || 1
    this.W = rect.width
    this.H = Math.min(rect.width * 0.65, 500)
    this.canvas.width = this.W * dpr
    this.canvas.height = this.H * dpr
    this.canvas.style.height = this.H + 'px'
    this.ctx.setTransform(dpr, 0, 0, dpr, 0, 0)

    // Layout zones
    this.sunY = this.H * 0.08
    this.atmoTop = this.H * 0.25
    this.atmoBot = this.H * 0.45
    this.groundY = this.H * 0.7
    this.seaY = this.H * 0.75
  }

  start(): void {
    const loop = () => {
      this.t += 0.016
      this.update()
      this.draw()
      this.animId = requestAnimationFrame(loop)
    }
    loop()
  }

  stop(): void {
    cancelAnimationFrame(this.animId)
  }

  private update(): void {
    const co2 = this.sim.getVariable('co2')
    const absorptionRate = Math.min(0.9, (co2 - 200) / 800 * 0.85)

    // Spawn solar particles
    if (Math.random() < 0.15) {
      this.particles.push({
        x: this.W * 0.3 + Math.random() * this.W * 0.4,
        y: 0,
        vx: (Math.random() - 0.5) * 0.3,
        vy: 1.5 + Math.random() * 0.5,
        type: 'solar',
        life: 0, maxLife: 300,
        absorbed: false,
      })
    }

    // Update particles
    for (let i = this.particles.length - 1; i >= 0; i--) {
      const p = this.particles[i]
      p.x += p.vx
      p.y += p.vy
      p.life++

      if (p.type === 'solar' && p.y >= this.groundY) {
        // Solar hits ground → becomes heat radiation going up
        p.type = 'heat'
        p.vy = -(1.0 + Math.random() * 0.5)
        p.vx = (Math.random() - 0.5) * 0.8
        p.y = this.groundY - 2
      }

      if (p.type === 'heat' && !p.absorbed && p.y <= this.atmoBot && p.y >= this.atmoTop) {
        // Heat in CO₂ layer — chance of absorption
        if (Math.random() < absorptionRate * 0.03) {
          p.absorbed = true
          p.vy = 0.8 + Math.random() * 0.5  // reflected back down
          p.vx = (Math.random() - 0.5) * 1.2
          p.type = 'reflected'
        }
      }

      // Remove particles that leave the canvas
      if (p.y < -10 || p.y > this.H + 10 || p.x < -20 || p.x > this.W + 20 || p.life > p.maxLife) {
        this.particles.splice(i, 1)
      }
    }

    // Cap particles
    if (this.particles.length > 120) {
      this.particles.splice(0, this.particles.length - 120)
    }
  }

  private draw(): void {
    const { ctx, W, H } = this
    const co2 = this.sim.getVariable('co2')
    const albedo = this.sim.getVariable('albedo')
    const temp = computeTemperature(co2, albedo)
    const effects = computeEffects(temp)
    const co2Opacity = Math.min(0.4, (co2 - 200) / 800 * 0.35)

    ctx.clearRect(0, 0, W, H)

    // Background — space/sky gradient
    const skyGrad = ctx.createLinearGradient(0, 0, 0, this.groundY)
    skyGrad.addColorStop(0, this.col.space)
    skyGrad.addColorStop(0.3, this.col.sky)
    skyGrad.addColorStop(1, '#c8d4c6')
    ctx.fillStyle = skyGrad
    ctx.fillRect(0, 0, W, this.groundY)

    // Sun
    const sunX = W * 0.8
    const sunR = 28
    // Glow
    const glow = ctx.createRadialGradient(sunX, this.sunY, sunR * 0.5, sunX, this.sunY, sunR * 3)
    glow.addColorStop(0, 'rgba(232,200,74,0.3)')
    glow.addColorStop(1, 'rgba(232,200,74,0)')
    ctx.fillStyle = glow
    ctx.fillRect(sunX - sunR * 3, this.sunY - sunR * 3, sunR * 6, sunR * 6)
    // Sun disc
    ctx.fillStyle = this.col.sun
    ctx.beginPath()
    ctx.arc(sunX, this.sunY, sunR, 0, Math.PI * 2)
    ctx.fill()

    // CO₂ layer
    ctx.fillStyle = `rgba(180,160,130,${co2Opacity})`
    ctx.fillRect(0, this.atmoTop, W, this.atmoBot - this.atmoTop)
    // CO₂ label
    ctx.fillStyle = `rgba(100,80,60,${Math.min(0.6, co2Opacity + 0.15)})`
    ctx.font = '11px Inter, sans-serif'
    ctx.textAlign = 'left'
    ctx.fillText(`CO₂: ${co2} ppm`, 12, this.atmoTop + 16)

    // Atmosphere borders (subtle)
    ctx.strokeStyle = `rgba(150,130,100,${co2Opacity * 0.5})`
    ctx.lineWidth = 0.5
    ctx.setLineDash([4, 4])
    ctx.beginPath()
    ctx.moveTo(0, this.atmoTop); ctx.lineTo(W, this.atmoTop)
    ctx.moveTo(0, this.atmoBot); ctx.lineTo(W, this.atmoBot)
    ctx.stroke()
    ctx.setLineDash([])

    // Ground
    ctx.fillStyle = this.col.ground
    ctx.fillRect(0, this.groundY, W, H - this.groundY)
    // Ground detail — hills
    ctx.fillStyle = this.col.groundDark
    ctx.beginPath()
    ctx.moveTo(0, this.groundY)
    for (let x = 0; x <= W; x += 5) {
      ctx.lineTo(x, this.groundY - Math.sin(x * 0.02 + 1) * 6 - Math.sin(x * 0.007) * 10)
    }
    ctx.lineTo(W, H); ctx.lineTo(0, H); ctx.closePath()
    ctx.fill()

    // Sea (rises with temperature)
    const seaRise = effects.seaLevelRise * 0.15
    const seaLevel = this.seaY - seaRise
    ctx.fillStyle = this.col.sea
    ctx.globalAlpha = 0.7
    ctx.fillRect(W * 0.55, seaLevel, W * 0.45, H - seaLevel)
    ctx.globalAlpha = 1

    // Ice cap (shrinks with temperature)
    const iceWidth = W * 0.12 * (effects.arcticIce / 100)
    if (iceWidth > 2) {
      ctx.fillStyle = this.col.ice
      ctx.beginPath()
      ctx.ellipse(W * 0.15, this.groundY - 8, iceWidth, 8, 0, 0, Math.PI * 2)
      ctx.fill()
    }

    // Small trees
    for (let i = 0; i < 5; i++) {
      const tx = W * 0.05 + i * W * 0.09
      this.drawTree(ctx, tx, this.groundY - 12, 0.5 + Math.sin(i) * 0.15)
    }

    // Small houses
    this.drawHouse(ctx, W * 0.35, this.groundY - 10, 0.7)
    this.drawHouse(ctx, W * 0.42, this.groundY - 8, 0.5)

    // Particles
    for (const p of this.particles) {
      ctx.globalAlpha = Math.max(0, 1 - p.life / p.maxLife) * 0.7
      if (p.type === 'solar') {
        ctx.fillStyle = this.col.solar
        ctx.beginPath()
        ctx.arc(p.x, p.y, 2.5, 0, Math.PI * 2)
        ctx.fill()
      } else if (p.type === 'heat') {
        ctx.fillStyle = this.col.heat
        ctx.beginPath()
        ctx.arc(p.x, p.y, 2, 0, Math.PI * 2)
        ctx.fill()
      } else if (p.type === 'reflected') {
        ctx.fillStyle = this.col.heat
        ctx.globalAlpha *= 0.8
        ctx.beginPath()
        ctx.arc(p.x, p.y, 2.5, 0, Math.PI * 2)
        ctx.fill()
      }
      ctx.globalAlpha = 1
    }

    // Temperature display
    this.drawThermometer(ctx, W - 55, this.groundY * 0.5, temp)

    // Info panel bottom
    ctx.fillStyle = 'rgba(255,255,255,0.75)'
    ctx.fillRect(0, H - 50, W, 50)
    ctx.fillStyle = this.col.text
    ctx.font = 'bold 13px Inter, sans-serif'
    ctx.textAlign = 'left'
    ctx.fillText(`🌡️ ${temp.toFixed(1)}°C`, 15, H - 20)
    ctx.font = '11px Inter, sans-serif'
    ctx.fillStyle = this.col.muted
    ctx.fillText(`Meeresspiegel: +${effects.seaLevelRise.toFixed(0)} cm`, W * 0.25, H - 20)
    ctx.fillText(`Arktis-Eis: ${effects.arcticIce.toFixed(0)}%`, W * 0.52, H - 20)
    ctx.fillText(`Extremereignisse: ×${effects.extremeEvents.toFixed(1)}`, W * 0.75, H - 20)
  }

  private drawThermometer(ctx: CanvasRenderingContext2D, x: number, y: number, temp: number): void {
    const h = 80
    const w = 14
    const fill = Math.max(0, Math.min(1, (temp + 20) / 50)) // -20..+30°C range

    // Background
    ctx.fillStyle = 'rgba(255,255,255,0.6)'
    ctx.beginPath()
    ctx.roundRect(x - w/2, y - h/2, w, h, 7)
    ctx.fill()
    ctx.strokeStyle = 'rgba(0,0,0,0.1)'
    ctx.lineWidth = 1
    ctx.stroke()

    // Fill
    const fillH = h * fill * 0.85
    const fillColor = temp > 17 ? '#c07a6b' : temp > 15 ? '#c4a35a' : '#4a7c8a'
    ctx.fillStyle = fillColor
    ctx.beginPath()
    ctx.roundRect(x - w/2 + 2, y + h/2 - fillH - 2, w - 4, fillH, 4)
    ctx.fill()

    // Temperature text
    ctx.fillStyle = this.col.text
    ctx.font = 'bold 11px Inter, sans-serif'
    ctx.textAlign = 'center'
    ctx.fillText(`${temp.toFixed(1)}°`, x, y - h/2 - 6)
  }

  private drawTree(ctx: CanvasRenderingContext2D, x: number, y: number, s: number): void {
    ctx.fillStyle = '#5a5a4a'
    ctx.fillRect(x - 1.5 * s, y, 3 * s, 10 * s)
    ctx.fillStyle = '#6a8a5e'
    ctx.beginPath()
    ctx.arc(x, y - 2 * s, 8 * s, 0, Math.PI * 2)
    ctx.fill()
  }

  private drawHouse(ctx: CanvasRenderingContext2D, x: number, y: number, s: number): void {
    // Wall
    ctx.fillStyle = '#d8c8b0'
    ctx.fillRect(x - 8 * s, y - 10 * s, 16 * s, 12 * s)
    // Roof
    ctx.fillStyle = '#c07a6b'
    ctx.beginPath()
    ctx.moveTo(x - 10 * s, y - 10 * s)
    ctx.lineTo(x, y - 18 * s)
    ctx.lineTo(x + 10 * s, y - 10 * s)
    ctx.closePath()
    ctx.fill()
    // Window
    ctx.fillStyle = '#a8c8d0'
    ctx.fillRect(x - 3 * s, y - 7 * s, 6 * s, 5 * s)
  }
}
