use anyhow::{bail, Ok, Result};
use async_trait::async_trait;
use std::sync::Arc;
use std::{collections::HashMap, path::PathBuf};
use tokio::sync::RwLock;
use crate::feature::FeatureManager;
use crate::generated::{Config, GetConfigResponse, UpdateConfigRequest, UpdateConfigResponse};
use crate::{
config::ConfigManager,
generated::{
Feature, FeatureUsecase, GetFeatureStatusRequest, GetFeatureStatusResponse,
GetFeaturesResponse, ToggleFeatureRequest, ToggleFeatureResponse,
},
};
pub mod wp;
pub use wp::WallpaperUsecaseImpl;
pub mod sshpm;
pub use sshpm::SshpmUsecaseImpl;
#[cfg(target_os = "windows")]
pub mod wslpf;
#[cfg(target_os = "windows")]
pub use wslpf::WslpfUsecaseImpl;
#[derive(Clone)]
pub struct FeatureUsecaseImpl {
cfg_mngr: Arc<dyn ConfigManager<serde_json::Value>>,
}
impl FeatureUsecaseImpl {
pub fn new(cfg_mngr: Arc<dyn ConfigManager<serde_json::Value>>) -> Self {
FeatureUsecaseImpl { cfg_mngr }
}
}
#[async_trait]
impl FeatureUsecase for FeatureUsecaseImpl {
async fn toggle_feature(&self, request: ToggleFeatureRequest) -> Result<ToggleFeatureResponse> {
let config_opt = self.cfg_mngr.get().await?;
if config_opt.is_none() {
bail!("configuration is not ready");
}
let mut config: serde_json::Value = config_opt.unwrap();
let new_status = match config.as_object_mut() {
Some(co) => {
match co.get_mut("features") {
Some(ft) => {
match ft.get_mut(&request.feature) {
Some(f) => {
match f.get_mut("status") {
Some(old_status) => {
if let Some(old_status) = old_status.as_bool() {
let new_status: bool = !old_status;
f.as_object_mut().unwrap().insert(
"status".to_string(),
serde_json::Value::Bool(new_status),
);
new_status
} else {
f.as_object_mut().unwrap().insert(
"status".to_string(),
serde_json::Value::Bool(true),
);
true
}
}
None => {
f.as_object_mut().unwrap().insert(
"status".to_string(),
serde_json::Value::Bool(true),
);
true
}
}
}
None => {
let mut map = serde_json::Map::new();
map.insert("status".into(), serde_json::Value::Bool(true));
ft.as_object_mut().unwrap().insert(
request.feature.clone(),
serde_json::Value::Object(map),
);
true
}
}
}
None => {
let mut map = serde_json::Map::new();
map.insert("status".into(), serde_json::Value::Bool(true));
let mut fmap = serde_json::Map::new();
fmap.insert(request.feature.clone(), serde_json::Value::Object(map));
co.insert("features".to_string(), serde_json::Value::Object(fmap));
true
}
}
}
None => {
let mut map = serde_json::Map::new();
map.insert("status".into(), serde_json::Value::Bool(true));
let mut fmap = serde_json::Map::new();
fmap.insert(request.feature.clone(), serde_json::Value::Object(map));
let mut co = serde_json::Map::new();
co.insert("features".to_string(), serde_json::Value::Object(fmap));
config = serde_json::Value::Object(co);
true
}
};
self.cfg_mngr.update(config.clone()).await?;
Ok(ToggleFeatureResponse { status: new_status })
}
async fn get_features(&self) -> Result<GetFeaturesResponse> {
let config_opt = self.cfg_mngr.get().await?;
if config_opt.is_none() {
bail!("configuration is not ready");
}
let config: serde_json::Value = config_opt.unwrap();
let features = serde_json::from_value(config.get("features").unwrap().clone())?;
Ok(GetFeaturesResponse { features })
}
async fn get_feature_status(
&self,
request: GetFeatureStatusRequest,
) -> Result<GetFeatureStatusResponse> {
let config_opt = self.cfg_mngr.get().await?;
if config_opt.is_none() {
bail!("configuration is not ready");
}
let config: serde_json::Value = config_opt.unwrap();
match config.get("features") {
Some(ft) => match ft.get(&request.feature) {
Some(f) => match f.get("status") {
Some(status) => match status.as_bool() {
Some(status) => Ok(GetFeatureStatusResponse { status }),
None => Ok(GetFeatureStatusResponse { status: false }),
},
None => Ok(GetFeatureStatusResponse { status: false }),
},
None => Ok(GetFeatureStatusResponse { status: false }),
},
None => Ok(GetFeatureStatusResponse { status: false }),
}
}
async fn update_config(&self, request: UpdateConfigRequest) -> Result<UpdateConfigResponse> {
let config_opt = self.cfg_mngr.get().await?;
if config_opt.is_none() {
bail!("configuration is not ready");
}
let config = serde_json::to_value(request.config)?;
self.cfg_mngr.update(config.clone()).await?;
let config: serde_json::Value = config_opt.unwrap();
Ok(UpdateConfigResponse {
config: serde_json::from_value(config)?,
})
}
async fn get_config(&self) -> Result<GetConfigResponse> {
let config_opt = self.cfg_mngr.get().await?;
if config_opt.is_none() {
bail!("configuration is not ready");
}
Ok(GetConfigResponse {
config: serde_json::from_value(config_opt.unwrap())?,
})
}
}