use core::{ops::Deref, ptr::NonNull};

/// Describes a physical mapping created by `AcpiHandler::map_physical_region` and unmapped by
/// `AcpiHandler::unmap_physical_region`. The region mapped must be at least `size_of::<T>()`
/// bytes, but may be bigger.
///
/// See `PhysicalMapping::new` for the meaning of each field.
#[derive(Debug)]
pub struct PhysicalMapping<H, T>
where
    H: AcpiHandler,
{
    physical_start: usize,
    virtual_start: NonNull<T>,
    region_length: usize, // Can be equal or larger than size_of::<T>()
    mapped_length: usize, // Differs from `region_length` if padding is added for alignment
    handler: H,
}

impl<H, T> PhysicalMapping<H, T>
where
    H: AcpiHandler,
{
    /// Construct a new `PhysicalMapping`.
    ///
    /// - `physical_start` should be the physical address of the structure to be mapped.
    /// - `virtual_start` should be the corresponding virtual address of that structure. It may differ from the
    ///   start of the region mapped due to requirements of the paging system. It must be a valid, non-null
    ///   pointer.
    /// - `region_length` should be the number of bytes requested to be mapped. It must be equal to or larger than
    ///   `size_of::<T>()`.
    /// - `mapped_length` should be the number of bytes mapped to fulfill the request. It may be equal to or larger
    ///   than `region_length`, due to requirements of the paging system or other reasoning.
    /// - `handler` should be the same `AcpiHandler` that created the mapping. When the `PhysicalMapping` is
    ///   dropped, it will be used to unmap the structure.
    pub unsafe fn new(
        physical_start: usize,
        virtual_start: NonNull<T>,
        region_length: usize,
        mapped_length: usize,
        handler: H,
    ) -> Self {
        Self { physical_start, virtual_start, region_length, mapped_length, handler }
    }

    pub fn physical_start(&self) -> usize {
        self.physical_start
    }

    pub fn virtual_start(&self) -> NonNull<T> {
        self.virtual_start
    }

    pub fn region_length(&self) -> usize {
        self.region_length
    }

    pub fn mapped_length(&self) -> usize {
        self.mapped_length
    }

    pub fn handler(&self) -> &H {
        &self.handler
    }
}

unsafe impl<H: AcpiHandler + Send, T: Send> Send for PhysicalMapping<H, T> {}

impl<H, T> Deref for PhysicalMapping<H, T>
where
    H: AcpiHandler,
{
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { self.virtual_start.as_ref() }
    }
}

impl<H, T> Drop for PhysicalMapping<H, T>
where
    H: AcpiHandler,
{
    fn drop(&mut self) {
        H::unmap_physical_region(self)
    }
}

/// An implementation of this trait must be provided to allow `acpi` to access platform-specific
/// functionality, such as mapping regions of physical memory. You are free to implement these
/// however you please, as long as they conform to the documentation of each function. The handler is stored in
/// every `PhysicalMapping` so it's able to unmap itself when dropped, so this type needs to be something you can
/// clone/move about freely (e.g. a reference, wrapper over `Rc`, marker struct, etc.).
pub trait AcpiHandler: Clone {
    /// Given a physical address and a size, map a region of physical memory that contains `T` (note: the passed
    /// size may be larger than `size_of::<T>()`). The address is not neccessarily page-aligned, so the
    /// implementation may need to map more than `size` bytes. The virtual address the region is mapped to does not
    /// matter, as long as it is accessible to `acpi`.
    ///
    /// See the documentation on `PhysicalMapping::new` for an explanation of each field on the `PhysicalMapping`
    /// return type.
    ///
    /// ## Safety
    ///
    /// - `physical_address` must point to a valid `T` in physical memory.
    /// - `size` must be at least `size_of::<T>()`.
    unsafe fn map_physical_region<T>(&self, physical_address: usize, size: usize) -> PhysicalMapping<Self, T>;

    /// Unmap the given physical mapping. This is called when a `PhysicalMapping` is dropped, you should **not** manually call this.
    ///
    /// Note: A reference to the handler used to construct `region` can be acquired by calling [`PhysicalMapping::handler`].
    fn unmap_physical_region<T>(region: &PhysicalMapping<Self, T>);
}

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

    #[test]
    #[allow(dead_code)]
    fn test_send_sync() {
        // verify that PhysicalMapping implements Send and Sync
        fn test_send_sync<T: Send>() {}
        fn caller<H: AcpiHandler + Send, T: Send>() {
            test_send_sync::<PhysicalMapping<H, T>>();
        }
    }
}
