/*
 * 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.flink.training.exercises.common.utils;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * GeoUtils provides utility methods to deal with locations for the data streaming exercises.
 */
public class GeoUtils {

	// geo boundaries of the area of NYC
	public static final double LON_EAST = -73.7;
	public static final double LON_WEST = -74.05;
	public static final double LAT_NORTH = 41.0;
	public static final double LAT_SOUTH = 40.5;

	// area width and height
	public static final double LON_WIDTH = 74.05 - 73.7;
	public static final double LAT_HEIGHT = 41.0 - 40.5;

	// delta step to create artificial grid overlay of NYC
	public static final double DELTA_LON = 0.0014;
	public static final double DELTA_LAT = 0.00125;

	// ( |LON_WEST| - |LON_EAST| ) / DELTA_LAT
	public static final int NUMBER_OF_GRID_X = 250;
	// ( LAT_NORTH - LAT_SOUTH ) / DELTA_LON
	public static final int NUMBER_OF_GRID_Y = 400;

	public static final float DEG_LEN = 110.25f;

	/**
	 * Checks if a location specified by longitude and latitude values is
	 * within the geo boundaries of New York City.
	 *
	 * @param lon longitude of the location to check
	 * @param lat latitude of the location to check
	 *
	 * @return true if the location is within NYC boundaries, otherwise false.
	 */
	public static boolean isInNYC(float lon, float lat) {

		return !(lon > LON_EAST || lon < LON_WEST) &&
				!(lat > LAT_NORTH || lat < LAT_SOUTH);
	}

	/**
	 * Maps a location specified by latitude and longitude values to a cell of a
	 * grid covering the area of NYC.
	 * The grid cells are roughly 100 x 100 m and sequentially number from north-west
	 * to south-east starting by zero.
	 *
	 * @param lon longitude of the location to map
	 * @param lat latitude of the location to map
	 *
	 * @return id of mapped grid cell.
	 */
	public static int mapToGridCell(float lon, float lat) {
		int xIndex = (int) Math.floor((Math.abs(LON_WEST) - Math.abs(lon)) / DELTA_LON);
		int yIndex = (int) Math.floor((LAT_NORTH - lat) / DELTA_LAT);

		return xIndex + (yIndex * NUMBER_OF_GRID_X);
	}

	/**
	 * Maps the direct path between two locations specified by longitude and latitude to a list of
	 * cells of a grid covering the area of NYC.
	 * The grid cells are roughly 100 x 100 m and sequentially number from north-west
	 * to south-east starting by zero.
	 *
	 * @param lon1 longitude of the first location
	 * @param lat1 latitude of the first location
	 * @param lon2 longitude of the second location
	 * @param lat2 latitude of the second location
	 *
	 * @return A list of cell ids
	 */
	public static List<Integer> mapToGridCellsOnWay(float lon1, float lat1, float lon2, float lat2) {

		int x1 = (int) Math.floor((Math.abs(LON_WEST) - Math.abs(lon1)) / DELTA_LON);
		int y1 = (int) Math.floor((LAT_NORTH - lat1) / DELTA_LAT);

		int x2 = (int) Math.floor((Math.abs(LON_WEST) - Math.abs(lon2)) / DELTA_LON);
		int y2 = (int) Math.floor((LAT_NORTH - lat2) / DELTA_LAT);

		int startX, startY, endX, endY;
		if (x1 <= x2) {
			startX = x1;
			startY = y1;
			endX = x2;
			endY = y2;
		}
		else {
			startX = x2;
			startY = y2;
			endX = x1;
			endY = y1;
		}

		double slope = (endY - startY) / ((endX - startX) + 0.00000001);

		int curX = startX;
		int curY = startY;

		ArrayList<Integer> cellIds = new ArrayList<>(64);
		cellIds.add(curX + (curY * NUMBER_OF_GRID_X));

		while (curX < endX || curY != endY) {

			if (slope > 0) {
				double y = (curX - startX + 0.5) * slope + startY - 0.5;

				if (y > curY - 0.05 && y < curY + 0.05) {
					curX++;
					curY++;
				}
				else if (y < curY) {
					curX++;
				}
				else {
					curY++;
				}
			}
			else {
				double y = (curX - startX + 0.5) * slope + startY + 0.5;

				if (y > curY - 0.05 && y < curY + 0.05) {
					curX++;
					curY--;
				}
				if (y > curY) {
					curX++;
				}
				else {
					curY--;
				}

			}

			cellIds.add(curX + (curY * NUMBER_OF_GRID_X));
		}

		return cellIds;
	}

	/**
	 * Returns the longitude of the center of a grid cell.
	 *
	 * @param gridCellId The grid cell.
	 *
	 * @return The longitude value of the cell's center.
	 */
	public static float getGridCellCenterLon(int gridCellId) {

		int xIndex = gridCellId % NUMBER_OF_GRID_X;

		return (float) (Math.abs(LON_WEST) - (xIndex * DELTA_LON) - (DELTA_LON / 2)) * -1.0f;
	}

	/**
	 * Returns the latitude of the center of a grid cell.
	 *
	 * @param gridCellId The grid cell.
	 *
	 * @return The latitude value of the cell's center.
	 */
	public static float getGridCellCenterLat(int gridCellId) {

		int xIndex = gridCellId % NUMBER_OF_GRID_X;
		int yIndex = (gridCellId - xIndex) / NUMBER_OF_GRID_X;

		return (float) (LAT_NORTH - (yIndex * DELTA_LAT) - (DELTA_LAT / 2));

	}

	/**
	 * Returns a random longitude within the NYC area.
	 *
	 * @param rand A random number generator.
	 * @return A random longitude value within the NYC area.
	 */
	public static float getRandomNYCLon(Random rand) {
		return (float) (LON_EAST - (LON_WIDTH * rand.nextFloat()));
	}

	/**
	 * Returns a random latitude within the NYC area.
	 *
	 * @param rand A random number generator.
	 * @return A random latitude value within the NYC area.
	 */
	public static float getRandomNYCLat(Random rand) {
		return (float) (LAT_SOUTH + (LAT_HEIGHT * rand.nextFloat()));
	}

	/**
	 * Returns the Euclidean distance between two locations specified as lon/lat pairs.
	 *
	 * @param lon1 Longitude of first location
	 * @param lat1 Latitude of first location
	 * @param lon2 Longitude of second location
	 * @param lat2 Latitude of second location
	 * @return The Euclidean distance between the specified locations.
	 */
	public static double getEuclideanDistance(float lon1, float lat1, float lon2, float lat2) {
		double x = lat1 - lat2;
		double y = (lon1 - lon2) * Math.cos(lat2);
		return (DEG_LEN * Math.sqrt(x * x + y * y));
	}

	/**
	 * Returns the angle in degrees between the vector from the start to the destination
	 * and the x-axis on which the start is located.
	 *
	 * <p>The angle describes in which direction the destination is located from the start, i.e.,
	 * 0° -> East, 90° -> South, 180° -> West, 270° -> North
	 *
	 * @param startLon longitude of start location
	 * @param startLat latitude of start location
	 * @param destLon longitude of destination
	 * @param destLat latitude of destination
	 * @return The direction from start to destination location
	 */
	public static int getDirectionAngle(
			float startLon, float startLat, float destLon, float destLat) {

		double x = destLat - startLat;
		double y = (destLon - startLon) * Math.cos(startLat);

		return (int) Math.toDegrees(Math.atan2(x, y)) + 179;
	}

}
