// index.js
import { geojsonRbush as rbush } from "@turf/geojson-rbush";
import { square } from "@turf/square";
import { bbox } from "@turf/bbox";
import { truncate } from "@turf/truncate";
import { lineSegment } from "@turf/line-segment";
import { lineIntersect } from "@turf/line-intersect";
import { nearestPointOnLine } from "@turf/nearest-point-on-line";
import { getCoords, getCoord, getType } from "@turf/invariant";
import { featureEach, featureReduce, flattenEach } from "@turf/meta";
import { lineString, featureCollection } from "@turf/helpers";
function lineSplit(line, splitter) {
  if (!line) throw new Error("line is required");
  if (!splitter) throw new Error("splitter is required");
  var lineType = getType(line);
  var splitterType = getType(splitter);
  if (lineType !== "LineString") throw new Error("line must be LineString");
  if (splitterType === "FeatureCollection")
    throw new Error("splitter cannot be a FeatureCollection");
  if (splitterType === "GeometryCollection")
    throw new Error("splitter cannot be a GeometryCollection");
  var truncatedSplitter = truncate(splitter, { precision: 7 });
  switch (splitterType) {
    case "Point":
      return splitLineWithPoint(line, truncatedSplitter);
    case "MultiPoint":
      return splitLineWithPoints(line, truncatedSplitter);
    case "LineString":
    case "MultiLineString":
    case "Polygon":
    case "MultiPolygon":
      return splitLineWithPoints(
        line,
        lineIntersect(line, truncatedSplitter, {
          ignoreSelfIntersections: true
        })
      );
  }
}
function splitLineWithPoints(line, splitter) {
  var results = [];
  var tree = rbush();
  flattenEach(splitter, function(point) {
    results.forEach(function(feature, index) {
      feature.id = index;
    });
    if (!results.length) {
      results = splitLineWithPoint(line, point).features;
      results.forEach(function(feature) {
        if (!feature.bbox) feature.bbox = square(bbox(feature));
      });
      tree.load(featureCollection(results));
    } else {
      var search = tree.search(point);
      if (search.features.length) {
        var closestLine = findClosestFeature(point, search);
        results = results.filter(function(feature) {
          return feature.id !== closestLine.id;
        });
        tree.remove(closestLine);
        featureEach(splitLineWithPoint(closestLine, point), function(line2) {
          results.push(line2);
          tree.insert(line2);
        });
      }
    }
  });
  return featureCollection(results);
}
function splitLineWithPoint(line, splitter) {
  var results = [];
  var startPoint = getCoords(line)[0];
  var endPoint = getCoords(line)[line.geometry.coordinates.length - 1];
  if (pointsEquals(startPoint, getCoord(splitter)) || pointsEquals(endPoint, getCoord(splitter)))
    return featureCollection([line]);
  var tree = rbush();
  var segments = lineSegment(line);
  tree.load(segments);
  var search = tree.search(splitter);
  if (!search.features.length) return featureCollection([line]);
  var closestSegment = findClosestFeature(splitter, search);
  var initialValue = [startPoint];
  var lastCoords = featureReduce(
    segments,
    function(previous, current, index) {
      var currentCoords = getCoords(current)[1];
      var splitterCoords = getCoord(splitter);
      if (index === closestSegment.id) {
        previous.push(splitterCoords);
        results.push(lineString(previous));
        if (pointsEquals(splitterCoords, currentCoords))
          return [splitterCoords];
        return [splitterCoords, currentCoords];
      } else {
        previous.push(currentCoords);
        return previous;
      }
    },
    initialValue
  );
  if (lastCoords.length > 1) {
    results.push(lineString(lastCoords));
  }
  return featureCollection(results);
}
function findClosestFeature(point, lines) {
  if (!lines.features.length) throw new Error("lines must contain features");
  if (lines.features.length === 1) return lines.features[0];
  var closestFeature;
  var closestDistance = Infinity;
  featureEach(lines, function(segment) {
    var pt = nearestPointOnLine(segment, point);
    var dist = pt.properties.dist;
    if (dist < closestDistance) {
      closestFeature = segment;
      closestDistance = dist;
    }
  });
  return closestFeature;
}
function pointsEquals(pt1, pt2) {
  return pt1[0] === pt2[0] && pt1[1] === pt2[1];
}
var turf_line_split_default = lineSplit;
export {
  turf_line_split_default as default,
  lineSplit
};
//# sourceMappingURL=index.js.map