import {Component} from '@angular/core';
import {ArcRotateCamera, Camera, ShaderMaterial} from '@babylonjs/core';
import {MANDELBULB_FRAGMENT, MANDELBULB_VERTEX} from './fractal3d.shader';
import {Information} from '../information/information';
import {MatCard, MatCardContent, MatCardHeader, MatCardTitle} from '@angular/material/card';
import {TranslatePipe} from '@ngx-translate/core';
import {AlgorithmInformation} from '../information/information.models';
import {UrlConstants} from '../../../constants/UrlConstants';
import {MatButton} from '@angular/material/button';
import {BabylonCanvas, RenderCallback, RenderConfig} from '../../../shared/components/render-canvas/babylon-canvas.component';

@Component({
  selector: 'app-fractal3d',
  imports: [
    Information,
    MatCard,
    MatCardContent,
    MatCardHeader,
    MatCardTitle,
    TranslatePipe,
    MatButton,
    BabylonCanvas
  ],
  templateUrl: './fractal3d.component.html',
  styleUrl: './fractal3d.component.scss',
})
export class Fractal3dComponent {

  algoInformation: AlgorithmInformation = {
    title: 'FRACTAL3D.EXPLANATION.TITLE',
    entries: [
      {
        name: 'Mandel-Bulb',
        description: 'FRACTAL3D.EXPLANATION.MANDELBULB_EXPLANATION',
        link: UrlConstants.MANDELBULB_WIKI
      },
      {
        name: 'Mandelbox',
        description: 'FRACTAL3D.EXPLANATION.MANDELBOX_EXPLANATION',
        link: UrlConstants.MANDELBOX_WIKI
      },
      {
        name: 'Julia-Bulb',
        description: 'FRACTAL3D.EXPLANATION.JULIA_EXPLANATION',
        link: UrlConstants.JULIA3D_WIKI
      }
    ],
    disclaimer: 'FRACTAL3D.EXPLANATION.DISCLAIMER',
    disclaimerBottom: '',
    disclaimerListEntry: ['FRACTAL3D.EXPLANATION.DISCLAIMER_1', 'FRACTAL3D.EXPLANATION.DISCLAIMER_2', 'FRACTAL3D.EXPLANATION.DISCLAIMER_3', 'FRACTAL3D.EXPLANATION.DISCLAIMER_4']
  };

  fractalConfig: RenderConfig = {
    mode: '3D',
    initialViewSize: 4,
    vertexShader: MANDELBULB_VERTEX,
    fragmentShader: MANDELBULB_FRAGMENT,
    uniformNames: ["time", "power", "fractalType"]
  };

  private readonly fractalPower = 8;
  private time = 0;
  private oldType = 0;
  public currentFractalType = 0;


  onRender: RenderCallback = (material: ShaderMaterial, camera: Camera) => {
    this.time += 0.005;

    if (this.oldType != this.currentFractalType && camera instanceof ArcRotateCamera) {
      this.oldType = this.currentFractalType;
      camera.radius = this.currentFractalType == 1 ? 15 : 4;
    }

    material.setFloat("time", this.time);
    material.setFloat("power", this.fractalPower);
    material.setInt("fractalType", this.currentFractalType);
  };


  onFractalTypeChange(type: number): void {
    this.currentFractalType = type;
  }

}
