import { ThreeJSOverlayView } from '@googlemaps/three';
import * as THREE from 'three';
import { SVGLoader } from 'three/examples/jsm/loaders/SVGLoader.js';

export class SharedThreeJSOverlayView extends ThreeJSOverlayView {
  meshes: any = [];
  geometries: any = [];
  materials: any = [];
  positions: any = [];

  loader = new SVGLoader();
  svgString = `
    <svg class="base-svg" width="32" height="39" viewBox="0 0 32 39" fill="none" xmlns="http://www.w3.org/2000/svg">
      <g class="border">
        <path d="M4.68629 27.9907C-1.5621 21.7771 -1.5621 11.703 4.68629 5.4895C10.9347 -0.724038 21.0653 -0.724038 27.3137 5.4895C33.5621 11.703 33.5621 21.7771 27.3137 27.9907L16.7071 38.5381C16.3166 38.9264 15.6834 38.9264 15.2929 38.5381L4.68629 27.9907Z" fill="white"/>
      </g>
      <g class="background" filter="url(#filter1_i_6001_29070)">
        <path fill-rule="evenodd" clip-rule="evenodd" d="M6.09654 6.90766C0.634484 12.3393 0.634486 21.1409 6.09654 26.5725L16 36.4207L25.9035 26.5725C31.3655 21.1409 31.3655 12.3393 25.9035 6.90766C20.4352 1.46991 11.5648 1.4699 6.09654 6.90766Z" fill="#009AFF"/>
      </g>
      <defs>
        <filter id="filter1_i_6001_29070" x="2" y="2.82935" width="28" height="35.5914" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
          <feFlood flood-opacity="0" result="BackgroundImageFix"/>
          <feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
          <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>

          <feOffset dy="2"/>
          <feGaussianBlur stdDeviation="2"/>
          <feComposite in2="SourceAlpha" operator="arithmetic" k2="-1" k3="1"/>
          <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.5 0"/>
          <feBlend mode="normal" in2="shape" result="effect1_innerShadow_6001_29070"/>
        </filter>
      </defs>
    </svg>
    `;
  constructor() {
    super();
  }

  createMeshFromSVG() {
    const result = this.loader.parse(this.svgString);
    const group = new THREE.Group();

    result.paths.forEach((path) => {
      const material = new THREE.MeshBasicMaterial({ color: path.color, side: THREE.DoubleSide, depthWrite: false });

      const shapes = path.toShapes(true);
      shapes.forEach((shape) => {
        const geometry = new THREE.ShapeGeometry(shape);
        const bufferGeometry = geometry.toNonIndexed();
        bufferGeometry.center();
        const mesh = new THREE.Mesh(bufferGeometry, material);
        group.add(mesh);
      });
    });
    this.meshes.push(group); // Add to meshes array
    return group;
  }

  onAdd() {
    this.positions.forEach((position: any) => {
      const mesh = this.createMeshFromSVG();

      const group = new THREE.Group();
      // group.scale.set(80000, -80000, 0);
      group.add(mesh);
      this.updateMeshPosition(group, position);

      this.scene.add(group);
    });
  }

  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  onDraw({gl, transformer}: google.maps.WebGLDrawOptions) {
    const mapZoom = this.getMap().getZoom();
    const baseScale = 80000; // Define your base scale at zoom level 0.
    const zoomScaleFactor = Math.pow(2, mapZoom - 1); // Adjust scale based on zoom.
    const scale = (baseScale / zoomScaleFactor);
    this.meshes.forEach((mesh: any) => {

      const bbox = new THREE.Box3().setFromObject(mesh);
      // Adjust the scale based on zoom level
      mesh.scale.set(scale, -scale, 0);
      // Optionally update position or other transformations if necessary
      mesh.position.set(0, (bbox.max.y - bbox.min.y) / 2, 0);
    });

    // Original render logic
    this.camera.projectionMatrix.fromArray(
      transformer.fromLatLngAltitude(this.anchor, this.rotationArray)
    );

    gl.disable(gl.SCISSOR_TEST);

    this.onBeforeDraw();

    this.renderer.render(this.scene, this.camera);
    this.renderer.resetState();

    if (this.animationMode === "always") this.requestRedraw();
  }

  updateMeshPosition(mesh: any, latLng: any) {
    // Convert the new LatLng to world coordinates (Three.js space)
    const worldPosition = this.latLngAltitudeToVector3(latLng);
    // Update the mesh's position with the new world coordinates
    mesh.position.set(worldPosition.x, worldPosition.y, 0);

    // Notify Three.js that the position has been updated
    mesh.updateMatrixWorld();
  }
}