import { Vector2 } from "three/src/math/Vector2";
import { Float32BufferAttribute } from "three/src/core/BufferAttribute";
import { BufferGeometry } from "three/src/core/BufferGeometry";
import { CoreGeometry } from "@polygonjs/polygonjs/dist/src/core/geometry/Geometry";
import { ObjectType } from "@polygonjs/polygonjs/dist/src/core/geometry/Constant";
import { CoordinatesCollection } from "./CoordinatesCollection";
import { ArrayUtils } from "@polygonjs/polygonjs/dist/src/core/ArrayUtils";
import { CoreMapboxString } from "./String";
const MULTILINESTRING = "MultiLineString";
const LINESTRING = "LineString";
export class FeatureConverter {
  constructor(node, name, features) {
    this.node = node;
    this.name = name;
    this.features = features;
  }
  createObject() {
    const coordinatesCollections = this._createAllCoordinatesCollections();
    const perimeter = ArrayUtils.sum(coordinatesCollections.map((f) => f.perimeter()));
    const sortedFeatures = CoordinatesCollection.sort(coordinatesCollections);
    const lines = sortedFeatures.map((feature) => {
      return this._createLine(feature);
    });
    lines.forEach((line) => {
      const geometry = line.geometry;
      const core_geometry2 = new CoreGeometry(geometry);
      core_geometry2.addNumericAttrib("perimeter", 1, perimeter);
    });
    const geometries = lines.map((l) => l.geometry);
    const merged_geometry = CoreGeometry.merge_geometries(geometries);
    if (!merged_geometry) {
      return;
    }
    const core_geometry = new CoreGeometry(merged_geometry);
    core_geometry.addNumericAttrib("pti", 1, 0);
    const points = core_geometry.points();
    const points_count = points.length;
    for (let i = 0; i < points.length; i++) {
      const point = points[i];
      const pti = i / (points_count - 1);
      point.setAttribValue("pti", pti);
    }
    const mergedObject = this.node.createObject(merged_geometry, ObjectType.LINE_SEGMENTS);
    return mergedObject;
  }
  _createLine(coordinates_collection) {
    const points_count = coordinates_collection.coordinates.length;
    const positions = [];
    const indices = [];
    for (let i = 0; i < points_count; i++) {
      const coordinates = coordinates_collection.coordinates[i];
      positions.push(coordinates.x);
      positions.push(0);
      positions.push(coordinates.y);
      if (i > 0) {
        indices.push(i - 1);
        indices.push(i);
      }
    }
    const geometry = new BufferGeometry();
    geometry.setAttribute("position", new Float32BufferAttribute(positions, 3));
    geometry.setIndex(indices);
    const object = this.node.createObject(geometry, ObjectType.LINE_SEGMENTS);
    const core_geometry = new CoreGeometry(geometry);
    const id_from_name = CoreMapboxString.toId(this.name) % 1e7;
    core_geometry.addNumericAttrib("id", 1, this.id);
    core_geometry.addNumericAttrib("name_id", 1, id_from_name);
    return object;
  }
  _createAllCoordinatesCollections() {
    const coordinates_collections = [];
    this.features.forEach((feature) => {
      this.id = this.id || feature["id"];
      const feature_geometry = feature.geometry;
      if (feature_geometry) {
        const type = feature_geometry["type"];
        switch (type) {
          case MULTILINESTRING:
            const multi_coordinates = feature_geometry["coordinates"];
            if (multi_coordinates) {
              for (let i = 0; i < multi_coordinates.length; i++) {
                const coordinates = multi_coordinates[i];
                coordinates_collections.push(this._create_coordinates(coordinates));
              }
            }
            break;
          case LINESTRING:
            coordinates_collections.push(this._create_coordinates(feature_geometry["coordinates"]));
            break;
          default:
            console.warn(`type ${type} not taken into account`);
        }
      }
    });
    return coordinates_collections;
  }
  _create_coordinates(raw_coordinates) {
    const vectors = raw_coordinates.map((raw_coordinate) => {
      return new Vector2(raw_coordinate[0], raw_coordinate[1]);
    });
    return new CoordinatesCollection(vectors);
  }
}
