// We avoid relying on anything else in the crate, apart from the `Debug` trait.
use crate::fmt::Debug;
use std::cmp::Ordering;
use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};

/// A blueprint for crash test dummy instances that monitor particular events.
/// Some instances may be configured to panic at some point.
/// Events are `clone`, `drop` or some anonymous `query`.
///
/// Crash test dummies are identified and ordered by an id, so they can be used
/// as keys in a BTreeMap.
#[derive(Debug)]
pub struct CrashTestDummy {
    pub id: usize,
    cloned: AtomicUsize,
    dropped: AtomicUsize,
    queried: AtomicUsize,
}

impl CrashTestDummy {
    /// Creates a crash test dummy design. The `id` determines order and equality of instances.
    pub fn new(id: usize) -> CrashTestDummy {
        CrashTestDummy {
            id,
            cloned: AtomicUsize::new(0),
            dropped: AtomicUsize::new(0),
            queried: AtomicUsize::new(0),
        }
    }

    /// Creates an instance of a crash test dummy that records what events it experiences
    /// and optionally panics.
    pub fn spawn(&self, panic: Panic) -> Instance<'_> {
        Instance { origin: self, panic }
    }

    /// Returns how many times instances of the dummy have been cloned.
    pub fn cloned(&self) -> usize {
        self.cloned.load(SeqCst)
    }

    /// Returns how many times instances of the dummy have been dropped.
    pub fn dropped(&self) -> usize {
        self.dropped.load(SeqCst)
    }

    /// Returns how many times instances of the dummy have had their `query` member invoked.
    pub fn queried(&self) -> usize {
        self.queried.load(SeqCst)
    }
}

#[derive(Debug)]
pub struct Instance<'a> {
    origin: &'a CrashTestDummy,
    panic: Panic,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Panic {
    Never,
    InClone,
    InDrop,
    InQuery,
}

impl Instance<'_> {
    pub fn id(&self) -> usize {
        self.origin.id
    }

    /// Some anonymous query, the result of which is already given.
    pub fn query<R>(&self, result: R) -> R {
        self.origin.queried.fetch_add(1, SeqCst);
        if self.panic == Panic::InQuery {
            panic!("panic in `query`");
        }
        result
    }
}

impl Clone for Instance<'_> {
    fn clone(&self) -> Self {
        self.origin.cloned.fetch_add(1, SeqCst);
        if self.panic == Panic::InClone {
            panic!("panic in `clone`");
        }
        Self { origin: self.origin, panic: Panic::Never }
    }
}

impl Drop for Instance<'_> {
    fn drop(&mut self) {
        self.origin.dropped.fetch_add(1, SeqCst);
        if self.panic == Panic::InDrop {
            panic!("panic in `drop`");
        }
    }
}

impl PartialOrd for Instance<'_> {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.id().partial_cmp(&other.id())
    }
}

impl Ord for Instance<'_> {
    fn cmp(&self, other: &Self) -> Ordering {
        self.id().cmp(&other.id())
    }
}

impl PartialEq for Instance<'_> {
    fn eq(&self, other: &Self) -> bool {
        self.id().eq(&other.id())
    }
}

impl Eq for Instance<'_> {}
