use std::os::raw::c_int;
use std::path::Path;
use std::ptr;
use fitsio::FitsFile;
use fitsio::sys::{self, LONGLONG, fitsfile};
use crate::error::{AtfitsError, Result, ffcall};
use crate::image::{copy_template_cards, serialise_header};
use crate::path::utf8;
pub struct CubeLayout {
pub header: Vec<u8>,
pub datastart: u64,
}
pub fn create_mem_cube(template: &Path, bitpix: i64, dims: &[usize]) -> Result<FitsFile> {
let mut raw: *mut fitsfile = ptr::null_mut();
ffcall(|s| unsafe { sys::ffinit(&mut raw, c"mem://".as_ptr(), s) })?;
let mut out = unsafe { FitsFile::from_raw(raw, fitsio::FileOpenMode::READWRITE)? };
let mut naxes: Vec<LONGLONG> = vec![1; dims.len()];
ffcall(|s| unsafe {
sys::ffcrimll(
out.as_raw(),
bitpix as c_int,
naxes.len() as c_int,
naxes.as_mut_ptr(),
s,
)
})?;
let mut src = FitsFile::open(utf8(template)?)?;
src.primary_hdu()?;
copy_template_cards(&mut src, &mut out, bitpix)?;
Ok(out)
}
pub fn extract_header_layout(fptr: &mut FitsFile, dims: &[usize]) -> Result<CubeLayout> {
fptr.primary_hdu()?;
let mut header = serialise_header(fptr, &[], 0)?;
for (i, &d) in dims.iter().enumerate() {
set_naxis_card(&mut header, i + 1, d)?;
}
let datastart = header.len() as u64;
Ok(CubeLayout { header, datastart })
}
fn set_naxis_card(header: &mut [u8], axis: usize, value: usize) -> Result<()> {
let key = format!("NAXIS{axis}");
let card = header
.as_chunks_mut::<80>()
.0
.iter_mut()
.find(|c| c.starts_with(key.as_bytes()) && c[key.len()] == b' ')
.ok_or_else(|| AtfitsError::Other(format!("{key} card not found in header")))?;
let digits = value.to_string();
let field = &mut card[10..30];
field.fill(b' ');
field[20 - digits.len()..].copy_from_slice(digits.as_bytes());
Ok(())
}