from OpenGL import GL
import OpenGL.GL.ARB.bindless_texture as bt

from .FBOAttachment import FBOAttachment
from .GLInfo import GLInfo
from .utils import checktype
from .helper import get_dtype

class sampler2DMS(FBOAttachment):

	_basic_info = \
	{
		"gen_func": GL.glGenTextures,
		"bind_func": GL.glBindTexture,
		"del_func": GL.glDeleteTextures,
		"target_type": GL.GL_TEXTURE_2D_MULTISAMPLE,
		"binding_type": GL.GL_TEXTURE_BINDING_2D_MULTISAMPLE,
		"need_number": True,
	}

	def __init__(self, width:int=0, height:int=0, samples:int=4, internal_format:GLInfo.internal_formats=GL.GL_RGBA32F):
		FBOAttachment.__init__(self)
		
		self._handle = 0
		self._samples = samples
		self._width = width
		self._height = height
		self._internal_format = internal_format
		self._param_changed = True

	def __del__(self):
		if self._handle != 0:
			self._handle = 0

		FBOAttachment.__del__(self)

	def __deepcopy__(self, memo):
		result = sampler2DMS()
		result._samples = self._samples
		result._width = self._width
		result._height = self._height
		result._internal_format = self._internal_format

		return result

	def bind(self, update_fbo:bool=False, force_update_image:bool=False):
		FBOAttachment.bind(self, update_fbo, force_update_image)
		if force_update_image or self._param_changed:
			GL.glTexImage2DMultisample(GL.GL_TEXTURE_2D_MULTISAMPLE, self._samples, self._internal_format, self._width, self._height, GL.GL_TRUE)
			self._param_changed = False

	@property
	def handle(self):
		if not bt.glGetTextureHandleARB:
			return 0

		if self._id == 0:
			return 0
		
		if self._handle == 0:
			self._handle = bt.glGetTextureHandleARB(self._id)
			if self._handle == 0:
				raise RuntimeError(f"failed to create sampler2D {self._id}'s handle")
			self._dynamic = False
			bt.glMakeTextureHandleResidentARB(self._handle)
			
		return self._handle

	@property
	def samples(self):
		return self._samples

	@samples.setter
	@FBOAttachment.param_setter
	def samples(self, samples:int):
		self._samples = samples
		self._param_changed = True

	@property
	def width(self):
		return self._width

	@width.setter
	@FBOAttachment.param_setter
	def width(self, width:int):
		self._width = width
		self._param_changed = True

	@property
	def height(self):
		return self._height

	@height.setter
	@FBOAttachment.param_setter
	def height(self, height:int):
		self._height = height
		self._param_changed = True

	@property
	def dtype(self):
		return get_dtype(self._internal_format)

	@property
	def internal_format(self):
		return self._internal_format

	@internal_format.setter
	@FBOAttachment.param_setter
	def internal_format(self, format:GLInfo.internal_formats):
		self._internal_format = format
		self._param_changed = True

	def update(self):
		self._param_changed = True

	@checktype
	def malloc(self, width:int, height:int, samples:int=4, layers:int=None, internal_format:GLInfo.internal_formats=None):
		self.width = width
		self.height = height
		self.samples = samples

		if internal_format is None:
			internal_format = self.internal_format

		if internal_format is None:
			internal_format = GL.GL_RGBA32F

		self.internal_format = internal_format

	@property
	def is_completed(self):
		return (self._width > 0 and self._height > 0)
