use ordered_float::OrderedFloat;
use std::ops::Sub;
use std::time::Duration;
use web_sys::window;

#[derive(Copy, Clone, PartialOrd, PartialEq, Ord, Eq, Debug)]
pub struct Instant(OrderedFloat<f64>);

impl Instant {
    pub fn now() -> Self {
        let seconds = window()
            .and_then(|w| w.performance())
            .expect("Can't measure time without a performance object")
            .now()
            / 1000.0;
        Instant(OrderedFloat(seconds))
    }
}

impl Sub for Instant {
    type Output = Duration;

    fn sub(self, rhs: Instant) -> Duration {
        let secs = (self.0).0 - (rhs.0).0;
        let nanos = ((secs % 1.0) * 1_000_000_000.0) as _;
        let secs = secs as _;
        Duration::new(secs, nanos)
    }
}

use ordered_float::OrderedFloat;
use std::ops::Sub;
use std::time::Duration;
use web_sys::window;

#[derive(Copy, Clone, PartialOrd, PartialEq, Ord, Eq, Debug)]
pub struct Instant(OrderedFloat<f64>);

thread_local! {
    static PERFORMANCE: web_sys::Performance = window()
        .expect("No window object available")
        .performance()
        .expect("Can't measure time without a performance object");
}

impl Instant {
    pub fn now() -> Self {
        let seconds = PERFORMANCE.with(|p| p.now()) / 1000.0;
        Instant(OrderedFloat(seconds))
    }
}

impl Sub for Instant {
    type Output = Duration;

    fn sub(self, rhs: Instant) -> Duration {
        let secs = (self.0).0 - (rhs.0).0;
        let nanos = ((secs % 1.0) * 1_000_000_000.0) as _;
        let secs = secs as _;
        Duration::new(secs, nanos)
    }
}

Reduce overhead of JavaScript calls
Reduce overhead of JavaScript calls

In the web our layout state calculation is actually massively dominated
by the calls to `performance.now()`. However before we can even call
`.now()` on the `performance` object, we first need to even get that. So
you first have to get the `window` object and access its `performance`
field. So overall that's three calls into JavaScript. If we however
cache the `performance` object, we can reduce it to just a single call.
That seems to improve the layout state calculation performance by over
2x.

Optimally we would only take a single time stamp per layout state
calculation, as otherwise there might be slight disagreements between
the individual values shown in the layout state. That's however a much
bigger refactoring, so that's something we can look into in the future.
