import * as THREE from 'three';

import * as CONSTANTS from '../../../types/world/worldConstants';
import * as Types from "../../../types/world/worldTypes";

//////////  Load the Boxes initially if there are any  //////////

function loadInitialPoint(
  lines: Types.RefLines,
  floorPlanGroupPoint: Types.RefGroup,
  currentLayerPoint: Types.RefMeshArray,
  dragPointControls: Types.RefDragControl
): void {

  if (!floorPlanGroupPoint.current) return

  floorPlanGroupPoint.current.children = [];
  currentLayerPoint.current = [];
  lines.current.forEach((line) => {
    const colour = getPointColor(line[0][3]);
    line.forEach((pointData) => {
      const [point, id] = pointData;

      /////////// Check if a box with this id already exists  //////////

      const existingBox = floorPlanGroupPoint.current?.getObjectByProperty('uuid', id);
      if (existingBox) {
        return;
      }

      const geometry = new THREE.BoxGeometry(...CONSTANTS.pointConfig.boxScale);
      const material = new THREE.ShaderMaterial({
        uniforms: {
          uColor: { value: new THREE.Color(colour) }, // Blue color for the border
          uInnerColor: { value: new THREE.Color(CONSTANTS.pointConfig.defaultInnerColor) }, // White color for the inner square
        },
        vertexShader: `
                  varying vec2 vUv;
              
                  void main() {
                    vUv = uv;
                    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
                  }
                `,
        fragmentShader: `
                  varying vec2 vUv;
                  uniform vec3 uColor;
                  uniform vec3 uInnerColor;
              
                  void main() {
                    // Define the size of the white square as a proportion of the face
                    float borderThickness = 0.2; // Adjust this value for border thickness
                    if (vUv.x > borderThickness && vUv.x < 1.0 - borderThickness && 
                        vUv.y > borderThickness && vUv.y < 1.0 - borderThickness) {
                      gl_FragColor = vec4(uInnerColor, 1.0); // White inner square
                    } else {
                      gl_FragColor = vec4(uColor, 1.0); // Blue border
                    }
                  }
                `,
      });
      const box = new THREE.Mesh(geometry, material);
      box.name = "point";
      box.uuid = id;
      box.userData = { type: line[0][3], color: colour };
      box.position.set(point.x, point.y, point.z);
      currentLayerPoint.current.push(box);

      floorPlanGroupPoint.current?.add(box);
    });
  });

  function getPointColor(lineType: string | undefined): string {
    switch (lineType) {
      case CONSTANTS.lineConfig.wallName: return CONSTANTS.pointConfig.wallOuterColor;
      case CONSTANTS.lineConfig.floorName: return CONSTANTS.pointConfig.floorOuterColor;
      case CONSTANTS.lineConfig.aisleName: return CONSTANTS.pointConfig.aisleOuterColor;
      default: return CONSTANTS.pointConfig.defaultOuterColor;
    }
  }

  if (dragPointControls.current) {
    dragPointControls.current!.objects = currentLayerPoint.current;
  }
}

export default loadInitialPoint;
