use std::ops::Deref;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use tokio::sync::RwLock;
use crate::core::base_structs::SessionsManager;
use crate::core::ClientBuilder;
use crate::core::subtypes::BotAuthToken;
use crate::core::traits::Sender;
use crate::core::voiceflow::{State, VoiceflowClient};
pub struct ClientBase<H: Sender> {
client_id: String,
voiceflow_client: Arc<VoiceflowClient>,
sessions: SessionsManager,
sender: H,
launch_state: State,
status: Arc<AtomicBool>,
bot_auth_token: Arc<RwLock<Option<BotAuthToken>>>,
}
impl<H: Sender> ClientBase<H> {
pub fn new(builder: ClientBuilder, sender: H) -> Self{
let client_id = builder.client_id().clone();
let voiceflow_client = builder.voiceflow_client().clone();
let session_duration = builder.session_duration();
let sessions_cleanup_interval = builder.sessions_cleanup_interval();
let launch_state = builder.launch_state().clone();
let status = builder.status();
let secret_auth_token = builder.bot_auth_token().clone();
let sessions= builder.sessions();
Self{
client_id,
voiceflow_client,
sessions: SessionsManager::new(sessions, session_duration, sessions_cleanup_interval),
sender,
launch_state,
status: Arc::new(AtomicBool::new(status)),
bot_auth_token: Arc::new(RwLock::new(
if let Some(token) = secret_auth_token{
Some(BotAuthToken::new(token))
}
else{
None
}
))
}
}
pub fn client_id(&self) -> &String {
&self.client_id
}
pub fn sessions(&self) -> &SessionsManager {
&self.sessions
}
pub fn voiceflow_client(&self) -> &Arc<VoiceflowClient> {
&self.voiceflow_client
}
pub fn sender(&self) -> &H {
&self.sender
}
pub fn launch_state(&self) -> &State {
&self.launch_state
}
pub fn is_active(&self) -> bool {
self.status.load(Ordering::SeqCst)
}
pub fn activate(&self) {
self.status.store(true, Ordering::SeqCst);
if let Some(interval) = self.sessions.cleanup_interval() {
self.sessions.start_cleanup(interval);
}
}
pub fn deactivate(&self) {
self.status.store(false, Ordering::SeqCst);
self.sessions.stop_cleanup();
}
pub async fn bot_auth_token(&self) -> Option<BotAuthToken> {
let read = self.bot_auth_token.read().await;
read.deref().clone()
}
pub async fn change_bot_auth_token(&self, token: Option<String>) {
let bot_auth_token = token.map(BotAuthToken::new);
let mut write = self.bot_auth_token.write().await;
*write = bot_auth_token;
}
pub async fn destructure_to_client_builder_without_sessions(&self) -> ClientBuilder{
let client_id = self.client_id.clone();
let api_key = self.sender.api_key().clone();
let voiceflow_client = self.voiceflow_client.clone();
let max_connections_per_moment = self.sender.http_client().max_connections_per_moment();
let connection_duration = self.sender.http_client().connection_duration();
let launch_state = self.launch_state.clone();
let status = self.is_active();
let token = self.bot_auth_token().await.map(|token| token.token().clone());
let mut builder = ClientBuilder::new(client_id, api_key, voiceflow_client, max_connections_per_moment)
.set_connection_duration(connection_duration)
.set_launch_state(launch_state)
.set_status(status);
builder = if let Some(interval) = self.sessions.cleanup_interval(){
builder.allow_sessions_cleaning(interval)
}
else {
builder
};
builder = if let Some(token) = token{
builder.set_bot_auth_token(token)
}
else {
builder
};
if let Some(duration) = self.sessions.valid_session_duration(){
builder.set_session_duration(duration)
}
else {
builder
}
}
}