use std::error::Error;
use std::sync::{Arc, RwLock};
use objc::runtime::{Object, BOOL};
use objc::{class, msg_send, sel, sel_impl};
use objc_id::Id;
use url::Url;
use crate::error::Error as AppKitError;
use crate::filesystem::enums::{SearchPathDirectory, SearchPathDomainMask};
use crate::foundation::{id, nil, NSString, NSUInteger, NO};
#[derive(Clone, Debug)]
pub struct FileManager(pub Arc<RwLock<Id<Object>>>);
impl Default for FileManager {
fn default() -> Self {
FileManager(Arc::new(RwLock::new(unsafe {
let manager: id = msg_send![class!(NSFileManager), defaultManager];
Id::from_ptr(manager)
})))
}
}
impl FileManager {
pub fn new() -> Self {
FileManager(Arc::new(RwLock::new(unsafe {
let manager: id = msg_send![class!(NSFileManager), new];
Id::from_ptr(manager)
})))
}
pub fn get_directory(&self, directory: SearchPathDirectory, in_domain: SearchPathDomainMask) -> Result<Url, Box<dyn Error>> {
let dir: NSUInteger = directory.into();
let mask: NSUInteger = in_domain.into();
let directory = unsafe {
let manager = self.0.read().unwrap();
let dir: id = msg_send![&**manager, URLForDirectory:dir
inDomain:mask
appropriateForURL:nil
create:NO
error:nil];
NSString::retain(msg_send![dir, absoluteString])
};
Url::parse(directory.to_str()).map_err(|e| e.into())
}
pub fn move_item(&self, from: Url, to: Url) -> Result<(), Box<dyn Error>> {
let from = NSString::new(from.as_str());
let to = NSString::new(to.as_str());
unsafe {
let from_url: id = msg_send![class!(NSURL), URLWithString:&*from];
let to_url: id = msg_send![class!(NSURL), URLWithString:&*to];
let manager = self.0.read().unwrap();
let error: id = nil;
let result: BOOL = msg_send![&**manager, moveItemAtURL:from_url toURL:to_url error:&error];
if result == NO {
return Err(AppKitError::new(error).into());
}
}
Ok(())
}
}