import { getType } from "@turf/invariant";
import { featureEach, geomEach } from "@turf/meta";
import pointToLineDistance from "@turf/point-to-line-distance";
import objectAssign from "object-assign";
/**
 * Returns the closest {@link Point|point}, of a {@link FeatureCollection|collection} of points,
 * to a {@link LineString|line}. The returned point has a `dist` property indicating its distance to the line.
 *
 * @name nearestPointToLine
 * @param {FeatureCollection|GeometryCollection<Point>} points Point Collection
 * @param {Feature|Geometry<LineString>} line Line Feature
 * @param {Object} [options] Optional parameters
 * @param {string} [options.units='kilometers'] unit of the output distance property
 * (eg: degrees, radians, miles, or kilometers)
 * @param {Object} [options.properties={}] Translate Properties to Point
 * @returns {Feature<Point>} the closest point
 * @example
 * var pt1 = turf.point([0, 0]);
 * var pt2 = turf.point([0.5, 0.5]);
 * var points = turf.featureCollection([pt1, pt2]);
 * var line = turf.lineString([[1,1], [-1,1]]);
 *
 * var nearest = turf.nearestPointToLine(points, line);
 *
 * //addToMap
 * var addToMap = [nearest, line];
 */
function nearestPointToLine(points, line, options) {
    if (options === void 0) { options = {}; }
    var units = options.units;
    var properties = options.properties || {};
    // validation
    var pts = normalize(points);
    if (!pts.features.length) {
        throw new Error("points must contain features");
    }
    if (!line) {
        throw new Error("line is required");
    }
    if (getType(line) !== "LineString") {
        throw new Error("line must be a LineString");
    }
    var dist = Infinity;
    var pt = null;
    featureEach(pts, function (point) {
        var d = pointToLineDistance(point, line, { units: units });
        if (d < dist) {
            dist = d;
            pt = point;
        }
    });
    /**
     * Translate Properties to final Point, priorities:
     * 1. options.properties
     * 2. inherent Point properties
     * 3. dist custom properties created by NearestPointToLine
     */
    if (pt) {
        pt.properties = objectAssign({ dist: dist }, pt.properties, properties);
    }
    // if (pt) { pt.properties = objectAssign({dist}, pt.properties, properties); }
    return pt;
}
/**
 * Convert Collection to FeatureCollection
 *
 * @private
 * @param {FeatureCollection|GeometryCollection} points Points
 * @returns {FeatureCollection<Point>} points
 */
function normalize(points) {
    var features = [];
    var type = points.geometry ? points.geometry.type : points.type;
    switch (type) {
        case "GeometryCollection":
            geomEach(points, function (geom) {
                if (geom.type === "Point") {
                    features.push({ type: "Feature", properties: {}, geometry: geom });
                }
            });
            return { type: "FeatureCollection", features: features };
        case "FeatureCollection":
            points.features = points.features.filter(function (feature) {
                return feature.geometry.type === "Point";
            });
            return points;
        default:
            throw new Error("points must be a Point Collection");
    }
}
export default nearestPointToLine;
