import  moderngl, math, time
import  numpy as np
from    PIL import Image, ImageOps
from    io  import BytesIO

vertex_shader_source = """
    #version 330
    in vec3 local_vertex;
    void main(){
        gl_Position = vec4( local_vertex, 1.0 );
    }
"""

fragment_shader_source = """
    #version 330
    out vec4 out_color;
    void main() {
        out_color = vec4(.2, 0.2, .8, 1.0);
    }
"""

class ogl:
    def __init__(self):
        self.imageQ = 'high'
        self.imageQ = 'medium'
        #self.imageQ = 'low'
        self.w_width, self.w_height = 800, 600
        self.ctx = moderngl.create_standalone_context()
        self.prog = self.ctx.program(vertex_shader= vertex_shader_source,
                                    fragment_shader= fragment_shader_source)
        self.dt = 0
        self.vertices = np.array(   [[ -.5,  -.5*math.sin(self.dt), 0.0],
                                    [ 0.5,  -.5*math.sin(self.dt), 0.0],
                                    [ 0.5,  0.5*math.sin(self.dt), 0.0],
                                    [ -.5,  -.5*math.sin(self.dt), 0.0],
                                    [ 0.5,  0.5*math.sin(self.dt), 0.0],
                                    [-.5,  0.5*math.sin(self.dt), 0.0]], dtype='f4')

        self.vbo = self.ctx.buffer(self.vertices.tobytes())
        self.vao = self.ctx.simple_vertex_array(self.prog, self.vbo, "local_vertex")
        self.color_renderbuffer = self.ctx.renderbuffer((self.w_width, self.w_height))
        self.fbo = self.ctx.framebuffer(color_attachments= (self.color_renderbuffer))

        print('OGL initiated')

    def display(self):
        self.fbo.use()
        self.ctx.clear(.1, .1, .1, 1.0)

        self.dt += .1
        self.vertices = np.array(   [[ -.5,  -.5*math.sin(self.dt), 0.0],
                                    [ 0.5,  -.5*math.sin(self.dt), 0.0],
                                    [ 0.5,  0.5*math.sin(self.dt), 0.0],
                                    [ -.5,  -.5*math.sin(self.dt), 0.0],
                                    [ 0.5,  0.5*math.sin(self.dt), 0.0],
                                    [-.5,  0.5*math.sin(self.dt), 0.0]], dtype='f4')

        self.vbo = self.ctx.buffer(self.vertices.tobytes())
        self.vao = self.ctx.simple_vertex_array(self.prog, self.vbo, "local_vertex")
        self.vao.render(mode=moderngl.TRIANGLES)
        self.ctx.finish()

    def get_frame(self):
        self.display()
        fb = self.fbo.read(components=3, alignment=1, dtype='f4')
        data_array = np.frombuffer(fb, dtype=np.float32).reshape(600,800,3)
        image_to_send = ImageOps.flip(Image.fromarray(np.uint8(data_array*255)))

        buf = BytesIO()
        if self.imageQ == 'low':
            image_to_send.save(buf, format= 'JPEG', quality= 40)
        elif self.imageQ == 'medium':
            image_to_send.save(buf, format= 'JPEG', quality= 70)
        else:
            image_to_send.save(buf, format= 'JPEG', quality= 100)
        return buf.getvalue()
