import { Vector2, Mesh, BufferGeometry, Float32BufferAttribute, DoubleSide, PlaneGeometry } from "../../../../../../three@0.154.0/node_modules/three/build/three.module.js";
import { Damper } from "./Damper.js";
/* @license
 * Copyright 2020 Google LLC. All Rights Reserved.
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
const RADIUS = 0.2;
const LINE_WIDTH = 0.03;
const MAX_OPACITY = 0.75;
const SEGMENTS = 12;
const DELTA_PHI = Math.PI / (2 * SEGMENTS);
const vector2 = new Vector2();
const addCorner = (vertices, cornerX, cornerY) => {
  let phi = cornerX > 0 ? cornerY > 0 ? 0 : -Math.PI / 2 : cornerY > 0 ? Math.PI / 2 : Math.PI;
  for (let i = 0; i <= SEGMENTS; ++i) {
    vertices.push(cornerX + (RADIUS - LINE_WIDTH) * Math.cos(phi), cornerY + (RADIUS - LINE_WIDTH) * Math.sin(phi), 0, cornerX + RADIUS * Math.cos(phi), cornerY + RADIUS * Math.sin(phi), 0);
    phi += DELTA_PHI;
  }
};
class PlacementBox extends Mesh {
  constructor(scene, side) {
    const geometry = new BufferGeometry();
    const triangles = [];
    const vertices = [];
    const { size, boundingBox } = scene;
    const x = size.x / 2;
    const y = (side === "back" ? size.y : size.z) / 2;
    addCorner(vertices, x, y);
    addCorner(vertices, -x, y);
    addCorner(vertices, -x, -y);
    addCorner(vertices, x, -y);
    const numVertices = vertices.length / 3;
    for (let i2 = 0; i2 < numVertices - 2; i2 += 2) {
      triangles.push(i2, i2 + 1, i2 + 3, i2, i2 + 3, i2 + 2);
    }
    const i = numVertices - 2;
    triangles.push(i, i + 1, 1, i, 1, 0);
    geometry.setAttribute("position", new Float32BufferAttribute(vertices, 3));
    geometry.setIndex(triangles);
    super(geometry);
    this.side = side;
    const material = this.material;
    material.side = DoubleSide;
    material.transparent = true;
    material.opacity = 0;
    this.goalOpacity = 0;
    this.opacityDamper = new Damper();
    this.hitPlane = new Mesh(new PlaneGeometry(2 * (x + RADIUS), 2 * (y + RADIUS)));
    this.hitPlane.visible = false;
    this.hitPlane.material.side = DoubleSide;
    this.add(this.hitPlane);
    boundingBox.getCenter(this.position);
    switch (side) {
      case "bottom":
        this.rotateX(-Math.PI / 2);
        this.shadowHeight = boundingBox.min.y;
        this.position.y = this.shadowHeight;
        break;
      case "back":
        this.shadowHeight = boundingBox.min.z;
        this.position.z = this.shadowHeight;
    }
    scene.target.add(this);
    this.offsetHeight = 0;
  }
  /**
   * Get the world hit position if the touch coordinates hit the box, and null
   * otherwise. Pass the scene in to get access to its raycaster.
   */
  getHit(scene, screenX, screenY) {
    vector2.set(screenX, -screenY);
    this.hitPlane.visible = true;
    const hitResult = scene.positionAndNormalFromPoint(vector2, this.hitPlane);
    this.hitPlane.visible = false;
    return hitResult == null ? null : hitResult.position;
  }
  getExpandedHit(scene, screenX, screenY) {
    this.hitPlane.scale.set(1e3, 1e3, 1e3);
    this.hitPlane.updateMatrixWorld();
    const hitResult = this.getHit(scene, screenX, screenY);
    this.hitPlane.scale.set(1, 1, 1);
    return hitResult;
  }
  /**
   * Offset the height of the box relative to the bottom of the scene. Positive
   * is up, so generally only negative values are used.
   */
  set offsetHeight(offset) {
    offset -= 1e-3;
    if (this.side === "back") {
      this.position.z = this.shadowHeight + offset;
    } else {
      this.position.y = this.shadowHeight + offset;
    }
  }
  get offsetHeight() {
    if (this.side === "back") {
      return this.position.z - this.shadowHeight;
    } else {
      return this.position.y - this.shadowHeight;
    }
  }
  /**
   * Set the box's visibility; it will fade in and out.
   */
  set show(visible) {
    this.goalOpacity = visible ? MAX_OPACITY : 0;
  }
  /**
   * Call on each frame with the frame delta to fade the box.
   */
  updateOpacity(delta) {
    const material = this.material;
    material.opacity = this.opacityDamper.update(material.opacity, this.goalOpacity, delta, 1);
    this.visible = material.opacity > 0;
  }
  /**
   * Call this to clean up Three's cache when you remove the box.
   */
  dispose() {
    var _a;
    const { geometry, material } = this.hitPlane;
    geometry.dispose();
    material.dispose();
    this.geometry.dispose();
    this.material.dispose();
    (_a = this.parent) === null || _a === void 0 ? void 0 : _a.remove(this);
  }
}
export {
  PlacementBox
};
//# sourceMappingURL=PlacementBox.js.map
