// SPDX-License-Identifier: Apache-2.0

#![deny(clippy::all)]
#![deny(clippy::pedantic)]

#[cfg(any(feature = "office95", feature = "pdf", feature = "rtf"))]
use malwaredb_types::doc;
#[cfg(any(feature = "elf", feature = "macho", feature = "pe32", feature = "pef"))]
use malwaredb_types::exec;
use malwaredb_types::utils::EntropyCalc;

use std::env;

fn main() {
    #[cfg(not(any(
        feature = "default",
        feature = "elf",
        feature = "macho",
        feature = "office95",
        feature = "pe32",
        feature = "pef",
        feature = "pdf",
        feature = "rtf"
    )))]
    eprintln!("No features selected, this program won't do much of anything!");

    let args: Vec<String> = env::args().collect();
    if args.len() < 2 {
        eprintln!("Usage: {} <path to file>", args[0]);
        std::process::exit(10);
    }
    for arg in &args[1..] {
        let contents = match std::fs::read(arg) {
            Ok(c) => c,
            Err(e) => {
                eprintln!("Failed to read {arg}: {e}");
                continue;
            }
        };

        println!("Entropy for {arg}: {}", contents.entropy());

        #[cfg(feature = "elf")]
        if let Ok(elf) = exec::elf::Elf::from(&contents) {
            println!("{arg} is an ELF:\n{elf}");
            continue;
        }

        #[cfg(feature = "pe32")]
        if let Ok(exe) = exec::pe32::EXE::from(&contents) {
            println!("{arg} is an EXE:\n{exe}");
            continue;
        }

        #[cfg(feature = "macho")]
        if let Ok(fmacho) = exec::macho::fat::FatMacho::from(&contents) {
            println!("{arg} is a Fat Mach-O:\n{fmacho}");
            continue;
        }

        #[cfg(feature = "macho")]
        if let Ok(macho) = exec::macho::Macho::from(&contents) {
            println!("{arg} is a Mach-O:\n{macho}");
            continue;
        }

        #[cfg(feature = "office95")]
        if let Ok(docfile) = doc::office95::Office95::from(&contents) {
            println!("{arg} is an Office95/Docfile:\n{docfile}");
            continue;
        }

        #[cfg(feature = "pef")]
        if let Ok(pef) = exec::pef::Pef::from(&contents) {
            println!("{arg} is a PEF:\n{pef}");
            continue;
        }

        #[cfg(feature = "pdf")]
        if let Ok(pdf) = doc::pdf::PDF::from(&contents) {
            println!("{arg} is a PDF:\n{pdf}");
            continue;
        }

        #[cfg(feature = "rtf")]
        if let Ok(rtf) = doc::rtf::Rtf::from(&contents) {
            println!("{arg} is an RTF:\n{rtf}");
            continue;
        }

        eprintln!(
            "{arg} isn't of a known type, or not enough feature flags were provided at compile time."
        );
    }
}
