/**********************************************************************
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.osgeo.org
 *
 * Copyright (C) 2016 Daniel Baston
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************
 *
 * Last port: operation/distance/FacetSequence.java (f6187ee2 JTS-1.14)
 *
 **********************************************************************/

#pragma once

#include <geos/geom/Envelope.h>
#include <geos/geom/Coordinate.h>

namespace geos {
namespace geom {
class CoordinateSequence;
}
}

namespace geos {
namespace operation {
namespace distance {

class FacetSequence {

private:

    const geom::CoordinateSequence* pts;
    const std::size_t start;
    const std::size_t end;

    /*
    * Unlike JTS, we store the envelope in the FacetSequence so
    * that it has a clear owner.  This is helpful when making a
    * tree of FacetSequence objects (FacetSequenceTreeBuilder)
    */
    geom::Envelope env;

    double computeDistanceLineLine(const FacetSequence& facetSeq,
                                   std::vector<geom::Coordinate> *locs) const;

    double computeDistancePointLine(const geom::Coordinate& pt,
                                    const FacetSequence& facetSeq,
                                    std::vector<geom::Coordinate> *locs) const;

    void updateNearestLocationsPointLine(const geom::Coordinate& pt,
                                         const geom::Coordinate& q0, const geom::Coordinate &q1,
                                         std::vector<geom::Coordinate> *locs) const;

    void updateNearestLocationsLineLine(const geom::Coordinate& p0, const geom::Coordinate& p1,
                                        const geom::Coordinate& q0, const geom::Coordinate &q1,
                                        std::vector<geom::Coordinate> *locs) const;

    void computeEnvelope();

public:

    const geom::Envelope* getEnvelope() const;

    const geom::Coordinate* getCoordinate(std::size_t index) const;

    std::size_t size() const;

    bool isPoint() const;

    double distance(const FacetSequence& facetSeq) const;

    FacetSequence(const geom::CoordinateSequence* pts, std::size_t start, std::size_t end);

    /**
     * Computes the locations of the nearest points between this sequence
     * and another sequence.
     * The locations are presented in the same order as the input sequences.
     *
     * @return a pair of {@link Coordinate}s for the nearest points
     */
    std::vector<geom::Coordinate> nearestLocations(const FacetSequence& facetSeq) const;

};

}
}
}

