from __future__ import annotations
from ..function import *
from .types import *
import math

class Camera3D:
    position: Vec3D
    rotation: Vec3D
    fov: float
    draw_distance: float
    aspect: Vec2D
    def __init__(self, width: int, height: int, fov: float, distance: float = 100):
        self.position = Vec3D(0, 0, 0)
        self.rotation = Vec3D(0, 0, 0)

        self.fov = fov
        self.draw_distance = distance

        self.aspect = Vec2D(width, height)
    
    def look_at(self, target: Vec3D):
        dx = target.x - self.position.x
        dy = target.y - self.position.y
        dz = target.z - self.position.z

        yaw = math.atan2(dz, dx)

        dist = math.sqrt(dx * dx + dz * dz)

        pitch = -math.atan2(dy, dist)

        self.rotation.x = -math.degrees(pitch)
        self.rotation.y = math.degrees(yaw)
        self.rotation.z = 0

    def get_forward(self):
        pitch = math.radians(self.rotation.x)
        yaw = math.radians(self.rotation.y)
        return Vec3D(
            math.cos(pitch) * math.cos(yaw),
            math.sin(pitch),
            math.cos(pitch) * math.sin(yaw)
        ).normalized()
    
    def get_right(self):
        pitch = math.radians(self.rotation.x)
        yaw = math.radians(self.rotation.y + 90)
        return Vec3D(
            math.cos(pitch) * math.cos(yaw), 
            0,
            math.cos(pitch) * math.sin(yaw)
        ).normalized()

class Space3D:
    _id: int
    def __init__(self):
        self._id = lib.create_space3d()

    def clear(self):
        lib.clear_space3d(self._id)
    
    def draw(self, window: Window, camera: Camera3D):
        lib.draw_camera_3d_win(window._id, self._id,
                               camera.position.x, camera.position.y, camera.position.z,
                               camera.rotation.x, camera.rotation.y, camera.rotation.z,
                               int(camera.aspect.x), int(camera.aspect.y), camera.fov, camera.draw_distance)



class draw3d:
    class light:
        @staticmethod
        def ambient(space: Space3D, power: float,
                    color: RGBA = RGBA(255, 255, 255, 255)):
            lib.draw_ambient_light_3d(
                space._id,
                power,
                color.r / 255.0,
                color.g / 255.0,
                color.b / 255.0,
                color.a / 255.0
            )

        @staticmethod
        def point(space: Space3D, position: Vec3D, power: float,
                    color: RGBA = RGBA(255, 255, 255, 255)):
            lib.draw_point_light_3d(
                space._id,
                position.x,
                position.y,
                position.z,
                power,
                color.r / 255.0,
                color.g / 255.0,
                color.b / 255.0,
                color.a / 255.0
            )

    @staticmethod
    def cube(space: Space3D,
             position: Vec3D,
             size: Vec3D,
             rotation: Vec3D = Vec3D(0, 0, 0),
             color: RGBA = RGBA(255, 255, 255, 255)):
        lib.draw_cube_3d(
            space._id,
            position.x, position.y, position.z,
            size.x, size.y, size.z,
            math.radians(rotation.x),
            math.radians(rotation.y),
            math.radians(rotation.z),
            color.r / 255.0,
            color.g / 255.0,
            color.b / 255.0,
            color.a / 255.0
        )