// 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 bitflags::bitflags;
use fuchsia_zircon as zx;
use parking_lot::{Mutex, RwLock};
use std::collections::HashMap;
use std::ops::Deref;
use std::sync::Arc;

use crate::not_implemented;
use crate::task::*;
use crate::uapi::*;

pub use starnix_macros::FileObject;

#[derive(Hash, PartialEq, Eq, Debug, Copy, Clone)]
pub struct FdNumber(i32);
impl FdNumber {
    pub fn from_raw(n: i32) -> FdNumber {
        FdNumber(n)
    }
    pub fn raw(&self) -> i32 {
        self.0
    }
}

/// Corresponds to struct file_operations in Linux, plus any filesystem-specific data.
pub trait FileObject: Deref<Target = FileCommon> {
    /// Read from the file without an offset. If your file is seekable, consider implementing this
    /// with fd_impl_seekable.
    fn read(&self, task: &Task, data: &[iovec_t]) -> Result<usize, Errno>;
    /// Read from the file at an offset. If your file is seekable, consider implementing this with
    /// fd_impl_nonseekable!.
    fn read_at(&self, _task: &Task, _offset: usize, _data: &[iovec_t]) -> Result<usize, Errno>;
    /// Write to the file without an offset. If your file is seekable, consider implementing this
    /// with fd_impl_seekable!.
    fn write(&self, task: &Task, data: &[iovec_t]) -> Result<usize, Errno>;
    /// Write to the file at a offset. If your file is nonseekable, consider implementing this with
    /// fd_impl_nonseekable!.
    fn write_at(&self, _task: &Task, _offset: usize, data: &[iovec_t]) -> Result<usize, Errno>;

    /// Responds to an mmap call by returning a VMO. At least the requested protection flags must
    /// be set on the VMO. Reading or writing the VMO must read or write the file. If this is not
    /// possible given the requested protection, an error must be returned.
    fn get_vmo(&self, _task: &Task, _prot: zx::VmarFlags, _flags: u32) -> Result<zx::Vmo, Errno> {
        Err(ENODEV)
    }

    // TODO(tbodt): This is actually an operation of the filesystem and not the file descriptor: if
    // you open a device file, fstat will go to the filesystem, not to the device. It's only here
    // because we don't have such a thing yet. Will need to be moved.
    fn fstat(&self, task: &Task) -> Result<stat_t, Errno>;

    fn ioctl(
        &self,
        task: &Task,
        request: u32,
        in_addr: UserAddress,
        out_addr: UserAddress,
    ) -> Result<SyscallResult, Errno> {
        self.deref().ioctl(task, request, in_addr, out_addr)
    }
}

/// Implements FileDesc methods in a way that makes sense for nonseekable files. You must implement
/// read and write.
#[macro_export]
macro_rules! fd_impl_nonseekable {
    () => {
        fn read_at(&self, _task: &Task, _offset: usize, _data: &[iovec_t]) -> Result<usize, Errno> {
            Err(ESPIPE)
        }
        fn write_at(
            &self,
            _task: &Task,
            _offset: usize,
            _data: &[iovec_t],
        ) -> Result<usize, Errno> {
            Err(ESPIPE)
        }
    };
}

/// Implements FileDesc methods in a way that makes sense for seekable files. You must implement
/// read_at and write_at.
#[macro_export]
macro_rules! fd_impl_seekable {
    () => {
        fn read(&self, task: &Task, data: &[iovec_t]) -> Result<usize, Errno> {
            let mut offset = self.offset.lock();
            let size = self.read_at(task, *offset, data)?;
            *offset += size;
            Ok(size)
        }
        fn write(&self, task: &Task, data: &[iovec_t]) -> Result<usize, Errno> {
            let mut offset = self.offset.lock();
            let size = self.write_at(task, *offset, data)?;
            *offset += size;
            Ok(size)
        }
    };
}

/// Corresponds to struct file in Linux.
#[derive(Default)]
pub struct FileCommon {
    pub offset: Mutex<usize>,
    pub async_owner: Mutex<pid_t>,
}

impl FileCommon {
    /// Get the async owner of this file.
    ///
    /// See fcntl(F_GETOWN)
    pub fn get_async_owner(&self) -> pid_t {
        *self.async_owner.lock()
    }

    /// Set the async owner of this file.
    ///
    /// See fcntl(F_SETOWN)
    pub fn set_async_owner(&self, owner: pid_t) {
        *self.async_owner.lock() = owner;
    }

    pub fn ioctl(
        &self,
        _task: &Task,
        request: u32,
        _in_addr: UserAddress,
        _out_addr: UserAddress,
    ) -> Result<SyscallResult, Errno> {
        not_implemented!("ioctl: request=0x{:x}", request);
        Err(ENOTTY)
    }
}

pub type FileHandle = Arc<dyn FileObject + Send + Sync>;

bitflags! {
    pub struct FdFlags: u32 {
        const CLOEXEC = FD_CLOEXEC;
    }
}

struct FdTableEntry {
    file: FileHandle,

    // Rather than using a separate "flags" field, we could maintain this data
    // as a bitfield over the file descriptors because there is only one flag
    // currently (CLOEXEC) and file descriptor numbers tend to cluster near 0.
    flags: FdFlags,
}

pub struct FdTable {
    table: RwLock<HashMap<FdNumber, FdTableEntry>>,
}

impl FdTable {
    pub fn new() -> FdTable {
        FdTable { table: RwLock::new(HashMap::new()) }
    }

    pub fn install_fd(&self, file: FileHandle) -> Result<FdNumber, Errno> {
        let mut table = self.table.write();
        let mut fd = FdNumber::from_raw(0);
        while table.contains_key(&fd) {
            fd = FdNumber::from_raw(fd.raw() + 1);
        }
        table.insert(fd, FdTableEntry { file, flags: FdFlags::empty() });
        Ok(fd)
    }

    pub fn get(&self, fd: FdNumber) -> Result<FileHandle, Errno> {
        let table = self.table.read();
        table.get(&fd).map(|entry| entry.file.clone()).ok_or_else(|| EBADF)
    }

    pub fn get_flags(&self, fd: FdNumber) -> Result<FdFlags, Errno> {
        let table = self.table.read();
        table.get(&fd).map(|entry| entry.flags).ok_or_else(|| EBADF)
    }

    pub fn set_flags(&self, fd: FdNumber, flags: FdFlags) -> Result<(), Errno> {
        let mut table = self.table.write();
        table
            .get_mut(&fd)
            .map(|entry| {
                entry.flags = flags;
            })
            .ok_or_else(|| EBADF)
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use crate::fs::SyslogFile;

    #[test]
    fn test_fd_table_install() {
        let table = FdTable::new();
        let test_file = SyslogFile::new();

        let fd_num = table.install_fd(test_file.clone()).unwrap();
        assert_eq!(fd_num.raw(), 0);
        let fd_num2 = table.install_fd(test_file.clone()).unwrap();
        assert_eq!(fd_num2.raw(), 1);

        assert!(Arc::ptr_eq(&table.get(fd_num).unwrap(), &test_file));
        assert!(Arc::ptr_eq(&table.get(fd_num2).unwrap(), &test_file));
        assert_eq!(table.get(FdNumber::from_raw(fd_num2.raw() + 1)).map(|_| ()), Err(EBADF));
    }
}
