use crate::ffi::callback::*;
use crate::ffi::helpers::*;
use crate::ffi::result::*;
use crate::file_converter::*;
use std::os::raw::{c_char, c_void};

#[no_mangle]
pub extern "C" fn XIMU3_file_converter_status_to_string(status: FileConverterStatus) -> *const c_char {
    str_to_char_ptr(&status.to_string())
}

#[no_mangle]
pub extern "C" fn XIMU3_file_converter_progress_to_string(progress: FileConverterProgress) -> *const c_char {
    str_to_char_ptr(&progress.to_string())
}

pub struct FileConverterC {
    internal: std::io::Result<FileConverter>,
}

#[no_mangle]
pub extern "C" fn XIMU3_file_converter_new(destination: *const c_char, name: *const c_char, file_paths: *const *const c_char, length: u32, callback: Callback<FileConverterProgress>, context: *mut c_void) -> *mut FileConverterC {
    let destination = unsafe { char_ptr_to_string(destination) };
    let name = unsafe { char_ptr_to_string(name) };
    let file_paths = unsafe { char_ptr_array_to_vec_string(file_paths, length) };
    let void_ptr = VoidPtr(context);

    Box::into_raw(Box::new(FileConverterC {
        internal: FileConverter::new(destination.as_str(), name.as_str(), file_paths.iter().map(|s| s.as_str()).collect(), Box::new(move |progress| callback(progress, void_ptr.0))),
    }))
}

#[no_mangle]
pub extern "C" fn XIMU3_file_converter_free(file_converter: *mut FileConverterC) {
    if file_converter.is_null() {
        return;
    }

    unsafe { drop(Box::from_raw(file_converter)) };
}

#[no_mangle]
pub extern "C" fn XIMU3_file_converter_get_result(file_converter: *mut FileConverterC) -> Result {
    let file_converter = unsafe { &*file_converter };

    Result::from(&file_converter.internal)
}

#[no_mangle]
pub extern "C" fn XIMU3_file_converter_convert(destination: *const c_char, name: *const c_char, file_paths: *const *const c_char, length: u32) -> Result {
    let destination = unsafe { char_ptr_to_string(destination) };
    let name = unsafe { char_ptr_to_string(name) };
    let file_paths = unsafe { char_ptr_array_to_vec_string(file_paths, length) };

    Result::from(&FileConverter::convert(destination.as_str(), name.as_str(), file_paths.iter().map(|s| s.as_str()).collect()))
}