use jsona_util::environment::Environment;
use lsp_async_stub::{
    rpc::Error,
    util::{LspExt, Position},
    Context, Params,
};
use lsp_types::{SelectionRange, SelectionRangeParams};

use crate::{query::Query, world::World};
#[tracing::instrument(skip_all)]
pub(crate) async fn selection_ranges<E: Environment>(
    context: Context<World<E>>,
    params: Params<SelectionRangeParams>,
) -> Result<Option<Vec<SelectionRange>>, Error> {
    let p = params.required()?;

    let workspaces = context.workspaces.read().await;
    let document_uri = &p.text_document.uri;
    let (_, doc) = workspaces.try_get_document(document_uri)?;

    Ok(Some(
        p.positions
            .into_iter()
            .flat_map(|position| {
                let offset = match doc.mapper.offset(Position::from_lsp(position)) {
                    Some(ofs) => ofs,
                    None => {
                        tracing::error!(?position, "document position not found");
                        return None;
                    }
                };
                let (_, node) = Query::node_at(&doc.dom, offset)?;
                let range = node.text_range().and_then(|v| doc.mapper.range(v))?;
                Some(SelectionRange {
                    range: range.into_lsp(),
                    parent: None,
                })
            })
            .collect(),
    ))
}
