Documentation
use alloc::string::String;
use core::future::Future;
use futures::{AsyncRead, AsyncWrite};
use thiserror::Error;

use crate::{
    fs::file::File,
    runtime::{Runtime, Share},
};

/// File-related errors
#[derive(Debug, Error)]
pub enum FileError {
    #[error("file not found: {path}")]
    NotFound { path: String },

    #[error("permission denied: {path}")]
    PermissionDenied { path: String },

    #[error("file already exists: {path}")]
    AlreadyExists { path: String },

    #[error("not a directory: {path}")]
    NotADirectory { path: String },

    #[error("is a directory: {path}")]
    IsADirectory { path: String },

    #[error("I/O error: {0}")]
    Io(String),

    #[error("disk full")]
    DiskFull,

    #[error("invalid path: {path}")]
    InvalidPath { path: String },

    #[error("syscall error: {0}")]
    Syscall(#[from] crate::linux::sys::SyscallError),
}

pub type Result<T> = core::result::Result<T, FileError>;

pub mod file {
    use super::Result;
    use crate::runtime::{Runtime, Share};
    use alloc::string::String;
    use core::future::Future;
    use futures::{AsyncRead, AsyncWrite};
    use thiserror::Error;
    // File operations follow a similar pattern
    pub trait File<R: Runtime<S>, S: Share>:
        AsyncRead + AsyncWrite + Send + Sync + 'static
    {
        fn open(path: &str) -> impl Future<Output = Result<Self>>
        where
            Self: Sized;
        fn create(path: &str) -> impl Future<Output = Result<Self>>
        where
            Self: Sized;

        // File-specific operations
        fn metadata(&self) -> impl Future<Output = Result<Metadata>>;
        fn sync_all(&self) -> impl Future<Output = Result<()>>;
        fn sync_data(&self) -> impl Future<Output = Result<()>>;
        fn set_len(&self, size: u64) -> impl Future<Output = Result<()>>;
    }
    pub struct Metadata {
        pub len: u64,
        pub is_file: bool,
        pub is_dir: bool,
        pub created: Option<u64>,
        pub modified: Option<u64>,
        pub accessed: Option<u64>,
    }
}
pub trait FileSystem<R: Runtime<S>, S: Share> {
    type File: File<R, S>;

    fn read_dir(path: &str) -> impl Future<Output = Result<ReadDir<R, S>>>;
    fn create_dir(path: &str) -> impl Future<Output = Result<()>>;
    fn remove_file(path: &str) -> impl Future<Output = Result<()>>;
    fn remove_dir(path: &str) -> impl Future<Output = Result<()>>;
    fn rename(from: &str, to: &str) -> impl Future<Output = Result<()>>;
    fn metadata(path: &str) -> impl Future<Output = Result<file::Metadata>>;
}

pub struct ReadDir<R: Runtime<S>, S: Share> {
    _phantom: core::marker::PhantomData<(R, S)>,
}