// Copyright 2021 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 crate::fs::*;
use crate::lock::Mutex;
use crate::task::*;
use crate::types::*;
use std::sync::Arc;

const DATA_SIZE: usize = 8;

pub enum EventFdType {
    Counter,
    Semaphore,
}

/// The eventfd file object has two modes of operation:
/// 1) Counter: Write adds to the value and read returns the value while setting it to zero.
/// 2) Semaphore: Write adds one to the counter and read decrements it and returns 1.
/// In both cases, if the value is 0, the read blocks or returns EAGAIN.
/// See https://man7.org/linux/man-pages/man2/eventfd.2.html

struct EventFdInner {
    value: u64,
    wait_queue: WaitQueue,
}

pub struct EventFdFileObject {
    inner: Mutex<EventFdInner>,
    eventfd_type: EventFdType,
}

pub fn new_eventfd(
    kernel: &Kernel,
    value: u32,
    eventfd_type: EventFdType,
    blocking: bool,
) -> FileHandle {
    let open_flags = if blocking { OpenFlags::RDWR } else { OpenFlags::RDWR | OpenFlags::NONBLOCK };
    Anon::new_file(
        anon_fs(kernel),
        Box::new(EventFdFileObject {
            inner: Mutex::new(EventFdInner {
                value: value.into(),
                wait_queue: WaitQueue::default(),
            }),
            eventfd_type,
        }),
        open_flags,
    )
}

fn query_events_internal(inner: &EventFdInner) -> FdEvents {
    // TODO check for error and HUP events
    let mut events = FdEvents::empty();
    if inner.value > 0 {
        events |= FdEvents::POLLIN;
    }
    if inner.value < u64::MAX - 1 {
        events |= FdEvents::POLLOUT;
    }
    events
}

impl FileOps for EventFdFileObject {
    fileops_impl_nonseekable!();

    fn write(
        &self,
        _file: &FileObject,
        current_task: &CurrentTask,
        data: &[UserBuffer],
    ) -> Result<usize, Errno> {
        let mut written_data = [0; DATA_SIZE];
        if current_task.mm.read_all(data, &mut written_data)? < DATA_SIZE {
            return error!(EINVAL);
        }
        let add_value = u64::from_ne_bytes(written_data);
        if add_value == u64::MAX {
            return error!(EINVAL);
        }

        // The maximum value of the counter is u64::MAX - 1
        let mut inner = self.inner.lock();
        let headroom = u64::MAX - inner.value;
        if headroom < add_value {
            return error!(EAGAIN);
        }
        inner.value = inner.value + add_value;
        if inner.value > 0 {
            inner.wait_queue.notify_mask(FdEvents::POLLIN.mask());
        }
        Ok(DATA_SIZE)
    }

    fn read(
        &self,
        _file: &FileObject,
        current_task: &CurrentTask,
        data: &[UserBuffer],
    ) -> Result<usize, Errno> {
        if UserBuffer::get_total_length(data)? < DATA_SIZE {
            return error!(EINVAL);
        }

        let mut inner = self.inner.lock();
        if inner.value == 0 {
            return error!(EAGAIN);
        }

        let return_value = match self.eventfd_type {
            EventFdType::Counter => {
                let start_value = inner.value;
                inner.value = 0;
                start_value
            }
            EventFdType::Semaphore => {
                inner.value = inner.value - 1;
                1
            }
        };
        current_task.mm.write_all(data, &return_value.to_ne_bytes())?;
        inner.wait_queue.notify_mask(FdEvents::POLLOUT.mask());

        Ok(DATA_SIZE)
    }

    fn wait_async(
        &self,
        _file: &FileObject,
        _current_task: &CurrentTask,
        waiter: &Arc<Waiter>,
        events: FdEvents,
        handler: EventHandler,
    ) -> WaitKey {
        let mut inner = self.inner.lock();
        let present_events = query_events_internal(&inner);
        if events & present_events {
            waiter.wake_immediately(present_events.mask(), handler)
        } else {
            inner.wait_queue.wait_async_mask(waiter, events.mask(), handler)
        }
    }

    fn cancel_wait(&self, _current_task: &CurrentTask, _waiter: &Arc<Waiter>, key: WaitKey) {
        let mut inner = self.inner.lock();
        inner.wait_queue.cancel_wait(key);
    }

    fn query_events(&self, _current_task: &CurrentTask) -> FdEvents {
        let inner = self.inner.lock();
        query_events_internal(&inner)
    }
}
