use comemo::Tracked;
use typst_syntax::Span;

use crate::diag::SourceResult;
use crate::engine::Engine;
use crate::foundations::{Context, LocatableSelector, func};
use crate::introspection::Location;

/// Determines the location of an element in the document.
///
/// Takes a selector that must match exactly one element and returns that
/// element's @location. This location can, in particular, be used to retrieve
/// the physical @location.page[`page`] number and
/// @location.position[`position`] (page, x, y) for that element.
///
/// = Examples <examples>
/// Locating a specific element:
///
/// ```example
/// #context [
///   Introduction is at: \
///   #locate(<intro>).position()
/// ]
///
/// = Introduction <intro>
/// ```
#[func(contextual)]
pub fn locate(
    engine: &mut Engine,
    context: Tracked<Context>,
    span: Span,
    /// A selector that should match exactly one element. This element will be
    /// located.
    ///
    /// Especially useful in combination with
    /// - @here to locate the current context,
    /// - a @location retrieved from some queried element via the
    ///   @content.location[`location()`] method on content.
    selector: LocatableSelector,
) -> SourceResult<Location> {
    selector.resolve_unique(engine, context, span)
}
