import {AfterViewInit, Component, ElementRef, OnDestroy, ViewChild} from '@angular/core';
import {MatMiniFabButton} from '@angular/material/button';

import {IntersectionPlaneService, PlaneOrientation} from '../../services/intersection-plane.service';
import {MatIcon} from '@angular/material/icon';
import {MatTooltip} from '@angular/material/tooltip';
import {RendererService} from '../../services/renderer.service';
import {PlayerModelService} from '../../services/player-model.service';
import {InputHandlerService} from '../../services/input-handler.service';
import {FormsModule} from '@angular/forms';
import {MatFormField, MatInput, MatLabel} from '@angular/material/input';

@Component({
  selector: 'app-render-container',
  imports: [
    MatIcon,
    MatMiniFabButton,
    MatTooltip,
    FormsModule,
    MatInput,
    MatFormField,
    MatLabel
],
  templateUrl: './render-container.component.html',
  styleUrl: './render-container.component.scss'
})
export class RenderContainerComponent implements AfterViewInit, OnDestroy {
  @ViewChild('rendererContainer') rendererContainer!: ElementRef;

  constructor(
    private intersectionPlaneService: IntersectionPlaneService,
    private playerModelService: PlayerModelService,
    private inputHandlerService: InputHandlerService,
    private rendererService: RendererService,
  ) {
  }

  ngAfterViewInit(): void {
    this.initializeScene();
    this.animate();
  }

  /**
   * Clean up resources when component is destroyed
   */
  ngOnDestroy(): void {
    if (this.rendererService.renderer) {
      this.inputHandlerService.cleanup(this.rendererService.renderer.domElement);
    }
  }

  /**
   * Initialize the 3D scene and all related components
   */
  private initializeScene(): void {
    this.rendererService.initializeRenderer(this.rendererContainer);
    this.playerModelService.loadSkinTexture('/public/img/skins/steve.png')
      .then(() => {
        // Then create the player model with the texture applied
        this.playerModelService.createPlayerModel();
      });
    this.intersectionPlaneService.createIntersectionPlane();
    this.inputHandlerService.initializeInputHandlers(this.rendererService.renderer.domElement);
  }

  /**
   * Animation loop
   */
  private animate(): void {
    requestAnimationFrame(this.animate.bind(this));
    this.intersectionPlaneService.updatePlaneOrientation(this.rendererService.camera);
    this.rendererService.render();
  }

  /**
   * Get whether the plane is locked
   */
  public get isPlaneLocked(): boolean {
    return this.intersectionPlaneService.isPlaneLocked();
  }

  public set opacity(opacity: number) {
    this.intersectionPlaneService.currentOpacity = opacity;
  }

  public get opacity(): number {
    return this.intersectionPlaneService.currentOpacity;
  }

  /**
   * Toggle the plane locked state
   */
  public togglePlaneLock(): void {
    const newLockedState = !this.isPlaneLocked;
    this.intersectionPlaneService.setPlaneLocked(newLockedState);
  }

  public resetCamera(): void {
    this.rendererService.resetCamera();
  }

  /**
   * Get the current plane orientation
   */
  public get currentPlaneOrientation(): PlaneOrientation {
    return this.intersectionPlaneService.getCurrentOrientation();
  }

  /**
   * Set the plane orientation
   */
  public setPlaneOrientation(orientation: PlaneOrientation): void {
    this.intersectionPlaneService.setPlaneOrientation(orientation);
  }

  /**
   * Get all available plane orientations
   */
  public get planeOrientations(): typeof PlaneOrientation {
    return PlaneOrientation;
  }
}
