// Path: src/main/java/com/indoqa/solr/spatial/corridor/direction/InDirectionUtils.java
// public class InDirectionUtils {
// 
//     private InDirectionUtils() {
//         //hide utility class
//     }
// 
//     public static int percentageOfPointsWithinDistanceTo(LineString route, List<Point> points, double pointsMaxDistanceToRoute) {
//         LocationIndexedLine lineRef = new LocationIndexedLine(route);
// 
//         int result = 0;
// 
//         for (Point point : points) {
//             LinearLocation loc = lineRef.project(point.getCoordinate());
//             Coordinate nearestPoint = lineRef.extractPoint(loc);
// 
//             double distance = nearestPoint.distance(point.getCoordinate()) * WGS84_TO_KILOMETERS_FACTOR;
// 
//             if (distance <= pointsMaxDistanceToRoute) {
//                 result++;
//             }
//         }
// 
//         return Double.valueOf((double) result / points.size() * 100).intValue();
//     }
// 
//     public static boolean checkAngleDifferenceInThirdOrFourthQuadrant(double actualDifference, double maxDifference) {
//         return actualDifference >= 180 - maxDifference && actualDifference <= 180 + maxDifference;
//     }
// 
//     public static boolean checkAngleDifferenceInFirstOrSecondQuadrant(double actualDifference, double maxDifference) {
//         if (actualDifference >= 360 - maxDifference && actualDifference <= 360) {
//             return true;
//         }
// 
//         if (actualDifference >= 0 && actualDifference <= maxDifference) {
//             return true;
//         }
// 
//         return false;
//     }
// }
// 
// Path: src/main/java/com/indoqa/solr/spatial/corridor/debug/DebugValues.java
// public interface DebugValues {
// 
//     void add(String key, String value);
//     void add(String key, boolean value);
//     void add(String key, Number value);
// 
//     void addAngleDifference(String key, String value);
//     void addAngleDifference(String key, Number value);
//     void addAngleDifference(String key, Coordinate coordinate);
// 
//     void addSingleAngleDifference(String key, Number value);
// 
//     String toJson();
// }
// 
// Path: src/main/java/com/indoqa/solr/spatial/corridor/debug/NoOpDebugValues.java
// public class NoOpDebugValues implements DebugValues {
// 
//     public static NoOpDebugValues NOOP_DEBUG_VALUES = new NoOpDebugValues();
// 
//     private NoOpDebugValues() {
//         super();
//     }
// 
//     @Override
//     public void add(String key, String value) {
// 
//     }
// 
//     @Override
//     public void add(String key, boolean value) {
// 
//     }
// 
//     @Override
//     public void add(String key, Number value) {
// 
//     }
// 
//     @Override
//     public void addAngleDifference(String key, String value) {
// 
//     }
// 
//     @Override
//     public void addAngleDifference(String key, Number value) {
// 
//     }
// 
//     @Override
//     public void addAngleDifference(String key, Coordinate coordinate) {
// 
//     }
// 
//     @Override
//     public void addSingleAngleDifference(String distance, Number distance1) {
// 
//     }
// 
//     @Override
//     public String toJson() {
//         return null;
//     }
// }


import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static com.indoqa.solr.spatial.corridor.direction.InDirectionUtils.*;
import java.io.IOException;
import java.util.*;
import com.indoqa.solr.spatial.corridor.debug.DebugValues;
import com.indoqa.solr.spatial.corridor.debug.NoOpDebugValues;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.LineString;
import org.locationtech.jts.geom.Point;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.queries.function.FunctionValues;
import org.apache.lucene.queries.function.ValueSource;
/*
 * Licensed to the Indoqa Software Design und Beratung GmbH (Indoqa) under
 * one or more contributor license agreements. See the NOTICE file distributed
 * with this work for additional information regarding copyright ownership.
 * Indoqa 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 com.indoqa.solr.spatial.corridor.direction;




public class InDirectionPointsValueSource extends ValueSource {

    private static final Logger LOGGER = LoggerFactory.getLogger(InDirectionPointsValueSource.class);
    private static final GeometryFactory geometryFactory = new GeometryFactory();

    private LineString lineString;
    private ValueSource locationValueSource;

    private double maxDifference;
    private double maxDifferenceAdditionalPointsCheck;
    private double pointsMaxDistanceToRoute;
    private int percentageOfPointsWithinDistance;
    private boolean alwaysCheckPointDistancePercent;

    private DebugValues debugValues;

    public InDirectionPointsValueSource(LineString lineString, ValueSource locationValueSource, double maxDifference,
        double maxDifferenceAdditionalPointsCheck, double pointsMaxDistanceToRoute, int percentageOfPointsWithinDistance,
        boolean alwaysCheckPointDistancePercent) {

// Path: src/main/java/com/indoqa/solr/spatial/corridor/direction/InDirectionUtils.java
// public class InDirectionUtils {
// 
//     private InDirectionUtils() {
//         //hide utility class
//     }
// 
//     public static int percentageOfPointsWithinDistanceTo(LineString route, List<Point> points, double pointsMaxDistanceToRoute) {
//         LocationIndexedLine lineRef = new LocationIndexedLine(route);
// 
//         int result = 0;
// 
//         for (Point point : points) {
//             LinearLocation loc = lineRef.project(point.getCoordinate());
//             Coordinate nearestPoint = lineRef.extractPoint(loc);
// 
//             double distance = nearestPoint.distance(point.getCoordinate()) * WGS84_TO_KILOMETERS_FACTOR;
// 
//             if (distance <= pointsMaxDistanceToRoute) {
//                 result++;
//             }
//         }
// 
//         return Double.valueOf((double) result / points.size() * 100).intValue();
//     }
// 
//     public static boolean checkAngleDifferenceInThirdOrFourthQuadrant(double actualDifference, double maxDifference) {
//         return actualDifference >= 180 - maxDifference && actualDifference <= 180 + maxDifference;
//     }
// 
//     public static boolean checkAngleDifferenceInFirstOrSecondQuadrant(double actualDifference, double maxDifference) {
//         if (actualDifference >= 360 - maxDifference && actualDifference <= 360) {
//             return true;
//         }
// 
//         if (actualDifference >= 0 && actualDifference <= maxDifference) {
//             return true;
//         }
// 
//         return false;
//     }
// }
// 
// Path: src/main/java/com/indoqa/solr/spatial/corridor/debug/DebugValues.java
// public interface DebugValues {
// 
//     void add(String key, String value);
//     void add(String key, boolean value);
//     void add(String key, Number value);
// 
//     void addAngleDifference(String key, String value);
//     void addAngleDifference(String key, Number value);
//     void addAngleDifference(String key, Coordinate coordinate);
// 
//     void addSingleAngleDifference(String key, Number value);
// 
//     String toJson();
// }
// 
// Path: src/main/java/com/indoqa/solr/spatial/corridor/debug/NoOpDebugValues.java
// public class NoOpDebugValues implements DebugValues {
// 
//     public static NoOpDebugValues NOOP_DEBUG_VALUES = new NoOpDebugValues();
// 
//     private NoOpDebugValues() {
//         super();
//     }
// 
//     @Override
//     public void add(String key, String value) {
// 
//     }
// 
//     @Override
//     public void add(String key, boolean value) {
// 
//     }
// 
//     @Override
//     public void add(String key, Number value) {
// 
//     }
// 
//     @Override
//     public void addAngleDifference(String key, String value) {
// 
//     }
// 
//     @Override
//     public void addAngleDifference(String key, Number value) {
// 
//     }
// 
//     @Override
//     public void addAngleDifference(String key, Coordinate coordinate) {
// 
//     }
// 
//     @Override
//     public void addSingleAngleDifference(String distance, Number distance1) {
// 
//     }
// 
//     @Override
//     public String toJson() {
//         return null;
//     }
// }


// Path: src/main/java/com/indoqa/solr/spatial/corridor/direction/InDirectionPointsValueSource.java
import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static com.indoqa.solr.spatial.corridor.direction.InDirectionUtils.*;
import java.io.IOException;
import java.util.*;
import com.indoqa.solr.spatial.corridor.debug.DebugValues;
import com.indoqa.solr.spatial.corridor.debug.NoOpDebugValues;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.LineString;
import org.locationtech.jts.geom.Point;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.queries.function.FunctionValues;
import org.apache.lucene.queries.function.ValueSource;

/*
 * Licensed to the Indoqa Software Design und Beratung GmbH (Indoqa) under
 * one or more contributor license agreements. See the NOTICE file distributed
 * with this work for additional information regarding copyright ownership.
 * Indoqa 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 com.indoqa.solr.spatial.corridor.direction;




public class InDirectionPointsValueSource extends ValueSource {

    private static final Logger LOGGER = LoggerFactory.getLogger(InDirectionPointsValueSource.class);
    private static final GeometryFactory geometryFactory = new GeometryFactory();

    private LineString lineString;
    private ValueSource locationValueSource;

    private double maxDifference;
    private double maxDifferenceAdditionalPointsCheck;
    private double pointsMaxDistanceToRoute;
    private int percentageOfPointsWithinDistance;
    private boolean alwaysCheckPointDistancePercent;

    private DebugValues debugValues;

    public InDirectionPointsValueSource(LineString lineString, ValueSource locationValueSource, double maxDifference,
        double maxDifferenceAdditionalPointsCheck, double pointsMaxDistanceToRoute, int percentageOfPointsWithinDistance,
        boolean alwaysCheckPointDistancePercent) {

        this.lineString = lineString;