use crate::reactive::{WuiBinding, WuiComputed};
use crate::{IntoFFI, WuiStr};
use alloc::vec::Vec;
use waterui_map::{Annotation, Coordinate, Location, MapConfig, MapStatus, MapStyle, Region};
use waterui_str::Str;
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct WuiCoordinate {
pub latitude: f64,
pub longitude: f64,
}
impl IntoFFI for Coordinate {
type FFI = WuiCoordinate;
fn into_ffi(self) -> Self::FFI {
WuiCoordinate {
latitude: self.latitude.get(),
longitude: self.longitude.get(),
}
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct WuiRegion {
pub center: WuiCoordinate,
pub latitude_delta: f64,
pub longitude_delta: f64,
}
impl IntoFFI for Region {
type FFI = WuiRegion;
fn into_ffi(self) -> Self::FFI {
WuiRegion {
center: self.center.into_ffi(),
latitude_delta: self.latitude_delta,
longitude_delta: self.longitude_delta,
}
}
}
#[repr(C)]
#[derive(Debug)]
pub struct WuiAnnotation {
pub coordinate: WuiCoordinate,
pub title: WuiStr,
pub subtitle: WuiStr,
}
impl IntoFFI for Annotation {
type FFI = WuiAnnotation;
fn into_ffi(self) -> Self::FFI {
WuiAnnotation {
coordinate: self.coordinate.into_ffi(),
title: self.title.into_ffi(),
subtitle: self
.subtitle
.unwrap_or_else(|| Str::from_static(""))
.into_ffi(),
}
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum WuiMapStyle {
Standard = 0,
Satellite = 1,
Hybrid = 2,
}
impl IntoFFI for MapStyle {
type FFI = WuiMapStyle;
fn into_ffi(self) -> Self::FFI {
match self {
Self::Standard => WuiMapStyle::Standard,
Self::Satellite => WuiMapStyle::Satellite,
Self::Hybrid => WuiMapStyle::Hybrid,
}
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct WuiLocation {
pub has_location: bool,
pub coordinate: WuiCoordinate,
pub altitude: f64,
pub has_altitude: bool,
pub horizontal_accuracy: f64,
pub has_horizontal_accuracy: bool,
pub timestamp_ms: i64,
}
impl IntoFFI for Option<Location> {
type FFI = WuiLocation;
fn into_ffi(self) -> Self::FFI {
let Some(location) = self else {
return WuiLocation {
has_location: false,
coordinate: WuiCoordinate {
latitude: 0.0,
longitude: 0.0,
},
altitude: 0.0,
has_altitude: false,
horizontal_accuracy: 0.0,
has_horizontal_accuracy: false,
timestamp_ms: 0,
};
};
WuiLocation {
has_location: true,
coordinate: Coordinate::from_location(&location).into_ffi(),
altitude: location.altitude().unwrap_or(0.0),
has_altitude: location.altitude().is_some(),
horizontal_accuracy: location.horizontal_accuracy().unwrap_or(0.0),
has_horizontal_accuracy: location.horizontal_accuracy().is_some(),
timestamp_ms: location.timestamp().as_millisecond(),
}
}
}
#[repr(C)]
#[derive(Debug)]
pub struct WuiMapStatus {
pub kind: WuiMapStatusKind,
pub reason: WuiStr,
}
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum WuiMapStatusKind {
Loading = 0,
Ready = 1,
Failed = 2,
}
impl crate::IntoRust for WuiMapStatus {
type Rust = MapStatus;
unsafe fn into_rust(self) -> Self::Rust {
match self.kind {
WuiMapStatusKind::Loading => MapStatus::Loading,
WuiMapStatusKind::Ready => MapStatus::Ready,
WuiMapStatusKind::Failed => MapStatus::Failed(
unsafe { crate::IntoRust::into_rust(self.reason) },
),
}
}
}
impl IntoFFI for MapStatus {
type FFI = WuiMapStatus;
fn into_ffi(self) -> Self::FFI {
match self {
Self::Loading => WuiMapStatus {
kind: WuiMapStatusKind::Loading,
reason: Str::from_static("").into_ffi(),
},
Self::Ready => WuiMapStatus {
kind: WuiMapStatusKind::Ready,
reason: Str::from_static("").into_ffi(),
},
Self::Failed(reason) => WuiMapStatus {
kind: WuiMapStatusKind::Failed,
reason: reason.into_ffi(),
},
}
}
}
#[repr(C)]
#[derive(Debug)]
pub struct WuiMap {
pub region: *mut WuiComputed<Region>,
pub annotations: *mut WuiComputed<Vec<Annotation>>,
pub style: WuiMapStyle,
pub shows_user_location: bool,
pub user_location: *mut WuiComputed<Option<Location>>,
pub status: *mut WuiBinding<MapStatus>,
pub is_interactive: bool,
pub shows_compass: bool,
pub shows_scale: bool,
}
impl IntoFFI for MapConfig {
type FFI = WuiMap;
fn into_ffi(self) -> Self::FFI {
WuiMap {
region: self.region.into_ffi(),
annotations: self.annotations.into_ffi(),
style: self.style.into_ffi(),
shows_user_location: self.user_location_visibility.is_visible(),
user_location: self
.user_location
.map_or(core::ptr::null_mut(), IntoFFI::into_ffi),
status: self
.status
.map_or(core::ptr::null_mut(), crate::IntoFFI::into_ffi),
is_interactive: self.interactivity.is_interactive(),
shows_compass: self.compass_visibility.is_visible(),
shows_scale: self.scale_visibility.is_visible(),
}
}
}
#[cfg(feature = "c-api")]
ffi_view!(MapConfig, WuiMap, map);
#[cfg(feature = "c-api")]
crate::ffi_computed!(Region, WuiRegion, region);
#[cfg(feature = "c-api")]
crate::ffi_computed!(
Vec<Annotation>,
crate::array::WuiArray<WuiAnnotation>,
annotations
);
#[cfg(feature = "c-api")]
crate::ffi_computed!(Option<Location>, WuiLocation, user_location);
#[cfg(feature = "c-api")]
crate::ffi_binding!(MapStatus, WuiMapStatus, map_status);