/***************************************************************************
*                                                                          *
*  Copyright (C) Golaem S.A.  All Rights Reserved.                         *
*                                                                          *
***************************************************************************/

#pragma once

#include "glmSDKAPI.h"
#include "glmNavigationMeshLocation.h"
#include "glmTriangle3.h"

#include "glmQueue.h"

#include "glmNavigationMesh3.h"

namespace glm
{
    class Vector3;

    // returns all cells even partially inside radius from location
    // Used by PathComponentLocation, SensorFilter
    void GLM_SDK_API getAllCellsInsideRadius3D(
        const NavigationMesh3& navMesh,
        const NavigationMeshLocation& location, // for cellId hint as start of exploration
        const Vector3& center,
        float radius,
        glm::PODArray<IDDistancePairPOD>& result,
        float exploreRadiusFactor = 2.f);

    // returns all cells even partially inside area defined by a radius around a segment
    // Used by PathDebugRenderArray
    void GLM_SDK_API getAllCellsInsideSegmentAndRadius3D(
        const NavigationMesh3& navMesh,
        const NavigationMeshLocation& location, // for cellId hint as start of exploration
        const Segment3& center,
        float radius,
        glm::PODArray<IDDistancePairPOD>& result,
        float exploreRadiusFactor = 2.f);

    // unfolds all cells edges around "fromLocation" until reaching toLocation, or an edge obstacle. Edges with distance > radius from the segment are discarded
    // returns local 2D distance based on upVector
    // used by PlatterLiftPathFollower Minimize & AbstractPathFollower
    bool GLM_SDK_API canReachCellWithoutObstacleLocal2D(
        const NavigationMesh3& navigationMesh,
        const NavigationMeshLocation& fromLocation,
        const NavigationMeshLocation& toLocation,
        float radius,
        const Vector3& upVector,
        bool distanceIn3D);

    // unfolds all cells edges around "fromLocation" until reaching toLocation, or an edge obstacle. Edges with distance > radius from the triangle are discarded
    // returns local 2D distance based on upVector
    // used by PlatterLiftPathFollower Maximize
    bool GLM_SDK_API canReachCellWithoutObstacleInsideTriangle3Local2D(
        const NavigationMesh3& navigationMesh,
        const NavigationMeshLocation& fromLocation,
        const NavigationMeshLocation& toLocation,
        float triangleAperture,
        float radius,
        const Vector3& upVector,
        bool distanceIn3D,
        Triangle3& triangle);

    // Used with locale 2D distance by AbstractSpawningZone, targetRandomizer (for placement, insure maximum safety for start collision)
    // Used with 3D distance by MotionEntityComponent if checkCollision active, GotoBehavior, NavigationData::isCollisionDetected, Path components
    // returns true if local 2D Distance based on upVector, from location to an obstacle, is < radius
    // explores surrounding overlapping cells to find if any neighbour overlapping cell has obstacle with local 2D distance < 0
    // drawback : this will raise a true, for cells whose direct neighbors have 2D projected obstacle, which can be an issue with big cells
    bool GLM_SDK_API containsObstaclesLocal2D(
        const NavigationMesh3& navigationMesh, const NavigationMeshLocation& location,
        float radius, const Vector3& upVector, bool distance3D);

    // Used by PathGroupComponent
    // Used by NaivePathFollower
    // returns true if 3D Distance, from origin+(upVector projected ray) to an obstacle, is < radius
    // containsObstaclesRayLocal2D explores surrounding overlapping cells
    bool GLM_SDK_API containsObstaclesRayLocal2D(
        const NavigationMesh3& navigationMesh, const NavigationMeshLocation& origin,
        const Vector3& ray, float radius, const Vector3& upVector);

    // Used by PlatterLiftPathFollower
    // retrieve local 2D Distance based on upVector
    bool GLM_SDK_API retrieveClosestObstacleInLocal2D(
        const NavigationMesh3& navigationMesh,
        const NavigationMeshLocation& location, IDDistancePairPOD& result, const Vector3& upVector, bool distance3D);

    // retrieves closest obstacle as (edge Id, distance) pair in result, based on a location or location + ray
    // Used by RoadMapCreator & AbstractRoadMapQuery
    // retrieve pure 3D / 2D z=0 proj distances depending on useZProjection
    bool GLM_SDK_API retrieveClosestObstacle(
        const NavigationMesh3& navigationMesh,
        const NavigationMeshLocation& location, IDDistancePairPOD& result, bool useZProjection = false);
    bool GLM_SDK_API retrieveClosestObstacleRay3D(
        const NavigationMesh3& navigationMesh,
        const NavigationMeshLocation& location, const Vector3& ray, IDDistancePairPOD& result, bool useZProjection = false);
} // namespace glm
