from yta_editor_frame.frame.resource.abstract import FrameResourceABC
from yta_editor_frame.frame.resource.types import FrameResourceType
from yta_validation.parameter import ParameterValidator


class GPUTextureFrameResource(
    FrameResourceABC
):
    """
    A frame resource based on a texture.

    The `.frame` attribute is a `moderngl.Texture`.
    """
    
    @property
    def width(
        self
    ) -> int:
        return self.frame.width
    
    @property
    def height(
        self
    ) -> int:
        return self.frame.height
    
    @property
    def format(
        self
    ) -> str:
        return self.frame.dtype
    
    @property
    def type(
        self
    ) -> FrameResourceType:
        return FrameResourceType.GPU

    def __init__(
        self,
        frame: 'moderngl.Texture',
        render_context: 'RenderContext'
    ):
        ParameterValidator.validate_mandatory_instance_of('frame', frame, 'Texture')

        super().__init__(
            frame = frame,
            render_context = render_context
        )

    def release(
        self
    ):
        self.render_context.gpu.texture.release(self.frame)

    # TODO: Untested
    def copy(
        self,
        # TODO: Maybe 'render_context' instead (?)
        opengl_context: 'moderngl.Context'
    ) -> 'GPUTextureFrameResource':
        """
        Get a copy of this frame resource.
        """
        texture_data = self.frame.read()
        copy = opengl_context.texture(
            size = self.frame.size,
            components = self.frame.components,
            dtype = self.frame.dtype,
            data = texture_data
        )

        # TODO: This below is not working. If I find a way,
        # try it and replace the one above because I think
        # that this below could be using only GPU
        # copy = opengl_context.texture(
        #     size = self.frame.size,
        #     components = self.frame.components,
        #     dtype = self.frame.dtype,
        # )
        # src_fbo = opengl_context.framebuffer(color_attachments=[self.frame])
        # dst_fbo = opengl_context.framebuffer(color_attachments=[copy])
        # opengl_context.copy(
        #     src=src_fbo,
        #     dst=dst_fbo,
        #     src_viewport=(0, 0, self.frame.width, self.frame.height),
        #     dst_viewport=(0, 0, copy.width, copy.height),
        #     # Use GL_COLOR_BUFFER_BIT for color data
        #     # Use 'nearest' or 'linear' filter if viewports have different sizes
        #     # Default filter is 'nearest'
        # )

        return GPUTextureFrameResource(copy)
        