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

#pragma once

#include "glmSDKAPI.h"

#include "glmGeometry3.h"
#include "glmArray.h"
#include "glmVector3.h"

namespace glm
{
    class AbstractGround;

    class GLM_SDK_API Track
    {
    public:
        struct InputMode
        {
            enum Value
            {
                MIDDLE_CURVE = 0,
                SIDE_CURVES,
                END
            };
        };

        InputMode::Value _inputMode = InputMode::SIDE_CURVES;
        glm::Array<Vector3> _sideCurves[2]; // computed from _middleCurve if _inputMode == InputMode::MIDDLE_CURVE
        glm::Array<Vector3> _middleCurve;   // computed from _sideCurves if _inputMode == InputMode::SIDE_CURVES

        float _width = 2.f;
        float _edgeWidth[2] = {0.2f, 0.2f};
        float _edgeAngleDelta[2] = {0.5236f, 0.5236f}; // ~30 degrees in radians

        size_t _lengthSampleCount = 20;

        AbstractGround::SP _ground = NULL;

        Geometry3 _geometry;                              // computed
        glm::Array<Vector3> _geoVertexDirections;         // computed
        glm::Array<Vector3> _geoVertexDirectionsReversed; // computed
        glm::Array<Vector3> _edgeInnerCurves[2];          // computed
        PODArray<size_t> _firstVertexOnCurveIndexes;      // computed

    public:
        Track();

        void clearCurves();
        void clearSideCurves();
        void clearMiddleCurve();
        void clearEdgeInnerCurves();

        void initGeometry();

        void computeDirection(Vector3& direction, Vector3& normal, float& intersectionDistance, bool& inside, const Vector3& position, const Vector3& upVector, bool reverse = false);

        void computeVertexDirections();

        Track& operator=(const Track& track);

    protected:
        void interpolateDirection(Vector3& direction, const Geometry3::PathTriangle& triangle, float u, float v, bool reverse);
        void interpolateDirection(Vector3& direction, size_t vertexIndex0, size_t vertexIndex1, float u, bool reverse);
    };
} // namespace glm
