use crate::{WingmanError, WingmanResult};
use std::ops::{Deref, DerefMut};
use crate::platform::{
PlatformApplication, PlatformApplicationBuilder, PlatformApplicationRunning,
};
pub struct EventStartup {}
pub struct EventShutdown {}
pub struct EventHandled {}
pub trait ApplicationCallbacks: Sized {
type Exit: Default;
type Error: std::error::Error + From<WingmanError>;
fn on_startup(
this: &mut ApplicationRunning<Self>,
event: &EventStartup,
) -> Result<(), Self::Error> {
Ok(())
}
fn on_events_handled(
this: &mut ApplicationRunning<Self>,
event: &EventHandled,
) -> Result<(), Self::Error> {
this.shutdown().map_err(Into::into)
}
fn on_shutdown(
this: &mut ApplicationRunning<Self>,
event: &EventShutdown,
) -> Result<Self::Exit, Self::Error> {
Ok(Default::default())
}
}
impl ApplicationCallbacks for () {
type Exit = ();
type Error = WingmanError;
}
pub struct ApplicationBuilder<C: ApplicationCallbacks = ()> {
platform: crate::platform::ApplicationBuilder<C>,
}
impl ApplicationBuilder {
fn new() -> Self {
Self {
platform: crate::platform::ApplicationBuilder::new(Default::default()),
}
}
}
impl Default for ApplicationBuilder {
fn default() -> Self {
Self::new()
}
}
impl<C: ApplicationCallbacks> ApplicationBuilder<C> {
pub fn with_callbacks<D: ApplicationCallbacks>(self, callbacks: D) -> ApplicationBuilder<D> {
ApplicationBuilder {
platform: self.platform.with_callbacks(callbacks),
}
}
pub fn build(self) -> WingmanResult<Application<C>> {
Ok(Application {
platform: self.platform.build()?,
})
}
}
pub struct Application<C: ApplicationCallbacks> {
platform: crate::platform::Application<C>,
}
impl Application<()> {
fn builder() -> ApplicationBuilder {
ApplicationBuilder::new()
}
}
pub fn application() -> ApplicationBuilder {
ApplicationBuilder::new()
}
impl<C: ApplicationCallbacks> Application<C> {
pub fn run(self) -> Result<C::Exit, C::Error> {
self.platform.run()
}
}
pub struct ApplicationRunning<C: ApplicationCallbacks> {
pub(crate) platform: crate::platform::ApplicationRunning<C>,
}
impl<C: ApplicationCallbacks> ApplicationRunning<C> {
pub fn shutdown(&mut self) -> WingmanResult<()> {
self.platform.shutdown()
}
pub fn wait_for_events(&mut self) -> WingmanResult<()> {
self.platform.wait_for_events()
}
pub fn wait_for_events_timeout(&mut self, timeout: std::time::Duration) -> WingmanResult<bool> {
self.platform.wait_for_events_timeout(timeout)
}
}
impl<C: ApplicationCallbacks> Deref for ApplicationRunning<C> {
type Target = C;
fn deref(&self) -> &Self::Target {
self.platform.callbacks()
}
}
impl<C: ApplicationCallbacks> DerefMut for ApplicationRunning<C> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.platform.callbacks_mut()
}
}