use core::{
    ffi::{c_int, c_void},
    ptr::NonNull,
};

use crate::{
    error::CIntZeroResult,
    headers::{
        sched::__ygg_sched_param_t,
        sys_types::{clockid_t, pthread_attr_t, pthread_t},
    },
    thread::Thread,
};

#[no_mangle]
unsafe extern "C" fn pthread_atfork(
    _prepare: extern "C" fn(),
    _parent: extern "C" fn(),
    _child: extern "C" fn(),
) -> c_int {
    todo!()
}

#[no_mangle]
unsafe extern "C" fn pthread_cancel(_thread: pthread_t) -> c_int {
    todo!()
}

#[no_mangle]
unsafe extern "C" fn pthread_create(
    result: *mut pthread_t,
    attr: *const pthread_attr_t,
    entry: extern "C" fn(*mut c_void) -> *mut c_void,
    argument: *mut c_void,
) -> CIntZeroResult {
    let attr = attr.as_ref();
    let id = Thread::spawn(attr, entry, argument)?;
    if let Some(result) = result.as_mut() {
        *result = id;
    }
    CIntZeroResult::SUCCESS
}

#[no_mangle]
unsafe extern "C" fn pthread_detach(_thread: pthread_t) -> c_int {
    // TODO
    0
}

#[no_mangle]
unsafe extern "C" fn pthread_equal(_thread1: pthread_t, _thread2: pthread_t) -> c_int {
    todo!()
}

#[no_mangle]
unsafe extern "C" fn pthread_exit(_result: *mut c_void) -> c_void {
    todo!()
}

#[no_mangle]
unsafe extern "C" fn pthread_getconcurrency() -> c_int {
    todo!()
}

#[no_mangle]
unsafe extern "C" fn pthread_getcpuclockid(_thread: pthread_t, _clock_id: *mut clockid_t) -> c_int {
    todo!()
}

#[no_mangle]
unsafe extern "C" fn pthread_getschedparam(
    _thread: pthread_t,
    _policy: *mut c_int,
    _param: *mut __ygg_sched_param_t,
) -> c_int {
    todo!()
}

#[no_mangle]
unsafe extern "C" fn pthread_join(thread: pthread_t, result: *mut *mut c_void) -> CIntZeroResult {
    let value = Thread::join(thread)?;
    if let Some(result) = NonNull::new(result) {
        result.write(value);
    }
    CIntZeroResult::SUCCESS
}

#[no_mangle]
unsafe extern "C" fn pthread_self() -> pthread_t {
    Thread::this().expect("pthread_self() failed")
}

#[no_mangle]
unsafe extern "C" fn pthread_setcancelstate(_state: c_int, _old_state: *mut c_int) -> c_int {
    todo!()
}

#[no_mangle]
unsafe extern "C" fn pthread_setcanceltype(_ty: c_int, _old_ty: *mut c_int) -> c_int {
    todo!()
}

#[no_mangle]
unsafe extern "C" fn pthread_setconcurrency(_c: c_int) -> c_int {
    todo!()
}

#[no_mangle]
unsafe extern "C" fn pthread_setschedparam(
    _thread: pthread_t,
    _policy: c_int,
    _param: *const __ygg_sched_param_t,
) -> c_int {
    todo!()
}

#[no_mangle]
unsafe extern "C" fn pthread_setschedprio(_thread: pthread_t, _priority: c_int) -> c_int {
    todo!()
}

#[no_mangle]
unsafe extern "C" fn pthread_testcancel() {
    todo!()
}
