#![allow(unused)]
#![allow(dead_code)]

mod ffi;

pub use ffi::{ptex_filter_create, PtexFilterOptions, PtexFilterType};

use std::ffi::c_void;
use std::marker::PhantomData;
use std::ptr::NonNull;

pub struct PtexFilter {
    handle: NonNull<c_void>,
    _marker: PhantomData<*mut ()>,
}

impl PtexFilter {
    /// Creates a new Ptex filter pointer
    ///
    /// # Safety
    pub unsafe fn new(texture_ptr: *mut c_void, opts: &PtexFilterOptions) -> Option<Self> {
        let handle = ffi::ptex_filter_create(texture_ptr, opts);
        NonNull::new(handle).map(|h| Self {
            handle: h,
            _marker: PhantomData,
        })
    }

    pub fn eval(
        &self,
        face_id: i32,
        u: f32,
        v: f32,
        dudx: f32,
        dvdx: f32,
        dudy: f32,
        dvdy: f32,
        num_channels: i32,
    ) -> [f32; 4] {
        let mut result = [0.0f32; 4];
        unsafe {
            ffi::ptex_filter_eval(
                self.handle.as_ptr(),
                result.as_mut_ptr(),
                0,
                num_channels.min(4),
                face_id,
                u,
                v,
                dudx,
                dvdx,
                dudy,
                dvdy,
            );
        }
        result
    }
}

impl Drop for PtexFilter {
    fn drop(&mut self) {
        unsafe {
            ffi::ptex_filter_release(self.handle.as_ptr());
        }
    }
}
