import gpu
from bgl import *
from .gl_utils import gl_utils


def buffer_to_str(buf, len):
    str = ""
    for i in buf[:len]:
        str += chr(i)
    return str


def delete_buffer(id):
    if id != 0:
        int_buf = Buffer(GL_INT, 1, (id,))
        glDeleteBuffers(1, int_buf)


class GLVertBuf():
    def __init__(self, len, format) -> None:
        self._len = len
        self._fmt = format
        self._vbo = 0
        self._vbuf = gpu.types.GPUVertBuf(len=len, format=format)

    def len(self):
        return self._len

    def attr_fill(self, id, data):
        self._vbuf.attr_fill(id, data)

    def get_vert_buffer(self):
        return self._vbuf

    def use_data(self):
        gl_utils.bind_vert_buffer(self._vbuf, self.get_vbo_id())

    def get_vbo_id(self):
        if self._vbo == 0:
            int_buf = Buffer(GL_INT, 1)
            glGenBuffers(1, int_buf)
            self._vbo = int_buf[0]
        return self._vbo

    def __del__(self):
        delete_buffer(self._vbo)


class GLIndexBuf():
    def __init__(self, len) -> None:
        self._len = len
        self._ibuf = gpu.types.Buffer('UINT', len)
        self._ibo = 0
        self._binded = False

    def len(self):
        return self._len

    def set_len(self, new_len):
        assert new_len <= self._len
        self._len = new_len

    def get_index_buffer(self):
        return self._ibuf

    def set_binded(self):
        self._binded = True

    def get_binded(self):
        return self._binded

    def get_ibo_id(self):
        if self._ibo == 0:
            int_buf = Buffer(GL_INT, 1)
            glGenBuffers(1, int_buf)
            self._ibo = int_buf[0]
        return self._ibo

    def __del__(self):
        delete_buffer(self._ibo)


class GLTextureBuf():
    def __init__(self, vbuf: GLVertBuf) -> None:
        self._len = vbuf.len()
        int_buf = Buffer(GL_INT, 1)
        glGenTextures(1, int_buf)
        self._tex_id = int_buf[0]
        self._target = GL_TEXTURE_BUFFER

        gl_utils.bind_texbuf_to_vertbuf(
            self._tex_id, vbuf.get_vbo_id(), vbuf.get_vert_buffer())

    def get_tex_id(self):
        return self._tex_id

    def rebind_vertbuf(self, vbuf):
        self._len = vbuf.len()
        gl_utils.bind_texbuf_to_vertbuf(
            self._tex_id, vbuf.get_vbo_id(), vbuf.get_vert_buffer())

    def bind(self, unit):
        glActiveTexture(GL_TEXTURE0 + unit)
        glBindTexture(self._target, self._tex_id)

    def __del__(self):
        if self._tex_id != 0:
            int_buf = Buffer(GL_INT, 1, (self._tex_id,))
            glDeleteTextures(1, int_buf)
