/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.commons.geometry.euclidean.twod;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.commons.geometry.core.Transform;
import org.apache.commons.geometry.core.precision.DoublePrecisionContext;

/** Class representing a polyline, ie, a connected series of line segments. The line
 * segments in the polyline are connected end to end, with the end vertex of the previous
 * line segment equivalent to the start vertex of the next line segment. The first segment,
 * the last segment, or both may be infinite.
 *
 * <p>Instances of this class are guaranteed to be immutable.</p>
 * @see <a href="https://en.wikipedia.org/wiki/Polygonal_chain">Polygonal chain</a>
 */
public class Polyline implements Iterable<Segment> {
    /** Polyline instance containing no segments. */
    private static final Polyline EMPTY = new Polyline(Collections.emptyList());

    /** List of line segments comprising the instance. */
    private final List<Segment> segments;

    /** Simple constructor. No validation is performed on the input segments.
     * @param segments line segments comprising the instance
     */
    private Polyline(final List<Segment> segments) {
        this.segments = Collections.unmodifiableList(segments);
    }

    /** Get the line segments comprising the polyline.
     * @return the line segments comprising the polyline
     */
    public List<Segment> getSegments() {
        return segments;
    }

    /** Get the start segment for the polyline or null if the polyline is empty.
     * @return the start segment for the polyline or null if the polyline is empty
     */
    public Segment getStartSegment() {
        if (!isEmpty()) {
            return segments.get(0);
        }
        return null;
    }

    /** Get the end segment for the polyline or null if the polyline is empty.
     * @return the end segment for the polyline or null if the polyline is empty
     */
    public Segment getEndSegment() {
        if (!isEmpty()) {
            return segments.get(segments.size() - 1);
        }
        return null;
    }

    /** Get the start vertex for the polyline or null if the polyline is empty
     * or has an infinite start segment.
     * @return the start vertex for the polyline
     */
    public Vector2D getStartVertex() {
        final Segment seg = getStartSegment();
        return (seg != null) ? seg.getStartPoint() : null;
    }

    /** Get the end vertex for the polyline or null if the polyline is empty
     * or has an infinite end segment.
     * @return the end vertex for the polyline
     */
    public Vector2D getEndVertex() {
        final Segment seg = getEndSegment();
        return (seg != null) ? seg.getEndPoint() : null;
    }

    /** Get the vertices contained in the polyline in the order they appear.
     * Closed polyline contain the start point at the beginning of the list
     * as well as the end.
     * @return the vertices contained in the polyline in order they appear
     */
    public List<Vector2D> getVertices() {
        final List<Vector2D> vertices = new ArrayList<>();

        Vector2D pt;

        // add the start point, if present
        pt = getStartVertex();
        if (pt != null) {
            vertices.add(pt);
        }

        // add end points
        for (Segment seg : segments) {
            pt = seg.getEndPoint();
            if (pt != null) {
                vertices.add(pt);
            }
        }

        return vertices;
    }

    /** Return true if the polyline has a start of end line segment that
     * extends to infinity.
     * @return true if the polyline is infinite
     */
    public boolean isInfinite() {
        return !isEmpty() && (getStartVertex() == null || getEndVertex() == null);
    }

    /** Return true if the polyline has a finite length. This will be true if there are
     * no segments in the polyline or if all segments have a finite length.
     * @return true if the polyline is finite
     */
    public boolean isFinite() {
        return !isInfinite();
    }

    /** Return true if the polyline does not contain any line segments.
     * @return true if the polyline does not contain any line segments
     */
    public boolean isEmpty() {
        return segments.isEmpty();
    }

    /** Return true if the polyline is closed, meaning that the end
     * point for the last line segment is equal to the start point
     * for the polyline.
     * @return true if the end point for the last line segment is
     *      equal to the start point for the polyline.
     */
    public boolean isClosed() {
        final Segment endSegment = getEndSegment();

        if (endSegment != null) {
            final Vector2D start = getStartVertex();
            final Vector2D end = endSegment.getEndPoint();

            return start != null && end != null && start.eq(end, endSegment.getPrecision());
        }

        return false;
    }

    /** Transform this instance with the argument, returning the result in a new instance.
     * @param transform the transform to apply
     * @return a new instance, transformed by the argument
     */
    public Polyline transform(final Transform<Vector2D> transform) {
        if (!isEmpty()) {
            final List<Segment> transformed = segments.stream()
                    .map(s -> s.transform(transform))
                    .collect(Collectors.toCollection(() -> new ArrayList<>()));

            return new Polyline(transformed);
        }

        return this;
    }

    /** Return a new instance with all line segment directions, and their order,
     * reversed. The last segment in this instance will be the first in the
     * returned instance.
     * @return a new instance with the polyline reversed
     */
    public Polyline reverse() {
        if (!isEmpty()) {
            final List<Segment> reversed = segments.stream()
                    .map(s -> s.reverse())
                    .collect(Collectors.toCollection(() -> new ArrayList<>()));
            Collections.reverse(reversed);

            return new Polyline(reversed);
        }

        return this;
    }

    /** Construct a {@link RegionBSPTree2D} from the line segments in this instance.
     * @return a bsp tree constructed from the line segments in this instance
     */
    public RegionBSPTree2D toTree() {
        RegionBSPTree2D tree = RegionBSPTree2D.empty();
        tree.insert(this);

        return tree;
    }

    /** Simplify this polyline, if possible, by combining adjacent segments that lie on the
     * same line (as determined by {@link Line#equals(Object)}).
     * @return a simplified instance
     */
    public Polyline simplify() {
        final List<Segment> simplified = new ArrayList<>();

        final int size = segments.size();

        Segment current;
        Line currentLine;
        double end;

        int idx = 0;
        int testIdx;
        while (idx < size) {
            current = segments.get(idx);
            currentLine = current.getLine();
            end = current.getSubspaceEnd();

            // try to combine with forward neighbors
            testIdx = idx + 1;
            while (testIdx < size && currentLine.equals(segments.get(testIdx).getLine())) {
                end = Math.max(end, segments.get(testIdx).getSubspaceEnd());
                ++testIdx;
            }

            if (testIdx > idx + 1) {
                // we found something to merge
                simplified.add(currentLine.segment(current.getSubspaceStart(), end));
            } else {
                simplified.add(current);
            }

            idx = testIdx;
        }

        // combine the first and last items if needed
        if (isClosed() && simplified.size() > 2 && simplified.get(0).getLine().equals(
                simplified.get(simplified.size() - 1).getLine())) {

            final Segment startSegment = simplified.get(0);
            final Segment endSegment = simplified.remove(simplified.size() - 1);

            final Segment combined = endSegment.getLine().segment(endSegment.getSubspaceStart(),
                    startSegment.getSubspaceEnd());

            simplified.set(0, combined);
        }

        return new SimplifiedPolyline(simplified);
    }

    /** {@inheritDoc} */
    @Override
    public Iterator<Segment> iterator() {
        return segments.iterator();
    }

    /** Return a string representation of the segment polyline.
     *
     * <p>In order to keep the string representation short but useful, the exact format of the return
     * value depends on the properties of the polyline. See below for examples.
     *
     * <ul>
     *      <li>Empty path
     *          <ul>
     *              <li>{@code Polyline[empty= true]}</li>
     *          </ul>
     *      </li>
     *      <li>Single segment
     *          <ul>
     *              <li>{@code Polyline[segment= Segment[lineOrigin= (0.0, 0.0), lineDirection= (1.0, 0.0)]]}</li>
     *              <li>{@code Polyline[segment= Segment[start= (0.0, 0.0), end= (1.0, 0.0)]]}</li>
     *          </ul>
     *      </li>
     *      <li>Path with infinite start segment
     *          <ul>
     *              <li>{@code Polyline[startDirection= (1.0, 0.0), vertices= [(1.0, 0.0), (1.0, 1.0)]]}</li>
     *          </ul>
     *      </li>
     *      <li>Path with infinite end segment
     *          <ul>
     *              <li>{@code Polyline[vertices= [(0.0, 1.0), (0.0, 0.0)], endDirection= (1.0, 0.0)]}</li>
     *          </ul>
     *      </li>
     *      <li>Path with infinite start and end segments
     *          <ul>
     *              <li>{@code Polyline[startDirection= (0.0, 1.0), vertices= [(0.0, 0.0)], endDirection= (1.0, 0.0)]}</li>
     *          </ul>
     *      </li>
     *      <li>Path with no infinite segments
     *          <ul>
     *              <li>{@code Polyline[vertices= [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0)]]}</li>
     *          </ul>
     *      </li>
     * </ul>
     */
    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder();
        sb.append(this.getClass().getSimpleName())
            .append('[');

        if (segments.isEmpty()) {
            sb.append("empty= true");
        } else if (segments.size() == 1) {
            sb.append("segment= ")
                .append(segments.get(0));
        } else {
            final Segment startSegment = getStartSegment();
            if (startSegment.getStartPoint() == null) {
                sb.append("startDirection= ")
                    .append(startSegment.getLine().getDirection())
                    .append(", ");
            }

            sb.append("vertices= ")
                .append(getVertices());

            final Segment endSegment = getEndSegment();
            if (endSegment.getEndPoint() == null) {
                sb.append(", endDirection= ")
                    .append(endSegment.getLine().getDirection());
            }
        }

        sb.append(']');

        return sb.toString();
    }

    /** Return a {@link Builder} instance configured with the given precision
     * context. The precision context is used when building line segments from
     * vertices and may be omitted if raw vertices are not used.
     * @param precision precision context to use when building line segments from
     *      raw vertices; may be null if raw vertices are not used.
     * @return a new {@link Builder} instance
     */
    public static Builder builder(final DoublePrecisionContext precision) {
        return new Builder(precision);
    }

    /** Build a new polyline from the given segments.
     * @param segments the segment to comprise the polyline
     * @return new polyline containing the given line segment in order
     * @throws IllegalStateException if the segments do not form a connected polyline
     */
    public static Polyline fromSegments(final Segment... segments) {
        return fromSegments(Arrays.asList(segments));
    }

    /** Build a new polyline from the given segments.
     * @param segments the segment to comprise the path
     * @return new polyline containing the given line segments in order
     * @throws IllegalStateException if the segments do not form a connected polyline
     */
    public static Polyline fromSegments(final Collection<Segment> segments) {
        Builder builder = builder(null);

        for (Segment segment : segments) {
            builder.append(segment);
        }

        return builder.build();
    }

    /** Build a new polyline from the given vertices. A line segment is created
     * from the last vertex to the first one, if the two vertices are not already
     * considered equal using the given precision context. This method is equivalent to
     * calling {@link #fromVertices(Collection, boolean, DoublePrecisionContext)
     * fromVertices(vertices, true, precision)}
     * @param vertices the vertices to construct the closed path from
     * @param precision precision context used to construct the line segment
     *      instances for the path
     * @return new closed polyline constructed from the given vertices
     * @see #fromVertices(Collection, boolean, DoublePrecisionContext)
     */
    public static Polyline fromVertexLoop(final Collection<Vector2D> vertices,
            final DoublePrecisionContext precision) {

        return fromVertices(vertices, true, precision);
    }

    /** Build a new polyline from the given vertices. No additional segment is added
     * from the last vertex to the first. This method is equivalent to calling
     * {@link #fromVertices(Collection, boolean, DoublePrecisionContext)
     * fromVertices(vertices, false, precision)}.
     * @param vertices the vertices to construct the path from
     * @param precision precision context used to construct the line segment
     *      instances for the path
     * @return new polyline constructed from the given vertices
     * @see #fromVertices(Collection, boolean, DoublePrecisionContext)
     */
    public static Polyline fromVertices(final Collection<Vector2D> vertices,
            final DoublePrecisionContext precision) {

        return fromVertices(vertices, false, precision);
    }

    /** Build a new polyline from the given vertices.
     * @param vertices the vertices to construct the path from
     * @param close if true, a line segment is created from the last vertex
     *      given to the first one, if the two vertices are not already considered
     *      equal using the given precision context.
     * @param precision precision context used to construct the line segment
     *      instances for the path
     * @return new polyline constructed from the given vertices
     */
    public static Polyline fromVertices(final Collection<Vector2D> vertices,
            final boolean close, final DoublePrecisionContext precision) {

        return builder(precision)
                .appendVertices(vertices)
                .build(close);
    }

    /** Return a line segment path containing no segments.
     * @return a line segment path containing no segments.
     */
    public static Polyline empty() {
        return EMPTY;
    }

    /** Class used to build polylines.
     */
    public static final class Builder {
        /** Line segments appended to the polyline. */
        private List<Segment> appendedSegments = null;

        /** Line segments prepended to the polyline. */
        private List<Segment> prependedSegments = null;

        /** Precision context used when creating line segments directly from vertices. */
        private DoublePrecisionContext precision;

        /** The current vertex at the start of the polyline. */
        private Vector2D startVertex;

        /** The current vertex at the end of the polyline. */
        private Vector2D endVertex;

        /** The precision context used when performing comparisons involving the current
         * end vertex.
         */
        private DoublePrecisionContext endVertexPrecision;

        /** Construct a new instance configured with the given precision context. The
         * precision context is used when building line segments from vertices and
         * may be omitted if raw vertices are not used.
         * @param precision precision context to use when creating line segments
         *      from vertices
         */
        private Builder(final DoublePrecisionContext precision) {
            setPrecision(precision);
        }

        /** Set the precision context. This context is used only when creating line segments
         * from appended or prepended vertices. It is not used when adding existing
         * {@link Segment} instances since those contain their own precision contexts.
         * @param builderPrecision precision context to use when creating line segments
         *      from vertices
         * @return this instance
         */
        public Builder setPrecision(final DoublePrecisionContext builderPrecision) {
            this.precision = builderPrecision;

            return this;
        }

        /** Get the line segment at the start of the polyline or null if
         * it does not exist.
         * @return the line segment at the start of the polyline
         */
        public Segment getStartSegment() {
            Segment start = getLast(prependedSegments);
            if (start == null) {
                start = getFirst(appendedSegments);
            }
            return start;
        }

        /** Get the line segment at the end of the polyline or null if
         * it does not exist.
         * @return the line segment at the end of the polyline
         */
        public Segment getEndSegment() {
            Segment end = getLast(appendedSegments);
            if (end == null) {
                end = getFirst(prependedSegments);
            }
            return end;
        }

        /** Append a line segment to the end of the polyline.
         * @param segment line segment to append to the polyline
         * @return the current builder instance
         * @throws IllegalStateException if the polyline contains a previous segment
         *      and the end vertex of the previous segment is not equivalent to the
         *      start vertex of the given segment.
         */
        public Builder append(final Segment segment) {
            validateSegmentsConnected(getEndSegment(), segment);
            appendInternal(segment);

            return this;
        }

        /** Add a vertex to the end of this polyline. If the polyline already has an end vertex,
         * then a line segment is added between the previous end vertex and this vertex,
         * using the configured precision context.
         * @param vertex the vertex to add
         * @return this instance
         * @see #setPrecision(DoublePrecisionContext)
         */
        public Builder append(final Vector2D vertex) {
            final DoublePrecisionContext vertexPrecision = getAddVertexPrecision();

            if (endVertex == null) {
                // make sure that we're not adding to an infinite segment
                final Segment end = getEndSegment();
                if (end != null) {
                    throw new IllegalStateException(
                            MessageFormat.format("Cannot add vertex {0} after infinite line segment: {1}",
                                    vertex, end));
                }

                // this is the first vertex added
                startVertex = vertex;
                endVertex = vertex;
                endVertexPrecision = vertexPrecision;
            } else if (!endVertex.eq(vertex, endVertexPrecision)) {
                // only add the vertex if its not equal to the end point
                // of the last segment
                appendInternal(Segment.fromPoints(endVertex, vertex, endVertexPrecision));
            }

            return this;
        }

        /** Convenience method for appending a collection of vertices to the polyline in a single method call.
         * @param vertices the vertices to append
         * @return this instance
         * @see #append(Vector2D)
         */
        public Builder appendVertices(final Collection<Vector2D> vertices) {
            for (Vector2D vertex : vertices) {
                append(vertex);
            }

            return this;
        }

        /** Convenience method for appending multiple vertices to the polyline at once.
         * @param vertices the vertices to append
         * @return this instance
         * @see #append(Vector2D)
         */
        public Builder appendVertices(final Vector2D... vertices) {
            return appendVertices(Arrays.asList(vertices));
        }

        /** Prepend a line segment to the beginning of the polyline.
         * @param segment line segment to prepend to the polyline
         * @return the current builder instance
         * @throws IllegalStateException if the polyline contains a start segment
         *      and the end vertex of the given segment is not equivalent to the
         *      start vertex of the start segment.
         */
        public Builder prepend(final Segment segment) {
            validateSegmentsConnected(segment, getStartSegment());
            prependInternal(segment);

            return this;
        }

        /** Add a vertex to the front of this polyline. If the polyline already has a start vertex,
         * then a line segment is added between this vertex and the previous start vertex,
         * using the configured precision context.
         * @param vertex the vertex to add
         * @return this instance
         * @see #setPrecision(DoublePrecisionContext)
         */
        public Builder prepend(final Vector2D vertex) {
            final DoublePrecisionContext vertexPrecision = getAddVertexPrecision();

            if (startVertex == null) {
                // make sure that we're not adding to an infinite segment
                final Segment start = getStartSegment();
                if (start != null) {
                    throw new IllegalStateException(
                            MessageFormat.format("Cannot add vertex {0} before infinite line segment: {1}",
                                    vertex, start));
                }

                // this is the first vertex added
                startVertex = vertex;
                endVertex = vertex;
                endVertexPrecision = vertexPrecision;
            } else if (!vertex.eq(startVertex, vertexPrecision)) {
                // only add if the vertex is not equal to the start
                // point of the first segment
                prependInternal(Segment.fromPoints(vertex, startVertex, vertexPrecision));
            }

            return this;
        }

        /** Convenience method for prepending a collection of vertices to the polyline in a single method call.
         * The vertices are logically prepended as a single group, meaning that the first vertex
         * in the given collection appears as the first vertex in the polyline after this method call.
         * Internally, this means that the vertices are actually passed to the {@link #prepend(Vector2D)}
         * method in reverse order.
         * @param vertices the vertices to prepend
         * @return this instance
         * @see #prepend(Vector2D)
         */
        public Builder prependVertices(final Collection<Vector2D> vertices) {
            return prependVertices(vertices.toArray(new Vector2D[0]));
        }

        /** Convenience method for prepending multiple vertices to the polyline in a single method call.
         * The vertices are logically prepended as a single group, meaning that the first vertex
         * in the given collection appears as the first vertex in the polyline after this method call.
         * Internally, this means that the vertices are actually passed to the {@link #prepend(Vector2D)}
         * method in reverse order.
         * @param vertices the vertices to prepend
         * @return this instance
         * @see #prepend(Vector2D)
         */
        public Builder prependVertices(final Vector2D... vertices) {
            for (int i = vertices.length - 1; i >= 0; --i) {
                prepend(vertices[i]);
            }

            return this;
        }

        /** Close the current polyline and build a new {@link Polyline} instance.  This method is equivalent
         * to {@code builder.build(true)}.
         * @return new closed polyline instance
         */
        public Polyline close() {
            return build(true);
        }

        /** Build a {@link Polyline} instance from the configured polyline. This method is equivalent
         * to {@code builder.build(false)}.
         * @return new polyline instance
         */
        public Polyline build() {
            return build(false);
        }

        /** Build a {@link Polyline} instance from the configured polyline.
         * @param close if true, the path will be closed by adding an end point equivalent to the
         *      start point
         * @return new polyline instance
         */
        public Polyline build(final boolean close) {
            if (close) {
                closePath();
            }

            // combine all of the segments
            List<Segment> result = null;

            if (prependedSegments != null) {
                result = prependedSegments;
                Collections.reverse(result);
            }

            if (appendedSegments != null) {
                if (result == null) {
                    result = appendedSegments;
                } else {
                    result.addAll(appendedSegments);
                }
            }

            if (result == null) {
                result = Collections.emptyList();
            }

            if (result.isEmpty() && startVertex != null) {
                throw new IllegalStateException(
                        MessageFormat.format("Unable to create polyline; only a single vertex provided: {0} ",
                                startVertex));
            }

            // clear internal state
            appendedSegments = null;
            prependedSegments = null;

            // build the final polyline instance, using the shared empty instance if
            // no segments are present
            return result.isEmpty() ? empty() : new Polyline(result);
        }

        /** Close the path by adding an end point equivalent to the path start point.
         * @throws IllegalStateException if the path cannot be closed
         */
        private void closePath() {
            final Segment end = getEndSegment();

            if (end != null) {
                if (startVertex != null && endVertex != null) {
                    if (!endVertex.eq(startVertex, endVertexPrecision)) {
                        appendInternal(Segment.fromPoints(endVertex, startVertex, endVertexPrecision));
                    }
                } else {
                    throw new IllegalStateException("Unable to close polyline: polyline is infinite");
                }
            }
        }

        /** Validate that the given segments are connected, meaning that the end vertex of {@code previous}
         * is equivalent to the start vertex of {@code next}. The segments are considered valid if either
         * segment is null.
         * @param previous previous segment
         * @param next next segment
         * @throws IllegalStateException if previous and next are not null and the end vertex of previous
         *      is not equivalent the start vertex of next
         */
        private void validateSegmentsConnected(final Segment previous, final Segment next) {
            if (previous != null && next != null) {
                final Vector2D nextStartVertex = next.getStartPoint();
                final Vector2D previousEndVertex = previous.getEndPoint();
                final DoublePrecisionContext previousPrecision = previous.getPrecision();

                if (nextStartVertex == null || previousEndVertex == null ||
                        !(nextStartVertex.eq(previousEndVertex, previousPrecision))) {

                    throw new IllegalStateException(
                            MessageFormat.format("Polyline segments are not connected: previous= {0}, next= {1}",
                                    previous, next));
                }
            }
        }

        /** Get the precision context used when adding raw vertices to the polyline. An exception is thrown
         * if no precision has been specified.
         * @return the precision context used when creating working with raw vertices
         * @throws IllegalStateException if no precision context is configured
         */
        private DoublePrecisionContext getAddVertexPrecision() {
            if (precision == null) {
                throw new IllegalStateException("Unable to create line segment: no vertex precision specified");
            }

            return precision;
        }

        /** Append the given, validated segment to the polyline.
         * @param segment validated segment to append
         */
        private void appendInternal(final Segment segment) {
            if (appendedSegments == null) {
                appendedSegments = new ArrayList<>();
            }

            if (appendedSegments.isEmpty() &&
                    (prependedSegments == null || prependedSegments.isEmpty())) {
                startVertex = segment.getStartPoint();
            }

            endVertex = segment.getEndPoint();
            endVertexPrecision = segment.getPrecision();

            appendedSegments.add(segment);
        }

        /** Prepend the given, validated segment to the polyline.
         * @param segment validated segment to prepend
         */
        private void prependInternal(final Segment segment) {
            if (prependedSegments == null) {
                prependedSegments = new ArrayList<>();
            }

            startVertex = segment.getStartPoint();

            if (prependedSegments.isEmpty() &&
                    (appendedSegments == null || appendedSegments.isEmpty())) {
                endVertex = segment.getEndPoint();
                endVertexPrecision = segment.getPrecision();
            }

            prependedSegments.add(segment);
        }

        /** Get the first element in the list or null if the list is null
         * or empty.
         * @param list the list to return the first item from
         * @return the first item from the given list or null if it does not exist
         */
        private Segment getFirst(final List<Segment> list) {
            if (list != null && !list.isEmpty()) {
                return list.get(0);
            }
            return null;
        }

        /** Get the last element in the list or null if the list is null
         * or empty.
         * @param list the list to return the last item from
         * @return the last item from the given list or null if it does not exist
         */
        private Segment getLast(final List<Segment> list) {
            if (list != null && !list.isEmpty()) {
                return list.get(list.size() - 1);
            }
            return null;
        }
    }

    /** Internal class returned when a polyline is simplified to remove
     * unecessary line segments divisions. The {@link #simplify()} method on this
     * class simply returns the same instance.
     */
    private static final class SimplifiedPolyline extends Polyline {
        /** Create a new instance containing the given line segments. No validation is
         * performed on the inputs. Caller must ensure that the given segments represent
         * a valid, simplified path.
         * @param segments line segments comprising the path
         */
        private SimplifiedPolyline(final List<Segment> segments) {
            super(segments);
        }

        /** {@inheritDoc} */
        @Override
        public Polyline simplify() {
            // already simplified
            return this;
        }
    }
}
