use std::collections::HashMap;
use std::sync::Arc;
use anyhow::Result;
use axum::extract::{Path, State};
use axum::http::StatusCode;
use axum::Json;
use dihardts_omicstools::biology::taxonomy::Taxonomy;
use serde::Deserialize;
use serde_json::{json, Value as JsonValue};
use crate::web::app_state::AppState;
use crate::web::web_error::WebError;
fn taxonomy_to_json(taxonomy: &Taxonomy, taxonomy_ranks: &HashMap<u64, String>) -> JsonValue {
json!({
"id": taxonomy.get_id(),
"parent_id": taxonomy.get_parent_id(),
"scientific_name": taxonomy.get_scientific_name(),
"rank": taxonomy_ranks.get(&taxonomy.get_rank_id()).unwrap_or(&"unknown".to_string())
})
}
pub async fn get_taxonomy(
State(app_state): State<Arc<AppState>>,
Path(id): Path<u64>,
) -> Result<Json<JsonValue>, WebError> {
let taxonomy_tree = app_state.get_taxonomy_tree_as_ref();
match taxonomy_tree.get_taxonomy(id) {
Some(taxonomy) => Ok(Json(taxonomy_to_json(taxonomy, taxonomy_tree.get_ranks()))),
None => Err(WebError::new(
StatusCode::NOT_FOUND,
format!("Could not find taxonomy with ID {}", id),
)),
}
}
pub async fn get_sub_taxonomies(
State(app_state): State<Arc<AppState>>,
Path(id): Path<u64>,
) -> Result<Json<JsonValue>, WebError> {
let taxonomy_tree = app_state.get_taxonomy_tree_as_ref();
match taxonomy_tree.get_sub_taxonomies(id) {
Some(taxonomies) => Ok(Json(
taxonomies
.iter()
.map(|taxonomy| taxonomy_to_json(taxonomy, taxonomy_tree.get_ranks()))
.collect(),
)),
None => Err(WebError::new(
StatusCode::NOT_FOUND,
format!("Could not find taxonomy with ID {}", id),
)),
}
}
#[derive(Deserialize)]
pub struct SearchRequestBody {
name_query: String,
}
impl SearchRequestBody {
pub fn get_name_query(&self) -> &str {
self.name_query.as_str()
}
}
pub async fn search_taxonomies(
State(app_state): State<Arc<AppState>>,
Json(payload): Json<SearchRequestBody>,
) -> Result<Json<Vec<JsonValue>>, WebError> {
let taxonomy_tree = app_state.get_taxonomy_tree_as_ref();
let taxonomy_search_idx = match app_state.get_taxonomy_index_as_ref() {
Some(idx) => idx,
None => {
return Err(WebError::new(
StatusCode::NOT_IMPLEMENTED,
"Taxonomy search is disable on this instance of MaCPepDB".to_string(),
))
}
};
Ok(Json(
taxonomy_search_idx
.search(payload.get_name_query())
.iter()
.map(|id| {
let taxonomy = match taxonomy_tree.get_taxonomy(**id) {
Some(taxonomy) => Ok(taxonomy),
None => Err(WebError::new(
StatusCode::NOT_FOUND,
format!("Could not find taxonomy with ID {}", id),
)),
};
Ok(taxonomy_to_json(taxonomy?, taxonomy_tree.get_ranks()))
})
.collect::<Result<Vec<JsonValue>, WebError>>()?,
))
}