// RMW (ROS Middleware) layer - C-compatible FFI types
// Package: {{ package_name }}
// Message: {{ message_name }}

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

{% for constant in constants %}
pub const {{ constant.name }}: {{ constant.rust_type }} = {{ constant.value }};
{% endfor %}

// FFI bindings to C libraries
#[link(name = "{{ package_name }}__rosidl_typesupport_c")]
extern "C" {
    fn rosidl_typesupport_c__get_message_type_support_handle__{{ package_name }}__msg__{{ message_name }}() -> *const std::ffi::c_void;
}

#[link(name = "{{ package_name }}__rosidl_generator_c")]
#[allow(improper_ctypes)]
extern "C" {
    fn {{ package_name }}__msg__{{ message_name }}__init(msg: *mut {{ message_name }}) -> bool;
    fn {{ package_name }}__msg__{{ message_name }}__Sequence__init(seq: *mut crate::rosidl_runtime_rs::Sequence<{{ message_name }}>, size: usize) -> bool;
    fn {{ package_name }}__msg__{{ message_name }}__Sequence__fini(seq: *mut crate::rosidl_runtime_rs::Sequence<{{ message_name }}>);
    fn {{ package_name }}__msg__{{ message_name }}__Sequence__copy(in_seq: &crate::rosidl_runtime_rs::Sequence<{{ message_name }}>, out_seq: *mut crate::rosidl_runtime_rs::Sequence<{{ message_name }}>) -> bool;
}

// RMW types are C-compatible FFI types
// Serde support is available via the "serde" feature flag
#[repr(C)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct {{ message_name }} {
    {% for field in fields %}
    pub {{ field.name }}: {{ field.rust_type }},
    {% endfor %}
}

impl {{ message_name }} {
    pub fn new() -> Self {
        Self::default()
    }
}

impl Default for {{ message_name }} {
    fn default() -> Self {
        unsafe {
            // SAFETY: Zeroing a message structure is valid for all ROS message types
            let mut msg = std::mem::zeroed();
            // SAFETY: The init function is safe to call on a zeroed message
            if !{{ package_name }}__msg__{{ message_name }}__init(&mut msg as *mut _) {
                panic!("Call to {{ package_name }}__msg__{{ message_name }}__init() failed");
            }
            msg
        }
    }
}

// Trait implementations for ROS runtime

impl crate::rosidl_runtime_rs::SequenceAlloc for {{ message_name }} {
    fn sequence_init(seq: &mut crate::rosidl_runtime_rs::Sequence<Self>, size: usize) -> bool {
        // SAFETY: The pointer is guaranteed to be valid since it comes from a mutable reference
        unsafe { {{ package_name }}__msg__{{ message_name }}__Sequence__init(seq as *mut _, size) }
    }

    fn sequence_fini(seq: &mut crate::rosidl_runtime_rs::Sequence<Self>) {
        // SAFETY: The pointer is guaranteed to be valid since it comes from a mutable reference
        unsafe { {{ package_name }}__msg__{{ message_name }}__Sequence__fini(seq as *mut _) }
    }

    fn sequence_copy(in_seq: &crate::rosidl_runtime_rs::Sequence<Self>, out_seq: &mut crate::rosidl_runtime_rs::Sequence<Self>) -> bool {
        // SAFETY: Both pointers are guaranteed to be valid since they come from references
        unsafe { {{ package_name }}__msg__{{ message_name }}__Sequence__copy(in_seq, out_seq as *mut _) }
    }
}

impl crate::rosidl_runtime_rs::Message for {{ message_name }} {
    type RmwMsg = Self;

    fn into_rmw_message(msg_cow: std::borrow::Cow<'_, Self>) -> std::borrow::Cow<'_, Self::RmwMsg> {
        // Identity conversion: RMW message is already in RMW format
        msg_cow
    }

    fn from_rmw_message(msg: Self::RmwMsg) -> Self {
        // Identity conversion: RMW message is already in RMW format
        msg
    }
}

impl crate::rosidl_runtime_rs::RmwMessage for {{ message_name }} where Self: Sized {
    const TYPE_NAME: &'static str = "{{ package_name }}/msg/{{ message_name }}";

    fn get_type_support() -> *const std::ffi::c_void {
        // SAFETY: No preconditions for this function
        unsafe { rosidl_typesupport_c__get_message_type_support_handle__{{ package_name }}__msg__{{ message_name }}() }
    }
}
