/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use std::cell::Cell;

use canvas_traits::webgl::{
    ActiveAttribInfo, WebGLCommand, WebGLError, WebGLResult, WebGLVersion, WebGLVertexArrayId,
};

use crate::dom::bindings::cell::{DomRefCell, Ref};
use crate::dom::bindings::codegen::Bindings::WebGL2RenderingContextBinding::WebGL2RenderingContextConstants as constants2;
use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
use crate::dom::bindings::root::{Dom, MutNullableDom};
use crate::dom::webgl::webglbuffer::WebGLBuffer;
use crate::dom::webgl::webglrenderingcontext::{Operation, WebGLRenderingContext};

#[derive(JSTraceable, MallocSizeOf)]
#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
pub(crate) struct VertexArrayObject {
    context: Dom<WebGLRenderingContext>,
    #[no_trace]
    id: Option<WebGLVertexArrayId>,
    ever_bound: Cell<bool>,
    is_deleted: Cell<bool>,
    vertex_attribs: DomRefCell<Box<[VertexAttribData]>>,
    element_array_buffer: MutNullableDom<WebGLBuffer>,
}

impl VertexArrayObject {
    pub(crate) fn new(context: &WebGLRenderingContext, id: Option<WebGLVertexArrayId>) -> Self {
        let max_vertex_attribs = context.limits().max_vertex_attribs as usize;
        Self {
            context: Dom::from_ref(context),
            id,
            ever_bound: Default::default(),
            is_deleted: Default::default(),
            vertex_attribs: DomRefCell::new(vec![Default::default(); max_vertex_attribs].into()),
            element_array_buffer: Default::default(),
        }
    }

    pub(crate) fn id(&self) -> Option<WebGLVertexArrayId> {
        self.id
    }

    pub(crate) fn is_deleted(&self) -> bool {
        self.is_deleted.get()
    }

    pub(crate) fn delete(&self, operation_fallibility: Operation) {
        assert!(self.id.is_some());
        if self.is_deleted.get() {
            return;
        }
        self.is_deleted.set(true);
        let cmd = WebGLCommand::DeleteVertexArray(self.id.unwrap());
        match operation_fallibility {
            Operation::Fallible => self.context.send_command_ignored(cmd),
            Operation::Infallible => self.context.send_command(cmd),
        }

        for attrib_data in &**self.vertex_attribs.borrow() {
            if let Some(buffer) = attrib_data.buffer() {
                buffer.decrement_attached_counter(operation_fallibility);
            }
        }
        if let Some(buffer) = self.element_array_buffer.get() {
            buffer.decrement_attached_counter(operation_fallibility);
        }
    }

    pub(crate) fn ever_bound(&self) -> bool {
        self.ever_bound.get()
    }

    pub(crate) fn set_ever_bound(&self) {
        self.ever_bound.set(true);
    }

    pub(crate) fn element_array_buffer(&self) -> &MutNullableDom<WebGLBuffer> {
        &self.element_array_buffer
    }

    pub(crate) fn get_vertex_attrib(&self, index: u32) -> Option<Ref<'_, VertexAttribData>> {
        Ref::filter_map(self.vertex_attribs.borrow(), |attribs| {
            attribs.get(index as usize)
        })
        .ok()
    }

    pub(crate) fn set_vertex_attrib_type(&self, index: u32, type_: u32) {
        self.vertex_attribs.borrow_mut()[index as usize].type_ = type_;
    }

    pub(crate) fn vertex_attrib_pointer(
        &self,
        index: u32,
        size: i32,
        type_: u32,
        normalized: bool,
        stride: i32,
        offset: i64,
    ) -> WebGLResult<()> {
        let mut attribs = self.vertex_attribs.borrow_mut();
        let data = attribs
            .get_mut(index as usize)
            .ok_or(WebGLError::InvalidValue)?;

        if !(1..=4).contains(&size) {
            return Err(WebGLError::InvalidValue);
        }

        // https://www.khronos.org/registry/webgl/specs/latest/1.0/#BUFFER_OFFSET_AND_STRIDE
        // https://www.khronos.org/registry/webgl/specs/latest/1.0/#VERTEX_STRIDE
        if !(0..=255).contains(&stride) || offset < 0 {
            return Err(WebGLError::InvalidValue);
        }

        let is_webgl2 = matches!(self.context.webgl_version(), WebGLVersion::WebGL2);

        let bytes_per_component: i32 = match type_ {
            constants::BYTE | constants::UNSIGNED_BYTE => 1,
            constants::SHORT | constants::UNSIGNED_SHORT => 2,
            constants::FLOAT => 4,
            constants::INT | constants::UNSIGNED_INT if is_webgl2 => 4,
            constants2::HALF_FLOAT if is_webgl2 => 2,
            glow::FIXED if is_webgl2 => 4,
            constants2::INT_2_10_10_10_REV | constants2::UNSIGNED_INT_2_10_10_10_REV
                if is_webgl2 && size == 4 =>
            {
                4
            },
            _ => return Err(WebGLError::InvalidEnum),
        };

        if offset % bytes_per_component as i64 > 0 || stride % bytes_per_component > 0 {
            return Err(WebGLError::InvalidOperation);
        }

        let buffer = self.context.array_buffer();
        match buffer {
            Some(ref buffer) => buffer.increment_attached_counter(),
            None if offset != 0 => {
                // https://github.com/KhronosGroup/WebGL/pull/2228
                return Err(WebGLError::InvalidOperation);
            },
            _ => {},
        }
        self.context.send_command(WebGLCommand::VertexAttribPointer(
            index,
            size,
            type_,
            normalized,
            stride,
            offset as u32,
        ));
        if let Some(old) = data.buffer() {
            old.decrement_attached_counter(Operation::Infallible);
        }

        *data = VertexAttribData {
            enabled_as_array: data.enabled_as_array,
            size: size as u8,
            type_,
            bytes_per_vertex: size as u8 * bytes_per_component as u8,
            normalized,
            stride: stride as u8,
            offset: offset as u32,
            buffer: buffer.map(|b| Dom::from_ref(&*b)),
            divisor: data.divisor,
        };

        Ok(())
    }

    pub(crate) fn vertex_attrib_divisor(&self, index: u32, value: u32) {
        self.vertex_attribs.borrow_mut()[index as usize].divisor = value;
    }

    pub(crate) fn enabled_vertex_attrib_array(&self, index: u32, value: bool) {
        self.vertex_attribs.borrow_mut()[index as usize].enabled_as_array = value;
    }

    pub(crate) fn unbind_buffer(&self, buffer: &WebGLBuffer) {
        for attrib in &mut **self.vertex_attribs.borrow_mut() {
            if let Some(b) = attrib.buffer() {
                if b.id() != buffer.id() {
                    continue;
                }
                b.decrement_attached_counter(Operation::Infallible);
            }
            attrib.buffer = None;
        }
        if self
            .element_array_buffer
            .get()
            .is_some_and(|b| buffer == &*b)
        {
            buffer.decrement_attached_counter(Operation::Infallible);
            self.element_array_buffer.set(None);
        }
    }

    pub(crate) fn validate_for_draw(
        &self,
        required_len: u32,
        instance_count: u32,
        active_attribs: &[ActiveAttribInfo],
    ) -> WebGLResult<()> {
        // TODO(nox): Cache limits per VAO.
        let attribs = self.vertex_attribs.borrow();
        // https://www.khronos.org/registry/webgl/specs/latest/1.0/#6.2
        if attribs
            .iter()
            .any(|data| data.enabled_as_array && data.buffer.is_none())
        {
            return Err(WebGLError::InvalidOperation);
        }
        let mut has_active_attrib = false;
        let mut has_divisor_0 = false;
        for active_info in active_attribs {
            let Some(location) = active_info.location else {
                continue;
            };
            has_active_attrib = true;
            let attrib = &attribs[location as usize];
            if attrib.divisor == 0 {
                has_divisor_0 = true;
            }
            if !attrib.enabled_as_array {
                continue;
            }
            // https://www.khronos.org/registry/webgl/specs/latest/1.0/#6.6
            if required_len > 0 && instance_count > 0 {
                let max_vertices = attrib.max_vertices();
                if attrib.divisor == 0 {
                    if max_vertices < required_len {
                        return Err(WebGLError::InvalidOperation);
                    }
                } else if max_vertices
                    .checked_mul(attrib.divisor)
                    .is_some_and(|v| v < instance_count)
                {
                    return Err(WebGLError::InvalidOperation);
                }
            }
        }
        if has_active_attrib && !has_divisor_0 {
            return Err(WebGLError::InvalidOperation);
        }
        Ok(())
    }
}

impl Drop for VertexArrayObject {
    fn drop(&mut self) {
        if self.id.is_some() {
            self.delete(Operation::Fallible);
        }
    }
}

#[derive(Clone, JSTraceable, MallocSizeOf)]
#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
pub(crate) struct VertexAttribData {
    pub(crate) enabled_as_array: bool,
    pub(crate) size: u8,
    pub(crate) type_: u32,
    bytes_per_vertex: u8,
    pub(crate) normalized: bool,
    pub(crate) stride: u8,
    pub(crate) offset: u32,
    pub(crate) buffer: Option<Dom<WebGLBuffer>>,
    pub(crate) divisor: u32,
}

impl Default for VertexAttribData {
    #[cfg_attr(crown, allow(crown::unrooted_must_root))]
    fn default() -> Self {
        Self {
            enabled_as_array: false,
            size: 4,
            type_: constants::FLOAT,
            bytes_per_vertex: 16,
            normalized: false,
            stride: 0,
            offset: 0,
            buffer: None,
            divisor: 0,
        }
    }
}

impl VertexAttribData {
    pub(crate) fn buffer(&self) -> Option<&WebGLBuffer> {
        self.buffer.as_deref()
    }

    pub(crate) fn max_vertices(&self) -> u32 {
        let capacity = (self.buffer().unwrap().capacity() as u32).saturating_sub(self.offset);
        if capacity < self.bytes_per_vertex as u32 {
            0
        } else if self.stride == 0 {
            capacity / self.bytes_per_vertex as u32
        } else if self.stride < self.bytes_per_vertex {
            (capacity - (self.bytes_per_vertex - self.stride) as u32) / self.stride as u32
        } else {
            let mut max = capacity / self.stride as u32;
            if capacity % self.stride as u32 >= self.bytes_per_vertex as u32 {
                max += 1;
            }
            max
        }
    }
}
