from ..Mesh import Mesh

from glass import Vertex
from glass.utils import checktype

import glm
import math
from OpenGL import GL


class Circle(Mesh):

    def __init__(
        self,
        radius: float = 1,
        vertical: bool = False,
        n_points: int = 100,
        start_angle: float = 0,
        span_angle: float = 360,
        color: (glm.vec3, glm.vec4) = glm.vec4(0.396, 0.74151, 0.69102, 1),
        line_width: int = 2,
        name: str = "",
    ):
        Mesh.__init__(self, primitive_type=GL.GL_LINE_STRIP, color=color, name=name)
        self.render_hints.line_width = line_width
        self.__radius: float = radius
        self.__vertical: bool = vertical
        self.__n_points: int = n_points
        self.__start_angle: float = start_angle
        self.__span_angle: float = span_angle
        self.start_building()

    def build(self):
        vertices = self.vertices
        radius: float = self.__radius
        vertical: bool = self.__vertical
        n_points: int = self.__n_points
        start_angle: float = self.__start_angle
        span_angle: float = self.__span_angle

        for i in range(n_points):
            theta = (start_angle + i / (n_points - 1) * span_angle) / 180 * math.pi

            position = radius * glm.vec3(math.cos(theta), math.sin(theta), 0)
            bitangent = glm.vec3(-math.sin(theta), math.cos(theta), 0)
            if vertical:
                position = radius * glm.vec3(math.cos(theta), 0, math.sin(theta))
                bitangent = glm.vec3(-math.sin(theta), 0, math.cos(theta))

            vertices[i] = Vertex(
                position=position,
                bitangent=bitangent,
                tex_coord=glm.vec3(radius * theta, 0, 0),
            )

        del vertices[n_points:]

    @property
    def line_width(self) -> int:
        return self.render_hints.line_width

    @line_width.setter
    @checktype
    def line_width(self, line_width: int) -> None:
        self.render_hints.line_width = line_width

    @property
    def radius(self) -> float:
        return self.__radius

    @radius.setter
    @Mesh.param_setter
    def radius(self, radius: float) -> None:
        self.__radius = radius

    @property
    def vertical(self) -> bool:
        return self.__vertical

    @vertical.setter
    @Mesh.param_setter
    def vertical(self, flag: bool) -> None:
        self.__vertical = flag

    @property
    def n_points(self) -> int:
        return self.__n_points

    @n_points.setter
    @Mesh.param_setter
    def n_points(self, n_points: int) -> None:
        self.__n_points = n_points

    @property
    def start_angle(self) -> float:
        return self.__start_angle

    @start_angle.setter
    @Mesh.param_setter
    def start_angle(self, angle: float) -> None:
        self.__start_angle = angle

    @property
    def span_angle(self) -> float:
        return self.__span_angle

    @span_angle.setter
    @Mesh.param_setter
    def span_angle(self, angle: float) -> None:
        self.__span_angle = angle
