#pragma once
#include <string>
#include <optional>
#include "Mat4Fwd.h"
#include "Vector.h"


//This is a implementation file used by the templated Vector class. The primary purpose of this 
//class is to form a compilation firewall for the Ve
namespace Aftr
{
   namespace Mat4Impl
   {
      //Wraps the call to AftrUtilites, so Vector.h does NOT have to actually include AftrUtilities.h (huge header)
      std::string trim_whitespace( const std::string& s );

      template< typename T >
      T str_to_numeric_val( const std::string& val );

      template< typename T >
      Mat4T<T> orthogonalize_3x3( Mat4T<T> const& m ) noexcept;

      //This implements the body of the constructor to avoid having to include
      //regex in Mat4.h
      template< typename T >
      Mat4T<T> make_Mat4T( std::string const& str, bool inputStringIsColumnMajor ) noexcept;

      template< typename T >
      std::optional< Mat4T<T> > make_Mat4T_opt( std::string const& str, bool inputStringIsColumnMajor ) noexcept;

      template< typename T >
      std::string toString( Mat4T<T> const& m, size_t length );

      template< typename T >
      std::string toStringWithVecMagnitudes( Mat4T<T> const& m, size_t length );

      template< typename T >
      VectorD getRPY_deg_clockwise( Mat4T<T> const& m ) noexcept;

      template< typename T >
      VectorD getRPY_deg_counter_clockwise( Mat4T<T> const& m ) noexcept;

      template< typename T >
      Aftr::Mat4T<T> fromRPY_deg_clockwise( const VectorT<T>& rpyDeg ) noexcept;

      template< typename T >
      VectorT<T> getAxisOfRotation_fromRotationMat( Mat4T<T> const& m ) noexcept;

      template< typename T >
      VectorT<T> toRodriguesVec_fromRotationMat( Mat4T<T> const& m ) noexcept;

      template< typename T >
      AxisAngleT<T> toAxisAngle_fromRotationMat( Mat4T<T> const& m ) noexcept;

      template< typename T >
      AxisAngleT<T> toAxisAngle_fromSkewSymmetricMat( Mat4T<T> const& m ) noexcept;

      template< typename T >
      bool isSkewSymmetric( Mat4T<T> const& m ) noexcept;

      //template< typename T >
      //Mat4T<T> scale( Mat4T<T> const& m,T const s ) noexcept;

   }

}
