/* +------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)            |
   |                          https://www.mrpt.org/                         |
   |                                                                        |
   | Copyright (c) 2005-2024, Individual contributors, see AUTHORS file     |
   | See: https://www.mrpt.org/Authors - All rights reserved.               |
   | Released under BSD License. See: https://www.mrpt.org/License          |
   +------------------------------------------------------------------------+ */
#pragma once

#include <mrpt/opengl/CRenderizableShaderWireFrame.h>

#include <array>

namespace mrpt::opengl
{
/** Draw a 3D world axis, with coordinate marks at some regular interval
 *  \sa opengl::Scene
 *
 *  ![mrpt::opengl::CAxis](preview_CAxis.png)
 *
 * \ingroup mrpt_opengl_grp
 */
class CAxis : public CRenderizableShaderWireFrame
{
  DEFINE_SERIALIZABLE(CAxis, mrpt::opengl)
 public:
  /** @name Renderizable shader API virtual methods
   * @{ */
  void onUpdateBuffers_Wireframe() override;
  void render(const RenderContext& rc) const override;
  void enqueueForRenderRecursive(
      const mrpt::opengl::TRenderMatrices& state,
      RenderQueue& rq,
      bool wholeInView,
      bool is1stShadowMapPass) const override;
  bool isCompositeObject() const override { return true; }
  /** @} */

  /** Constructor */
  CAxis(
      float xmin = -1.0f,
      float ymin = -1.0f,
      float zmin = -1.0f,
      float xmax = 1.0f,
      float ymax = 1.0f,
      float zmax = 1.0f,
      float frecuency = 1.f,
      float lineWidth = 3.0f,
      bool marks = true);

  virtual ~CAxis() override = default;

  void setAxisLimits(float xmin, float ymin, float zmin, float xmax, float ymax, float zmax);
  /** Changes the frequency of the "ticks" */
  void setFrequency(float f);
  float getFrequency() const;
  /** Changes the size of text labels (default:0.25) */
  void setTextScale(float f);
  float getTextScale() const;
  /** axis: {0,1,2}=>{X,Y,Z} */
  void setTextLabelOrientation(int axis, float yaw_deg, float pitch_deg, float roll_deg);
  /** axis: {0,1,2}=>{X,Y,Z} */
  void getTextLabelOrientation(int axis, float& yaw_deg, float& pitch_deg, float& roll_deg) const;

  void enableTickMarks(bool v = true);
  void enableTickMarks(bool show_x, bool show_y, bool show_z);
  /** As a ratio of "marks frequency" (default: 0.05) */
  void setTickMarksLength(float len);
  float getTickMarksLength(float len) { return m_markLen; }

  mrpt::math::TBoundingBoxf internalBoundingBoxLocal() const override;

 protected:
  float m_xmin, m_ymin, m_zmin;
  float m_xmax, m_ymax, m_zmax;
  float m_frequency;
  /** draw marks for X,Y,Z */
  std::array<bool, 3> m_marks = {false, false, false};
  float m_textScale{0.10f};
  float m_textRot[3][3];  // {x,y,z},{yaw,pitch,roll}
  float m_markLen{0.07f};

  mrpt::containers::PerThreadDataHolder<mrpt::opengl::CListOpenGLObjects> m_gl_labels;
};

}  // namespace mrpt::opengl
