use std::sync::Arc;
use std::thread;
use crate::application::app_error::AppError;
use crate::application::application::{ApplicationConfig, ApplicationInfo};
use crate::application::commands::help_command::HelpCommand;
use crate::application::commands::info_command::InfoCommand;
use crate::communication::communication_manager::{CommunicationManager, CommunicationManagerImpl};
use crate::method::method_manager::{MethodManager, MethodManagerImpl};
use crate::net::tcp_server::{TcpServer, TcpServerImpl};
pub trait ApplicationFramework {
fn get_application_port(&self) -> i16;
fn get_application_ip(&self) -> String;
fn get_application_info(&self) -> ApplicationInfo;
fn setup_method_manager(&self, method_manager: &mut Box<dyn MethodManager>);
}
pub struct Application {
pub application_framework: Box<dyn ApplicationFramework>,
pub application_config: Option<ApplicationConfig>,
pub communication_manager: Option<Box<dyn CommunicationManager + Send + Sync>>,
booted: bool,
}
pub trait BootApplication {
fn boot(&mut self) -> Result<(), AppError>;
fn run(&self) -> Result<(), AppError>;
fn multi_run(self, thread_count: i32) -> Result<(), AppError>;
}
impl BootApplication for Application {
fn boot(&mut self) -> Result<(), AppError> {
if self.booted {
return Err(AppError::new(None, String::from("Application is already booted!")));
}
if self.application_config.is_none() {
self.build_application_config();
}
if self.communication_manager.is_none() {
self.build_communication_manager()?;
}
self.communication_manager.as_mut().unwrap().run();
self.booted = true;
Ok(())
}
fn run(&self) -> Result<(), AppError> {
let communication_manager = self.communication_manager.as_ref().unwrap();
loop {
let handle_result = communication_manager.handle_client();
if handle_result.is_err() {
let error = handle_result.err().unwrap();
let message = error.to_string().clone();
return Err(AppError::new(Some(Box::new(error)), message));
}
}
}
fn multi_run(self, thread_count: i32) -> Result<(), AppError> {
let mut threads = vec![];
let arc_self = Arc::new(self);
for _ in 0..thread_count {
let thread_app = arc_self.clone();
threads.push(thread::spawn(move || {
let run = thread_app.run();
if run.is_err() {
println!("Thread errored: {:?}", run.err().unwrap());
return;
}
}));
}
for thread in threads {
if thread.join().is_err() {
println!("Could not join thread")
}
}
Ok(())
}
}
impl Application {
pub fn new(application_framework: Box<dyn ApplicationFramework>) -> Self {
Self {
application_framework,
booted: false,
application_config: None,
communication_manager: None,
}
}
fn build_application_config(&mut self) {
self.application_config = Some(ApplicationConfig {
app_info: self.application_framework.get_application_info(),
ip: self.application_framework.get_application_ip(),
port: self.application_framework.get_application_port(),
});
}
fn build_communication_manager(&mut self) -> Result<(), AppError> {
self.communication_manager = Some(Box::new(CommunicationManagerImpl::new(
self.build_server()?,
self.build_method_manager()?,
)));
Ok(())
}
fn build_server(&mut self) -> Result<Box<dyn TcpServer>, AppError> {
let config = &self.application_config.as_ref().unwrap();
let server: Box<dyn TcpServer> = Box::new(TcpServerImpl::new(
config.port,
Some(config.ip.clone()),
));
Ok(server)
}
fn build_method_manager(&mut self) -> Result<Box<dyn MethodManager>, AppError> {
let mut method_manager: Box<dyn MethodManager> = Box::new(MethodManagerImpl::new());
InfoCommand::self_register(&mut method_manager, self.application_config.clone().unwrap());
self.application_framework.as_ref().setup_method_manager(&mut method_manager);
HelpCommand::self_register(&mut method_manager);
Ok(method_manager)
}
}
unsafe impl Send for Application {}
unsafe impl Sync for Application {}