// 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 libc::size_t;
use std::fmt;
use std::mem::size_of;
use std::os::raw::c_char;

#[repr(C)]
#[derive(Clone, Copy)]
pub struct LtcMessage {
    pub timestamp: u64,
    pub char_array: [c_char; DATA_MESSAGE_CHAR_ARRAY_SIZE],
    pub number_of_bytes: size_t,
}

impl Default for LtcMessage {
    fn default() -> Self {
        Self {
            timestamp: 0,
            char_array: [0; DATA_MESSAGE_CHAR_ARRAY_SIZE],
            number_of_bytes: 0,
        }
    }
}

impl LtcMessage {
    pub fn char_array_as_string(self) -> String {
        char_array_to_string(&self.char_array, self.number_of_bytes)
    }
}

impl DataMessage for LtcMessage {
    fn get_ascii_id() -> u8 {
        b'C'
    }

    fn parse_ascii(message: &str) -> Result<Self, ReceiveError> {
        match scan_fmt!(message, "{},{d},{[^\n]}\n", char, u64, String) {
            Ok((_, timestamp, string)) => {
                let (char_array, number_of_bytes) = string_to_char_array(string);

                Ok(Self {
                    timestamp,
                    char_array,
                    number_of_bytes,
                })
            }
            Err(_) => Err(ReceiveError::UnableToParseAsciiMessage),
        }
    }

    fn parse_binary(message: &[u8]) -> Result<Self, ReceiveError> {
        #[repr(C, packed)]
        struct Header {
            _id: u8,
            timestamp: u64,
        }

        let min_message_size = size_of::<Header>() + 1; // include termination byte

        if message.len() < min_message_size {
            return Err(ReceiveError::InvalidBinaryMessageLength);
        }

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

        let (char_array, number_of_bytes) = slice_to_char_array(&message[size_of::<Header>()..(message.len() - 1)]); // exclude termination byte

        Ok(LtcMessage {
            timestamp,
            char_array,
            number_of_bytes,
        })
    }

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

    fn get_csv_headings(&self) -> &'static str {
        "Timestamp (us),String\n"
    }

    fn to_csv_row(&self) -> String {
        format!("{},{}\n", self.timestamp, char_array_to_string(&self.char_array, self.number_of_bytes))
    }
}

impl fmt::Display for LtcMessage {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{:>8} us \"{}\"", self.timestamp, char_array_to_string(&self.char_array, self.number_of_bytes))
    }
}