use std::sync::Arc;
use tokio::sync::broadcast;
use crate::audit::helper::AuditHelper;
use crate::audit::AuditEventSender;
use crate::command_sender::CommandSender;
use crate::config::Settings;
use crate::ipc::server::IpcServer;
use crate::state::SharedState;
use super::events::CoreEvent;
const EVENT_CHANNEL_CAPACITY: usize = 256;
pub struct TmaiCore {
state: SharedState,
command_sender: Option<Arc<CommandSender>>,
settings: Arc<Settings>,
ipc_server: Option<Arc<IpcServer>>,
event_tx: broadcast::Sender<CoreEvent>,
audit_helper: AuditHelper,
}
impl TmaiCore {
pub(crate) fn new(
state: SharedState,
command_sender: Option<Arc<CommandSender>>,
settings: Arc<Settings>,
ipc_server: Option<Arc<IpcServer>>,
audit_tx: Option<AuditEventSender>,
) -> Self {
let (event_tx, _) = broadcast::channel(EVENT_CHANNEL_CAPACITY);
let audit_helper = AuditHelper::new(audit_tx, state.clone());
Self {
state,
command_sender,
settings,
ipc_server,
event_tx,
audit_helper,
}
}
#[deprecated(note = "Use TmaiCore query/action methods instead of direct state access")]
pub fn raw_state(&self) -> &SharedState {
&self.state
}
#[deprecated(note = "Use TmaiCore action methods instead of direct CommandSender access")]
pub fn raw_command_sender(&self) -> Option<&Arc<CommandSender>> {
self.command_sender.as_ref()
}
pub fn settings(&self) -> &Settings {
&self.settings
}
pub fn ipc_server(&self) -> Option<&Arc<IpcServer>> {
self.ipc_server.as_ref()
}
pub fn event_sender(&self) -> broadcast::Sender<CoreEvent> {
self.event_tx.clone()
}
pub(crate) fn state(&self) -> &SharedState {
&self.state
}
pub(crate) fn command_sender_ref(&self) -> Option<&Arc<CommandSender>> {
self.command_sender.as_ref()
}
pub(crate) fn audit_helper(&self) -> &AuditHelper {
&self.audit_helper
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::state::AppState;
#[test]
fn test_tmai_core_creation() {
let state = AppState::shared();
let settings = Arc::new(Settings::default());
let core = TmaiCore::new(state, None, settings.clone(), None, None);
assert_eq!(core.settings().poll_interval_ms, 500);
assert!(core.ipc_server().is_none());
assert!(core.command_sender_ref().is_none());
}
#[test]
#[allow(deprecated)]
fn test_escape_hatches() {
let state = AppState::shared();
let settings = Arc::new(Settings::default());
let core = TmaiCore::new(state.clone(), None, settings, None, None);
let raw = core.raw_state();
assert!(Arc::ptr_eq(raw, &state));
assert!(core.raw_command_sender().is_none());
}
}