import {BaseSopOperation} from "@polygonjs/polygonjs/dist/src/core/operations/sop/_Base";
import {InputCloneMode as InputCloneMode2} from "@polygonjs/polygonjs/dist/src/engine/poly/InputCloneMode";
import {Vector3 as Vector32} from "three/src/math/Vector3";
import {Quaternion as Quaternion2} from "three/src/math/Quaternion";
import {RBDAttribute, RBD_SHAPES, RBDShape} from "../../../core/physics/ammo/RBDBodyHelper";
import {TypeAssert} from "@polygonjs/polygonjs/dist/src/engine/poly/Assert";
export var RBDAttributeMode;
(function(RBDAttributeMode2) {
  RBDAttributeMode2["OBJECTS"] = "objects";
  RBDAttributeMode2["POINTS"] = "points";
})(RBDAttributeMode || (RBDAttributeMode = {}));
export const RBD_ATTRIBUTE_MODES = [RBDAttributeMode.OBJECTS, RBDAttributeMode.POINTS];
export class PhysicsRbdAttributesSopOperation extends BaseSopOperation {
  constructor() {
    super(...arguments);
    this._bbox_size = new Vector32();
    this._object_t = new Vector32();
    this._object_q = new Quaternion2();
    this._object_s = new Vector32();
  }
  static type() {
    return "physicsRbdAttributes";
  }
  cook(input_contents, params) {
    if (RBD_ATTRIBUTE_MODES[params.mode] == RBDAttributeMode.OBJECTS) {
      this._add_object_attributes(input_contents[0], params);
    } else {
      this._add_point_attributes(input_contents[0], params);
    }
    return input_contents[0];
  }
  _add_object_attributes(core_group, params) {
    const core_objects = core_group.coreObjects();
    let core_object;
    for (let i = 0; i < core_objects.length; i++) {
      core_object = core_objects[i];
      core_object.setAttribValue(RBDAttribute.ACTIVE, params.active ? 1 : 0);
      core_object.setAttribValue(RBDAttribute.MASS, params.mass);
      core_object.setAttribValue(RBDAttribute.RESTITUTION, params.restitution);
      core_object.setAttribValue(RBDAttribute.DAMPING, params.damping);
      core_object.setAttribValue(RBDAttribute.ANGULAR_DAMPING, params.angularDamping);
      core_object.setAttribValue(RBDAttribute.FRICTION, params.friction);
      core_object.setAttribValue(RBDAttribute.SIMULATED, params.simulated);
      if (params.addId == true) {
        core_object.setAttribValue(RBDAttribute.ID, core_object.object().uuid);
      }
      this._add_object_shape_specific_attributes(core_object, params);
    }
  }
  _add_object_shape_specific_attributes(core_object, params) {
    core_object.setAttribValue(RBDAttribute.SHAPE, params.shape);
    const shape = RBD_SHAPES[params.shape];
    const object = core_object.object();
    object.matrix.decompose(this._object_t, this._object_q, this._object_s);
    switch (shape) {
      case RBDShape.BOX: {
        const geometry = object.geometry;
        geometry.computeBoundingBox();
        const bbox = geometry.boundingBox;
        if (bbox) {
          bbox.getSize(this._bbox_size);
          this._bbox_size.multiply(this._object_s);
          core_object.setAttribValue(RBDAttribute.SHAPE_SIZE_BOX, this._bbox_size);
        }
        return;
      }
      case RBDShape.SPHERE: {
        const geometry = object.geometry;
        geometry.computeBoundingSphere();
        const bounding_sphere = geometry.boundingSphere;
        if (bounding_sphere) {
          const diameter = 2 * bounding_sphere.radius * this._object_s.x;
          core_object.setAttribValue(RBDAttribute.SHAPE_SIZE_SPHERE, diameter);
        }
        return;
      }
    }
    TypeAssert.unreachable(shape);
  }
  _add_point_attributes(core_group, params) {
    for (let core_point of core_group.points()) {
      core_point.setAttribValue(RBDAttribute.ACTIVE, params.active ? 1 : 0);
    }
  }
}
PhysicsRbdAttributesSopOperation.DEFAULT_PARAMS = {
  mode: RBD_ATTRIBUTE_MODES.indexOf(RBDAttributeMode.OBJECTS),
  active: true,
  shape: RBD_SHAPES.indexOf(RBDShape.BOX),
  addId: true,
  mass: 1,
  restitution: 0.5,
  damping: 0,
  angularDamping: 0,
  friction: 0.5,
  simulated: 1
};
PhysicsRbdAttributesSopOperation.INPUT_CLONED_STATE = InputCloneMode2.FROM_NODE;
