use std::collections::BTreeSet;
use serde_json::{Value, json};
use super::{Hosted, Out, Refused, Route, Social, no_items, spellings};
const MINIDOC: Route = Route {
nsid: "blue.microcosm.identity.resolveMiniDoc",
source: "$arg_identifier",
var: "$ks_soc_doc",
miss: "not_found",
empty: None,
refused: &[],
ignored: &[],
};
const PROFILE: Route = Route {
nsid: "org.tangled.actor.getProfile",
source: "$arg_actor",
var: "$ks_soc_profile",
miss: "not_found",
empty: None,
refused: &[],
ignored: &[],
};
const PROFILES: Route = Route {
nsid: "org.tangled.actor.getProfiles",
source: "$arg_actors",
var: "$ks_soc_profiles",
miss: "invalid_request",
empty: Some(no_items),
refused: &[Refused::Distinct("actors")],
ignored: &[],
};
const KEYS: Route = Route {
nsid: "org.tangled.publicKey.listKeys",
source: "$arg_subject$arg_actor",
var: "$ks_soc_keys",
miss: "invalid_request",
empty: Some(no_items),
refused: &[],
ignored: &["cursor", "limit", "offset", "order"],
};
pub(super) const ROUTES: &[Route] = &[MINIDOC, PROFILE, PROFILES, KEYS];
/// every known account gets an answer, its cached profile record or a stub
pub(super) fn emit(out: &mut Out, hosted: &[Hosted], social: &Social) -> anyhow::Result<()> {
let accounts: BTreeSet<&str> = hosted
.iter()
.flat_map(Hosted::accounts)
.chain(social.owner.as_deref())
.chain(social.handles.keys().map(String::as_str))
.collect();
for did in accounts {
let handle = social.handles.get(did);
let mut names = spellings(did);
names.extend(
handle
.iter()
.flat_map(|handle| spellings(&handle.to_lowercase())),
);
out.answer(&MINIDOC, names.clone(), &social.doc(did))?;
let uri = format!("at://{did}/org.tangled.actor.profile/self");
let mut value = Value::Object(social.profiles.get(did).cloned().unwrap_or_default());
value["$type"] = json!("org.tangled.actor.profile");
if let Some(avatar) = social.avatars.get(did) {
value["avatar"] = avatar.blob();
}
let profile = json!({ "uri": uri, "value": value });
let mut actors = names;
actors.extend(spellings(&uri));
out.answer(&PROFILE, actors.clone(), &profile)?;
out.answer(&PROFILES, actors, &json!({ "items": [profile] }))?;
}
Ok(())
}