// This file was generated by x-IMU3-API/Rust/src/data_messages/generate_data_messages.py

use crate::data_messages::*;
use crate::receive_error::*;
use std::fmt;
use std::mem::size_of;

#[repr(C)]
#[derive(Clone, Copy)]
pub struct RotationMatrixMessage {
    pub timestamp: u64,
    pub xx: f32,
    pub xy: f32,
    pub xz: f32,
    pub yx: f32,
    pub yy: f32,
    pub yz: f32,
    pub zx: f32,
    pub zy: f32,
    pub zz: f32,
}

impl Default for RotationMatrixMessage {
    fn default() -> Self {
        Self {
            timestamp: 0,
            xx: 0.0,
            xy: 0.0,
            xz: 0.0,
            yx: 0.0,
            yy: 0.0,
            yz: 0.0,
            zx: 0.0,
            zy: 0.0,
            zz: 0.0,
        }
    }
}

impl DataMessage for RotationMatrixMessage {
    fn get_ascii_id() -> u8 {
        b'R'
    }

    fn parse_ascii(message: &str) -> Result<Self, ReceiveError> {
        match scan_fmt!(message, "{},{d},{f},{f},{f},{f},{f},{f},{f},{f},{f}\n", char, u64, f32, f32, f32, f32, f32, f32, f32, f32, f32) {
            Ok((_, timestamp, xx, xy, xz, yx, yy, yz, zx, zy, zz)) => Ok(Self {
                timestamp,
                xx,
                xy,
                xz,
                yx,
                yy,
                yz,
                zx,
                zy,
                zz,
            }),
            Err(_) => Err(ReceiveError::UnableToParseAsciiMessage),
        }
    }

    fn parse_binary(message: &[u8]) -> Result<Self, ReceiveError> {
        #[repr(C, packed)]
        struct BinaryMessage {
            _id: u8,
            timestamp: u64,
            xx: f32,
            xy: f32,
            xz: f32,
            yx: f32,
            yy: f32,
            yz: f32,
            zx: f32,
            zy: f32,
            zz: f32,
            _termination: u8,
        }

        if message.len() != size_of::<BinaryMessage>() {
            return Err(ReceiveError::InvalidBinaryMessageLength);
        }

        let binary_message = unsafe {
            let ref binary_message = *(message.as_ptr() as *const BinaryMessage);
            binary_message
        };

        Ok(Self {
            timestamp: binary_message.timestamp,
            xx: binary_message.xx,
            xy: binary_message.xy,
            xz: binary_message.xz,
            yx: binary_message.yx,
            yy: binary_message.yy,
            yz: binary_message.yz,
            zx: binary_message.zx,
            zy: binary_message.zy,
            zz: binary_message.zz,
        })
    }

    fn get_csv_file_name(&self) -> &'static str {
        "RotationMatrix.csv"
    }

    fn get_csv_headings(&self) -> &'static str {
        "Timestamp (us),XX,XY,XZ,YX,YY,YZ,ZX,ZY,ZZ\n"
    }

    fn to_csv_row(&self) -> String {
        format!("{},{:.6},{:.6},{:.6},{:.6},{:.6},{:.6},{:.6},{:.6},{:.6}\n", self.timestamp, self.xx, self.xy, self.xz, self.yx, self.yy, self.yz, self.zx, self.zy, self.zz)
    }
}

impl fmt::Display for RotationMatrixMessage {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{:>8} us {:>8.3} {:>8.3} {:>8.3} {:>8.3} {:>8.3} {:>8.3} {:>8.3} {:>8.3} {:>8.3}", self.timestamp, self.xx, self.xy, self.xz, self.yx, self.yy, self.yz, self.zx, self.zy, self.zz)
    }
}