import * as THREE from 'three';
import type { Game } from './Game';

const TELEGRAPH_TIME = 0.9;
const IMPACT_RADIUS = 1.8;
const ROCK_DAMAGE = 30;
const DUST_TIME = 0.4;

export class FallingRock {
  body: THREE.Group;
  private shadow: THREE.Mesh;
  private rock: THREE.Mesh;
  private phase: 'telegraph' | 'fall' | 'dust' = 'telegraph';
  private timer = TELEGRAPH_TIME;
  private dust: THREE.Mesh[] = [];
  private dustDirs: THREE.Vector3[] = [];
  private dustMat: THREE.MeshBasicMaterial;

  constructor(pos: THREE.Vector3) {
    this.body = new THREE.Group();
    this.body.position.set(pos.x, 0, pos.z);

    // Schatten-Telegraf (waechst kurz vor dem Aufprall)
    const shadowMat = new THREE.MeshBasicMaterial({
      color: 0x000000,
      transparent: true,
      opacity: 0.3,
      depthWrite: false,
    });
    this.shadow = new THREE.Mesh(new THREE.CircleGeometry(1.6, 24), shadowMat);
    this.shadow.rotation.x = -Math.PI / 2;
    this.shadow.position.y = 0.06;
    this.shadow.scale.setScalar(0.4);
    this.body.add(this.shadow);

    // Fels von der Decke
    const rockMat = new THREE.MeshToonMaterial({ color: 0x777788 });
    this.rock = new THREE.Mesh(new THREE.BoxGeometry(0.9, 0.9, 0.9), rockMat);
    this.rock.position.y = 16;
    this.rock.rotation.set(Math.random() * 3, Math.random() * 3, Math.random() * 3);
    this.body.add(this.rock);

    this.dustMat = new THREE.MeshBasicMaterial({
      color: 0x888899,
      transparent: true,
      opacity: 0,
      depthWrite: false,
    });
  }

  update(dt: number, game: Game): boolean {
    this.timer -= dt;

    if (this.phase === 'telegraph') {
      const t = 1 - this.timer / TELEGRAPH_TIME;
      this.shadow.scale.setScalar(0.4 + t * 0.6);
      (this.shadow.material as THREE.MeshBasicMaterial).opacity = 0.2 + t * 0.2;
      if (this.timer <= 0) {
        this.phase = 'fall';
        this.timer = 2;
      }
    } else if (this.phase === 'fall') {
      this.rock.position.y -= 26 * dt;
      this.rock.rotation.x += dt * 3;
      this.rock.rotation.z += dt * 2;
      if (this.rock.position.y <= 0.15) {
        this.rock.position.y = 0.15;
        this.rock.visible = false;
        this.shadow.visible = false;

        if (game.player.health > 0) {
          const dx = game.player.body.position.x - this.body.position.x;
          const dz = game.player.body.position.z - this.body.position.z;
          if (Math.hypot(dx, dz) < IMPACT_RADIUS) {
            game.player.damage(ROCK_DAMAGE, this.body.position);
          }
        }

        // Staubwolke
        for (let i = 0; i < 5; i++) {
          const a = (i / 5) * Math.PI * 2;
          const dir = new THREE.Vector3(Math.cos(a), 0, Math.sin(a));
          const puff = new THREE.Mesh(new THREE.SphereGeometry(0.25, 6, 5), this.dustMat);
          this.body.add(puff);
          this.dust.push(puff);
          this.dustDirs.push(dir);
        }
        this.phase = 'dust';
        this.timer = DUST_TIME;
      }
    } else {
      const t = 1 - this.timer / DUST_TIME;
      for (let i = 0; i < this.dust.length; i++) {
        this.dust[i].position.copy(this.dustDirs[i]).multiplyScalar(0.5 + t * 1.8);
        this.dust[i].position.y = 0.2 + t * 0.8;
      }
      this.dustMat.opacity = 0.5 * (1 - t);
      if (this.timer <= 0) return false;
    }
    return true;
  }

  dispose() {
    this.body.removeFromParent();
    this.body.traverse((obj) => {
      if (obj instanceof THREE.Mesh) {
        obj.geometry.dispose();
        (obj.material as THREE.Material).dispose();
      }
    });
  }
}
