/*
 * This file is part of OpenTTD.
 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
 */

/** @file pathfinder_func.h General functions related to pathfinders. */

#ifndef PATHFINDER_FUNC_H
#define PATHFINDER_FUNC_H

#include "../tile_cmd.h"
#include "../waypoint_base.h"

/**
 * Calculates the tile of given station that is closest to a given tile
 * for this we assume the station is a rectangle,
 * as defined by its tile are (st->train_station)
 * @param station The station to calculate the distance to
 * @param tile The tile from where to calculate the distance
 * @param station_type the station type to get the closest tile of
 * @return The closest station tile to the given tile.
 */
inline TileIndex CalcClosestStationTile(StationID station, TileIndex tile, StationType station_type)
{
	const BaseStation *st = BaseStation::Get(station);
	TileArea ta = st->GetTileArea(station_type);

	/* If the rail station is (temporarily) not present, use the station sign to drive near the station */
	if (ta.tile == INVALID_TILE) return st->xy;

	uint minx = TileX(ta.tile);  // topmost corner of station
	uint miny = TileY(ta.tile);
	uint maxx = minx + ta.w - 1; // lowermost corner of station
	uint maxy = miny + ta.h - 1;

	/* we are going the aim for the x coordinate of the closest corner
	 * but if we are between those coordinates, we will aim for our own x coordinate */
	uint x = ClampU(TileX(tile), minx, maxx);

	/* same for y coordinate, see above comment */
	uint y = ClampU(TileY(tile), miny, maxy);

	/* return the tile of our target coordinates */
	return TileXY(x, y);
}

/**
 * Wrapper around GetTileTrackStatus(), as for single tram bits
 * GetTileTrackStatus() returns 0. The reason for this is
 * that there are no half-tile TrackBits in OpenTTD.
 * This tile, however, is a valid tile for trams, one on which they can
 * reverse safely. To "fix" this, pretend that if we are on a half-tile, we
 * are in fact on a straight tram track tile. CFollowTrackT will make sure
 * the pathfinders cannot exit on the wrong side and allows reversing on such
 * tiles.
 * @param tile The tile to check.
 * @param rtt Whether to check the road or tram type.
 * @return The trackdir bits on the tile.
 */
inline TrackdirBits GetTrackdirBitsForRoad(TileIndex tile, RoadTramType rtt)
{
	TrackdirBits bits = GetTileTrackStatus(tile, TransportType::Road, rtt).trackdirs;

	if (rtt == RoadTramType::Tram && bits.None()) {
		if (IsNormalRoadTile(tile)) {
			RoadBits rb = GetRoadBits(tile, RoadTramType::Tram);
			switch (rb.base()) {
				case RoadBits{RoadBit::NE}.base():
				case RoadBits{RoadBit::SW}.base():
					bits = {Trackdir::X_NE, Trackdir::X_SW};
					break;

				case RoadBits{RoadBit::NW}.base():
				case RoadBits{RoadBit::SE}.base():
					bits = {Trackdir::Y_NW, Trackdir::Y_SE};
					break;

				default: break;
			}
		}
	}

	return bits;
}

#endif /* PATHFINDER_FUNC_H */
