#pragma once
#include <cassert>
#include <type_traits>
#include "AftrConfig.h"
namespace Aftr
{

class GLView;

class ManagerGLView
{
public:
   static void init( GLView* currentGLView );

   /// Returns a pointer to the current GLView as a base class pointer:
   /// GLView* glv = ManagerGLView::GetGLViewT();
   /// If you need to access subclassed methods within a specific GLView and you know the exact type of GLView
   /// in a module (which is almost always the case), you may call the templated versions shown below in ManagerGLView.h.
   static GLView* getGLView()
   {
      if( ManagerGLView::glView == nullptr )
      {
         ManagerGLView::print_and_abort( AFTR_FILE_LINE_STR );
      }
      return ManagerGLView::glView;
   }

   static const GLView* getGLViewConst() 
   {
      if( ManagerGLView::glView == nullptr )
      {
         ManagerGLView::print_and_abort( AFTR_FILE_LINE_STR );
      }
      return ManagerGLView::glView;
   }
   
   /// This method is similar to getGLView() but it explicitly casts the return type to the GLView subclass passed inside
   /// of the template parameter.
   /// Expected usage is: GLViewMySubType* glv = ManagerGLView::GetGLViewT<GLViewMySubType>();
   template< typename T, typename R = std::remove_pointer_t<T> >
   static R* getGLViewT() noexcept
   {
      static_assert( std::is_base_of_v< GLView, R >, "NYKL: T does not inherit from Aftr::GLView. Improper usage of getGLViewT().\n");
      if( ManagerGLView::glView == nullptr )
      {
         ManagerGLView::print_and_abort( AFTR_FILE_LINE_STR );
      }
      return static_cast<R*>( ManagerGLView::glView );
   }

   /// This method is similar to getGLView() but it explicitly casts the return type to the GLView subclass passed inside
   /// of the template parameter.
   /// CONST Version of method above
   /// Expected usage is: const GLViewMySubType* glv = ManagerGLView::GetGLViewT<GLViewMySubType>(); //(WEST CONST)
   ///      or
   /// GLViewMySubType* const glv = ManagerGLView::GetGLViewT<GLViewMySubType>(); //(EAST CONST)
   template< typename T, typename R = std::remove_pointer<T> >
   static const R* getGLViewTConst() noexcept
   {
      static_assert(std::is_base_of_v< GLView, R >, "NYKL: T does not inherit from Aftr::GLView. Improper usage of getGLViewT().\n");
      if( ManagerGLView::glView == nullptr )
      {
         ManagerGLView::print_and_abort( AFTR_FILE_LINE_STR );
      }
      return static_cast<R*>(ManagerGLView::glView);
   }

private:
   //Silly private function to avoid #include <iostream> in a manager included by "everyone" (reduce compile time)
   static void print_and_abort( char const* s );
   static GLView* glView;
};

} //namespace Aftr

