import {TypedSopNode} from "./_Base";
import {
  AttribSize,
  ATTRIBUTE_TYPES,
  AttribType,
  AttribTypeMenuEntries,
  objectTypeFromConstructor
} from "../../../core/geometry/Constant";
import {NodeParamsConfig, ParamConfig} from "../utils/params/ParamsConfig";
import {CoreObject} from "../../../core/geometry/Object";
import {CoreGeometry} from "../../../core/geometry/Geometry";
import {MapUtils as MapUtils2} from "../../../core/MapUtils";
class DeleteSopParamsConfig extends NodeParamsConfig {
  constructor() {
    super(...arguments);
    this.attribType = ParamConfig.INTEGER(ATTRIBUTE_TYPES.indexOf(AttribType.NUMERIC), {
      menu: {
        entries: AttribTypeMenuEntries
      }
    });
    this.attribName = ParamConfig.STRING("");
  }
}
const ParamsConfig2 = new DeleteSopParamsConfig();
export class SplitSopNode extends TypedSopNode {
  constructor() {
    super(...arguments);
    this.params_config = ParamsConfig2;
    this._new_objects = [];
  }
  static type() {
    return "split";
  }
  static displayedInputNames() {
    return ["geometry to split in multiple objects"];
  }
  initializeNode() {
    this.io.inputs.setCount(1);
  }
  async cook(input_contents) {
    const core_group = input_contents[0];
    this._new_objects = [];
    if (this.pv.attribName != "") {
      this._split_core_group(core_group);
    }
    this.setObjects(this._new_objects);
  }
  async _split_core_group(core_group) {
    const core_objects = core_group.coreObjects();
    for (let core_object of core_objects) {
      this._split_core_object(core_object);
    }
  }
  _split_core_object(core_object) {
    let core_geometry = core_object.coreGeometry();
    let attribName = this.pv.attribName;
    let points_by_value = new Map();
    if (core_geometry) {
      const object = core_object.object();
      const points = core_geometry.pointsFromGeometry();
      const first_point = points[0];
      if (first_point) {
        const attrib_size = first_point.attribSize(attribName);
        if (!(attrib_size == AttribSize.FLOAT || first_point.isAttribIndexed(attribName))) {
          this.states.error.set(`attrib '${attribName}' must be a float or a string`);
          return;
        }
        let val;
        if (first_point.isAttribIndexed(attribName)) {
          for (let point of points) {
            val = point.indexedAttribValue(attribName);
            MapUtils2.push_on_array_at_entry(points_by_value, val, point);
          }
        } else {
          for (let point of points) {
            val = point.attribValue(attribName);
            MapUtils2.push_on_array_at_entry(points_by_value, val, point);
          }
        }
      }
      const object_type = objectTypeFromConstructor(object.constructor);
      points_by_value.forEach((points2, value) => {
        const new_geometry = CoreGeometry.geometryFromPoints(points2, object_type);
        if (new_geometry) {
          const object2 = this.create_object(new_geometry, object_type);
          CoreObject.addAttribute(object2, attribName, value);
          this._new_objects.push(object2);
        }
      });
    }
  }
}
