// rasm-core/src/codegen/aot/mod.rs
//
//! # AOT-компилятор RASM
//!
//! | Формат  | Платформа | Модуль   |
//! |---------|-----------|----------|
//! | ELF64   | Linux     | `elf.rs` |
//! | PE32+   | Windows   | `pe.rs`  |
pub mod elf;
pub mod pe;

/// Форматы для записи бинарного кода в файл
#[derive(Debug, Clone, Copy)]
pub enum Formats {
    /// # Бинарный формат (`.bin`)
    ///
    /// Просто сырой машинный код, не исполняемый,
    /// в основном нужен для создания ОС.
    BIN,

    /// # PE (`.exe`)
    ///
    /// Формат для исполняемых файлов на Windows.
    PE,

    /// # ELF
    ///
    /// Формат для исполняемых файлов на Linux.
    /// У итогового файла может быть любое расширение.
    ELF,
}

use std::io::Write;

pub use elf::ElfWriter;
pub use pe::PeWriter;

/// Записывает исполняемый файл в формате текущей платформы.
///
/// На Linux — ELF64, на Windows — PE32+.
pub fn write_native_executable(
    code: &[u8],
    entry_offset: usize,
    path: &str,
    file_format: Formats,
) -> std::io::Result<()> {
    use std::fs::File;

    let mut file = File::create(path)?;

    let _ = match file_format {
        Formats::BIN => file.write_all(code),
        Formats::PE => {
            {
                let writer = PeWriter::new(code.to_vec(), entry_offset);
                writer.write(&mut file)?;
            }
            Ok(())
        }
        Formats::ELF => {
            {
                let writer = ElfWriter::new(code.to_vec(), Vec::new(), entry_offset);
                writer.write(&mut file)?;

                // chmod +x на Unix
                #[cfg(unix)]
                {
                    use std::os::unix::fs::PermissionsExt;
                    if let Ok(meta) = std::fs::metadata(path) {
                        let mut perms = meta.permissions();
                        perms.set_mode(perms.mode() | 0o111);
                        let _ = std::fs::set_permissions(path, perms);
                    }
                }
            }
            Ok(())
        }
    };

    Ok(())
}
