#![allow(non_camel_case_types)]
#![allow(clippy::module_name_repetitions)]

use std::ffi::CString;

use eccodes_sys::codes_handle;

use crate::{errors::CodesError, intermediate_bindings::error_code_to_result, pointer_guard};

pub unsafe fn codes_set_long(
    handle: *mut codes_handle,
    key: &str,
    value: i64,
) -> Result<(), CodesError> {
    unsafe {
        pointer_guard::non_null!(handle);

        let key = CString::new(key).unwrap();

        let error_code = eccodes_sys::codes_set_long(handle, key.as_ptr(), value);
        error_code_to_result(error_code)?;

        Ok(())
    }
}

pub unsafe fn codes_set_double(
    handle: *mut codes_handle,
    key: &str,
    value: f64,
) -> Result<(), CodesError> {
    unsafe {
        pointer_guard::non_null!(handle);

        let key = CString::new(key).unwrap();

        let error_code = eccodes_sys::codes_set_double(handle, key.as_ptr(), value);
        error_code_to_result(error_code)?;

        Ok(())
    }
}

pub unsafe fn codes_set_long_array(
    handle: *mut codes_handle,
    key: &str,
    values: &[i64],
) -> Result<(), CodesError> {
    unsafe {
        pointer_guard::non_null!(handle);

        let key = CString::new(key).unwrap();

        let length = values.len();

        let error_code =
            eccodes_sys::codes_set_long_array(handle, key.as_ptr(), values.as_ptr().cast(), length);
        error_code_to_result(error_code)?;

        Ok(())
    }
}

pub unsafe fn codes_set_double_array(
    handle: *mut codes_handle,
    key: &str,
    values: &[f64],
) -> Result<(), CodesError> {
    unsafe {
        pointer_guard::non_null!(handle);

        let key = CString::new(key).unwrap();

        let length = values.len();

        let error_code = eccodes_sys::codes_set_double_array(
            handle,
            key.as_ptr(),
            values.as_ptr().cast(),
            length,
        );
        error_code_to_result(error_code)?;

        Ok(())
    }
}

pub unsafe fn codes_set_string(
    handle: *mut codes_handle,
    key: &str,
    value: &str,
) -> Result<(), CodesError> {
    unsafe {
        pointer_guard::non_null!(handle);

        let key = CString::new(key).unwrap();
        let mut length = value.len();
        let value = CString::new(value).unwrap();

        let error_code =
            eccodes_sys::codes_set_string(handle, key.as_ptr(), value.as_ptr(), &raw mut length);
        error_code_to_result(error_code)?;

        Ok(())
    }
}

pub unsafe fn codes_set_bytes(
    handle: *mut codes_handle,
    key: &str,
    values: &[u8],
) -> Result<(), CodesError> {
    unsafe {
        pointer_guard::non_null!(handle);

        let key = CString::new(key).unwrap();

        let mut length = values.len();

        let error_code = eccodes_sys::codes_set_bytes(
            handle,
            key.as_ptr(),
            values.as_ptr().cast(),
            &raw mut length,
        );
        error_code_to_result(error_code)?;

        Ok(())
    }
}
