use std::net::IpAddr;
use std::time::Duration;
use crate::Error;
use crate::auth_token_store::AuthTokenStore;
use crate::frame_tv::FrameTv;
use crate::frame_tv_impl::{FrameTvImpl, Transport};
use crate::transport::persistent_ws_transport::PersistentWsTransport;
use crate::transport::rest_client::RestClient;
use crate::transport::tls_config;
use crate::transport::ws_transport::WsTransport;
const DEFAULT_TIMEOUT: Duration = Duration::from_secs(5);
pub struct FrameTvConnectionBuilder<S: AuthTokenStore = NoAuthTokenStore> {
host: IpAddr,
auth_token_store: S,
connection_timeout: Duration,
persistent: bool,
}
impl FrameTv {
pub fn connection_builder(host: IpAddr) -> FrameTvConnectionBuilder<NoAuthTokenStore> {
FrameTvConnectionBuilder {
host,
auth_token_store: NoAuthTokenStore,
connection_timeout: DEFAULT_TIMEOUT,
persistent: false,
}
}
}
impl<S: AuthTokenStore> FrameTvConnectionBuilder<S> {
pub fn connection_timeout(mut self, timeout: Duration) -> Self {
self.connection_timeout = timeout;
self
}
pub fn persistent(mut self) -> Self {
self.persistent = true;
self
}
pub async fn connect(self) -> Result<FrameTv, Error> {
let token = self
.auth_token_store
.load_token()
.await
.map_err(Error::AuthTokenStore)?;
let transport = if self.persistent {
let t =
PersistentWsTransport::connect(self.host, token, self.connection_timeout).await?;
if let Some(new_token) = t.get_token().await {
self.auth_token_store
.save_token(&new_token)
.await
.map_err(Error::AuthTokenStore)?;
}
Transport::Persistent(Box::new(t))
} else {
let t = WsTransport::connect(self.host, token, self.connection_timeout).await?;
if let Some(new_token) = t.get_token().await {
self.auth_token_store
.save_token(&new_token)
.await
.map_err(Error::AuthTokenStore)?;
}
Transport::OneShot(t)
};
let rest_client = RestClient::new(self.host, tls_config::make_reqwest_client());
Ok(FrameTv(FrameTvImpl {
transport,
rest_client,
}))
}
}
impl FrameTvConnectionBuilder<NoAuthTokenStore> {
pub fn auth_token_store<S: AuthTokenStore>(self, store: S) -> FrameTvConnectionBuilder<S> {
FrameTvConnectionBuilder {
host: self.host,
auth_token_store: store,
connection_timeout: self.connection_timeout,
persistent: self.persistent,
}
}
}
pub struct NoAuthTokenStore;
impl AuthTokenStore for NoAuthTokenStore {
async fn load_token(&self) -> Result<Option<String>, Box<dyn std::error::Error + Send + Sync>> {
Ok(None)
}
async fn save_token(
&self,
_token: &str,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
Ok(())
}
}