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

use crate::{
    error::{CIntZeroResult, EResult, ResultExt},
    headers::{
        errno::Errno,
        sys_time::{__ygg_timespec_t, timespec},
        sys_types::{clock_t, clockid_t, pid_t, time_t},
        time::{CLOCK_MONOTONIC, CLOCK_REALTIME},
    },
};

use yggdrasil_rt::time::{self as rt, ClockType};

/*
TODO
int        timer_create(clockid_t, struct sigevent *restrict,
               timer_t *restrict);
int        timer_delete(timer_t);
int        timer_getoverrun(timer_t);
int        timer_gettime(timer_t, struct itimerspec *);
int        timer_settime(timer_t, int, const struct itimerspec *restrict,
               struct itimerspec *restrict);
*/

fn clock_type(clock_id: clockid_t) -> EResult<ClockType> {
    match clock_id {
        CLOCK_REALTIME => EResult::Ok(ClockType::RealTime),
        CLOCK_MONOTONIC => EResult::Ok(ClockType::Monotonic),
        _ => EResult::Err(Errno::EINVAL),
    }
}

#[no_mangle]
unsafe extern "C" fn clock() -> clock_t {
    // TODO
    0
}

#[no_mangle]
unsafe extern "C" fn clock_getcpuclockid(_pid: pid_t, _clock_id_ptr: *mut clockid_t) -> c_int {
    todo!()
}

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

#[no_mangle]
unsafe extern "C" fn clock_gettime(
    clock_id: clockid_t,
    ts: *mut __ygg_timespec_t,
) -> CIntZeroResult {
    let clock = clock_type(clock_id)?;
    let time = rt::get_clock(clock).e_map_err(Errno::from)?;

    if let Some(ts) = NonNull::new(ts) {
        ts.write(timespec {
            tv_sec: time_t(time.seconds() as _),
            tv_nsec: time.subsec_nanos() as _,
        });
    }

    CIntZeroResult::SUCCESS
}

#[no_mangle]
unsafe extern "C" fn clock_settime(_clock_id: clockid_t, _ts: *const __ygg_timespec_t) -> c_int {
    todo!()
}

#[no_mangle]
unsafe extern "C" fn clock_nanosleep(
    _clock_id: clockid_t,
    _flags: c_int,
    _rqtp: *const __ygg_timespec_t,
    _rmtp: *mut __ygg_timespec_t,
) -> c_int {
    todo!()
}

// TODO Timer something
