// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use fuchsia_zircon as zx;
use std::cmp;

/// An estimate of the worst possible time drift in the device's oscillator.
const MAX_DRIFT_PPM: i64 = 200;
const ONE_MILLION: i64 = 1_000_000;

/// A representation of the range of possible UTC times at an instant of monotonic time.
#[derive(Debug, PartialEq)]
pub struct Bound {
    /// Monotonic time for which the bound is valid.
    pub monotonic: zx::Time,
    /// The minimum possible UTC time.
    pub utc_min: zx::Time,
    /// The maximum possible UTC time.
    pub utc_max: zx::Time,
}

impl Bound {
    /// Take the intersection of two bounds to produce a (possibly) tighter bound. Returns None if
    /// the bounds do not intersect.
    pub fn combine(&self, other: &Bound) -> Option<Bound> {
        let (earlier, later) =
            if self.monotonic < other.monotonic { (self, other) } else { (other, self) };

        let projected = earlier.project(later.monotonic);
        let combined = Bound {
            monotonic: later.monotonic,
            utc_min: cmp::max(later.utc_min, projected.utc_min),
            utc_max: cmp::min(later.utc_max, projected.utc_max),
        };
        if combined.utc_min > combined.utc_max {
            None
        } else {
            Some(combined)
        }
    }

    /// Project a bound to a different monotonic time. The bound is expanded by the time
    /// elapsed between the bound and the provided monotonic time multiplied by the drift.
    fn project(&self, later_monotonic: zx::Time) -> Bound {
        let time_delta = later_monotonic - self.monotonic;
        let max_drift = (time_delta * MAX_DRIFT_PPM) / ONE_MILLION;
        Bound {
            monotonic: later_monotonic,
            utc_min: self.utc_min + time_delta - max_drift,
            utc_max: self.utc_max + time_delta + max_drift,
        }
    }

    /// Returns the size of the possible range.
    pub fn size(&self) -> zx::Duration {
        self.utc_max - self.utc_min
    }

    /// Returns the center of the possible UTC range.
    pub fn center(&self) -> zx::Time {
        self.utc_min + self.size() / 2
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use lazy_static::lazy_static;

    const DURATION_MICROS_500: zx::Duration = zx::Duration::from_micros(500);
    const MONOTONIC_TIME: zx::Time = zx::Time::from_nanos(1_000_000_000_000);
    lazy_static! {
        static ref DRIFT_IN_500_MICROS: zx::Duration =
            DURATION_MICROS_500 * MAX_DRIFT_PPM / ONE_MILLION;
    }

    fn assert_combine_commutative(bound_1: &Bound, bound_2: &Bound) {
        assert_eq!(bound_1.combine(bound_2), bound_2.combine(bound_1))
    }

    #[fuchsia::test]
    fn combine_bounds_with_same_monotonic_times() {
        let earlier_utc_bound = Bound {
            monotonic: MONOTONIC_TIME,
            utc_min: zx::Time::from_nanos(1_000_000),
            utc_max: zx::Time::from_nanos(2_000_000),
        };
        let later_utc_bound = Bound {
            monotonic: MONOTONIC_TIME,
            utc_min: zx::Time::from_nanos(1_500_000),
            utc_max: zx::Time::from_nanos(2_500_000),
        };
        assert_eq!(
            earlier_utc_bound.combine(&later_utc_bound).unwrap(),
            Bound {
                monotonic: MONOTONIC_TIME,
                utc_min: later_utc_bound.utc_min,
                utc_max: earlier_utc_bound.utc_max,
            }
        );
        assert_combine_commutative(&earlier_utc_bound, &later_utc_bound);

        let enclosing_utc_bound = Bound {
            monotonic: MONOTONIC_TIME,
            utc_min: zx::Time::from_nanos(1_000_000),
            utc_max: zx::Time::from_nanos(2_000_000),
        };
        let enclosed_utc_bound = Bound {
            monotonic: MONOTONIC_TIME,
            utc_min: zx::Time::from_nanos(1_200_000),
            utc_max: zx::Time::from_nanos(1_800_000),
        };
        assert_eq!(enclosed_utc_bound.combine(&enclosing_utc_bound).unwrap(), enclosed_utc_bound);
        assert_combine_commutative(&enclosed_utc_bound, &enclosing_utc_bound);
    }

    #[fuchsia::test]
    fn combine_bounds_with_different_monotonic_times() {
        let earlier = Bound {
            monotonic: MONOTONIC_TIME,
            utc_min: zx::Time::from_nanos(1_000_000),
            utc_max: zx::Time::from_nanos(2_000_000),
        };
        let later = Bound {
            monotonic: MONOTONIC_TIME + DURATION_MICROS_500,
            utc_min: zx::Time::from_nanos(2_000_000),
            utc_max: zx::Time::from_nanos(3_000_000),
        };
        assert_eq!(
            earlier.combine(&later).unwrap(),
            Bound {
                monotonic: later.monotonic,
                utc_min: later.utc_min,
                utc_max: earlier.utc_max + DURATION_MICROS_500 + *DRIFT_IN_500_MICROS
            }
        );
        assert_combine_commutative(&earlier, &later);

        let earlier_enclosing = Bound {
            monotonic: MONOTONIC_TIME,
            utc_min: zx::Time::from_nanos(1_000_000),
            utc_max: zx::Time::from_nanos(2_000_000),
        };
        let later_enclosed = Bound {
            monotonic: MONOTONIC_TIME + DURATION_MICROS_500,
            utc_min: zx::Time::from_nanos(1_700_000),
            utc_max: zx::Time::from_nanos(2_300_000),
        };
        assert_eq!(earlier_enclosing.combine(&later_enclosed).unwrap(), later_enclosed);
        assert_combine_commutative(&earlier_enclosing, &later_enclosed);

        let earlier_enclosed = Bound {
            monotonic: MONOTONIC_TIME,
            utc_min: zx::Time::from_nanos(1_200_000),
            utc_max: zx::Time::from_nanos(1_800_000),
        };
        let later_enclosing = Bound {
            monotonic: MONOTONIC_TIME + DURATION_MICROS_500,
            utc_min: zx::Time::from_nanos(1_500_000),
            utc_max: zx::Time::from_nanos(2_500_000),
        };
        assert_eq!(
            earlier_enclosed.combine(&later_enclosing).unwrap(),
            Bound {
                monotonic: later_enclosing.monotonic,
                utc_min: earlier_enclosed.utc_min + DURATION_MICROS_500 - *DRIFT_IN_500_MICROS,
                utc_max: earlier_enclosed.utc_max + DURATION_MICROS_500 + *DRIFT_IN_500_MICROS,
            }
        );
        assert_combine_commutative(&earlier_enclosed, &later_enclosing);
    }

    #[fuchsia::test]
    fn combine_bounds_no_overlap() {
        let earlier_utc = Bound {
            monotonic: MONOTONIC_TIME,
            utc_min: zx::Time::from_nanos(1_000_000),
            utc_max: zx::Time::from_nanos(2_000_000),
        };
        let later_utc = Bound {
            monotonic: MONOTONIC_TIME,
            utc_min: zx::Time::from_nanos(2_500_000),
            utc_max: zx::Time::from_nanos(3_500_000),
        };
        assert!(earlier_utc.combine(&later_utc).is_none());
        assert_combine_commutative(&earlier_utc, &later_utc);

        let earlier = Bound {
            monotonic: MONOTONIC_TIME,
            utc_min: zx::Time::from_nanos(1_000_000),
            utc_max: zx::Time::from_nanos(2_000_000),
        };
        let later = Bound {
            monotonic: MONOTONIC_TIME + DURATION_MICROS_500,
            utc_min: zx::Time::from_nanos(2_600_000),
            utc_max: zx::Time::from_nanos(3_600_000),
        };
        assert!(earlier.combine(&later).is_none());
        assert_combine_commutative(&earlier, &later);
    }
}
