/*
 * Author:          Patrick-Christopher Mattulat
 * Company:         Lynar Studios
 * E-Mail:          webmaster@lynarstudios.com
 * Created:         2022-08-05
 * Changed:         2023-06-02
 *
 * */

#ifndef LS_MATH_VECTOR2_HPP
#define LS_MATH_VECTOR2_HPP

#include <cstdlib>
#include <ls-math/core/types/VectorTypes.hpp>
#include <ls-math/os/dynamic-goal.hpp>

namespace ls::math::vector
{
  class LS_MATH_DYNAMIC_GOAL Vector2
  {
    public:

      Vector2(const ls::math::core::type::vector2_component &_x, const ls::math::core::type::vector2_component &_y);
      ~Vector2() = default;

      // arithmetic operations

      ls::math::vector::Vector2 operator+(const ls::math::vector::Vector2 &_vector) const;
      ls::math::vector::Vector2 operator-(const ls::math::vector::Vector2 &_vector) const;
      ls::math::core::type::vector_scalar operator*(const ls::math::vector::Vector2 &_vector) const;
      ls::math::vector::Vector2 operator*(double _value);
      ls::math::vector::Vector2 operator/(double _divisor);

      // comparison operations

      bool operator==(const Vector2 &_vector);
      bool operator!=(const Vector2 &_vector);

      // additional functionality

      [[nodiscard]] static ls::math::vector::Vector2 add(const ls::math::vector::Vector2 &_leftAddend, const ls::math::vector::Vector2 &_rightAddend);
      [[nodiscard]] static ls::math::core::type::vector_scalar dot(const ls::math::vector::Vector2 &_leftAddend, const ls::math::vector::Vector2 &_rightAddend);
      [[nodiscard]] ls::math::core::type::vector2_components getComponents() const;
      [[nodiscard]] double getLength();
      [[nodiscard]] ls::math::core::type::vector2_component getX();
      [[nodiscard]] ls::math::core::type::vector2_component getY();
      [[nodiscard]] ls::math::vector::Vector2 normalize();
      void setX(const ls::math::core::type::vector2_component &_value);
      void setY(const ls::math::core::type::vector2_component &_value);
      [[nodiscard]] static ls::math::vector::Vector2 subtract(const ls::math::vector::Vector2 &_leftAddend, const ls::math::vector::Vector2 &_rightAddend);

    private:

      ls::math::core::type::vector2_components components{};

      [[nodiscard]] static ls::math::vector::Vector2 _add(const ls::math::vector::Vector2 &_leftAddend, const ls::math::vector::Vector2 &_rightAddend);
      [[nodiscard]] static ls::math::core::type::vector_scalar _dot(const ls::math::vector::Vector2 &_leftAddend, const ls::math::vector::Vector2 &_rightAddend);
      [[nodiscard]] static double _getLength(const ls::math::core::type::vector2_component &_x, const ls::math::core::type::vector2_component &_y);
      [[nodiscard]] static ls::math::vector::Vector2 _operatorDivision(const ls::math::core::type::vector2_component &_x, const ls::math::core::type::vector2_component &_y, double _divisor);
      [[nodiscard]] static ls::math::vector::Vector2 _subtract(const ls::math::vector::Vector2 &_leftAddend, const ls::math::vector::Vector2 &_rightAddend);
  };
}

#endif
