/*
 * Copyright 2015 The gRPC Authors
 *
 * Licensed 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 fish.payara.example.grpc;

import io.grpc.examples.routeguide.Feature;
import io.grpc.examples.routeguide.Point;
import javax.enterprise.context.ApplicationScoped;

import static java.lang.Math.*;
import static java.lang.Math.sqrt;

/**
 * Common utilities for the RouteGuide demo.
 */
@ApplicationScoped
public class RouteGuideUtil {
    private final double COORD_FACTOR = 1e7;

    /**
     * Gets the latitude for the given point.
     */
    public double getLatitude(Point location) {
        return location.getLatitude() / COORD_FACTOR;
    }

    /**
     * Gets the longitude for the given point.
     */
    public double getLongitude(Point location) {
        return location.getLongitude() / COORD_FACTOR;
    }


    /**
     * Indicates whether the given feature exists (i.e. has a valid name).
     */
    public boolean exists(Feature feature) {
        return feature != null && !feature.getName().isEmpty();
    }



    /**
     * Calculate the distance between two points using the "haversine" formula.
     * The formula is based on http://mathforum.org/library/drmath/view/51879.html.
     *
     * @param start The starting point
     * @param end   The end point
     * @return The distance between the points in meters
     */
    public int calcDistance(Point start, Point end) {
        int r = 6371000; // earth radius in meters
        double lat1 = toRadians(getLatitude(start));
        double lat2 = toRadians(getLatitude(end));
        double lon1 = toRadians(getLongitude(start));
        double lon2 = toRadians(getLongitude(end));
        double deltaLat = lat2 - lat1;
        double deltaLon = lon2 - lon1;

        double a = sin(deltaLat / 2) * sin(deltaLat / 2)
                + cos(lat1) * cos(lat2) * sin(deltaLon / 2) * sin(deltaLon / 2);
        double c = 2 * atan2(sqrt(a), sqrt(1 - a));

        return (int) (r * c);
    }

}