import numpy as np
from OpenGL.GL import *
import ctypes
import time

class WaterMesh:
    def __init__(self, size=10.0, resolution=100):
        self.size = size
        self.resolution = resolution
        self.vertices = self.generate_vertices()
        self.vertex_count = len(self.vertices) // 8

        self.vao = glGenVertexArrays(1)
        self.vbo = glGenBuffers(1)

        glBindVertexArray(self.vao)
        glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
        glBufferData(GL_ARRAY_BUFFER, self.vertices.nbytes, self.vertices, GL_DYNAMIC_DRAW)

        stride = 8 * 4
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, ctypes.c_void_p(0))   # pos
        glEnableVertexAttribArray(0)
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride, ctypes.c_void_p(12))  # color
        glEnableVertexAttribArray(1)
        glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, stride, ctypes.c_void_p(24))  # uv
        glEnableVertexAttribArray(2)

        glBindBuffer(GL_ARRAY_BUFFER, 0)
        glBindVertexArray(0)

        self.start_time = time.time()

    def generate_vertices(self):
        step = self.size / self.resolution
        verts = []

        for z in range(self.resolution):
            for x in range(self.resolution):
                # cztery rogi jednego kwadratu
                x0 = x * step - self.size / 2
                x1 = (x + 1) * step - self.size / 2
                z0 = z * step - self.size / 2
                z1 = (z + 1) * step - self.size / 2

                uv0 = (x / self.resolution, z / self.resolution)
                uv1 = ((x + 1) / self.resolution, z / self.resolution)
                uv2 = ((x + 1) / self.resolution, (z + 1) / self.resolution)
                uv3 = (x / self.resolution, (z + 1) / self.resolution)

                color = (0.2, 0.4, 1.0)

                # dwa trójkąty
                verts += [x0, 0, z0, *color, *uv0]
                verts += [x1, 0, z0, *color, *uv1]
                verts += [x1, 0, z1, *color, *uv2]

                verts += [x0, 0, z0, *color, *uv0]
                verts += [x1, 0, z1, *color, *uv2]
                verts += [x0, 0, z1, *color, *uv3]

        return np.array(verts, dtype=np.float32)

    def update(self):
        time_now = time.time() - self.start_time
        verts = self.vertices

        for i in range(0, len(verts), 8):
            x = verts[i]
            z = verts[i + 2]
            verts[i + 1] = np.sin(x * 0.5 + time_now) * 0.2 + np.cos(z * 0.5 + time_now) * 0.2

        glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
        glBufferSubData(GL_ARRAY_BUFFER, 0, verts.nbytes, verts)
        glBindBuffer(GL_ARRAY_BUFFER, 0)

    def draw(self, shader):
        shader.use()
        glBindVertexArray(self.vao)
        glDrawArrays(GL_TRIANGLES, 0, self.vertex_count)
        glBindVertexArray(0)

    def destroy(self):
        glDeleteVertexArrays(1, [self.vao])
        glDeleteBuffers(1, [self.vbo])