/*
==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--

Namaste

Copyright (C) 2019, 2021-2023  Anonymous

There are several releases over multiple years,
they are listed as ranges, such as: "2021-2023".

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.

::--::--::--::--::--::--::--::--::--::--::--::--::--::--::--::--
*/

//! # Root

#![cfg(any(target_os = "linux", target_os = "l4re", target_os = "android", target_os = "windows"))]

use {
    core::time::Duration,
    std::{
        io::{Error, ErrorKind},
        thread,
        time::Instant,
    },
    crate::{Namaste, Result},
};

/// # Sleep duration
pub (crate) const SLEEP_DURATION: Duration = Duration::from_millis(10);

/// # Makes new `Namaste`
pub fn make<B>(id: B) -> Result<Namaste> where B: AsRef<[u8]> {
    Namaste::make(id)
}

/// # Tries to make a `Namaste`...
///
/// If *the same ID is in use*, waits and tries again until timed out.
pub fn make_wait<B>(id: B, timeout: Duration) -> Result<Namaste> where B: AsRef<[u8]> {
    let start = Instant::now();
    loop {
        match make(&id) {
            Ok(namaste) => return Ok(namaste),
            Err(_) => {
                match Instant::now().checked_duration_since(start) {
                    Some(duration) => if duration > timeout {
                        return Err(Error::new(ErrorKind::TimedOut, __!("Timed out")));
                    },
                    None => return Err(Error::new(ErrorKind::Other, __!("Invalid system time"))),
                };
                thread::sleep(SLEEP_DURATION);
            },
        };
    }
}
