use std::ffi::CStr;
use std::os::raw::c_char;
use objc::runtime::Object;
use objc::{class, msg_send, sel, sel_impl};
use objc_id::Id;
use crate::foundation::{id, to_bool, NSInteger, BOOL, NO, YES};
#[derive(Debug)]
pub struct NSNumber(pub Id<Object>);
impl NSNumber {
pub fn retain(data: id) -> Self {
NSNumber(unsafe { Id::from_ptr(data) })
}
pub fn wrap(data: id) -> Self {
NSNumber(unsafe { Id::from_retained_ptr(data) })
}
pub fn bool(value: bool) -> Self {
NSNumber(unsafe {
Id::from_retained_ptr(msg_send![class!(NSNumber), numberWithBool:match value {
true => YES,
false => NO
}])
})
}
pub fn integer(value: i64) -> Self {
NSNumber(unsafe { Id::from_retained_ptr(msg_send![class!(NSNumber), numberWithInteger: value as NSInteger]) })
}
pub fn float(value: f64) -> Self {
NSNumber(unsafe { Id::from_retained_ptr(msg_send![class!(NSNumber), numberWithDouble: value]) })
}
pub fn objc_type(&self) -> &str {
unsafe {
let t: *const c_char = msg_send![&*self.0, objCType];
let slice = CStr::from_ptr(t);
slice.to_str().unwrap()
}
}
pub fn as_i64(&self) -> i64 {
unsafe {
let i: NSInteger = msg_send![&*self.0, integerValue];
i as i64
}
}
pub fn as_f64(&self) -> f64 {
unsafe { msg_send![&*self.0, doubleValue] }
}
pub fn as_bool(&self) -> bool {
let result: BOOL = unsafe { msg_send![&*self.0, boolValue] };
to_bool(result)
}
pub fn is(obj: id) -> bool {
let result: BOOL = unsafe { msg_send![obj, isKindOfClass: class!(NSNumber)] };
to_bool(result)
}
}
impl From<NSNumber> for id {
fn from(mut number: NSNumber) -> Self {
&mut *number.0
}
}