/**
 * Tool Context Types
 *
 * Defines the context types passed to tools for making visibility and behavior decisions.
 * Each context level provides increasingly specific information about where the tool is being used.
 */
/**
 * Type guard to check if context is at assessment level
 */
export function isAssessmentContext(context) {
    return context.level === "assessment";
}
/**
 * Type guard to check if context is at section level
 */
export function isSectionContext(context) {
    return context.level === "section";
}
/**
 * Type guard to check if context is at item level
 */
export function isItemContext(context) {
    return context.level === "item";
}
/**
 * Type guard to check if context is at passage level
 */
export function isPassageContext(context) {
    return context.level === "passage";
}
/**
 * Type guard to check if context is at rubric level
 */
export function isRubricContext(context) {
    return context.level === "rubric";
}
/**
 * Type guard to check if context is at element level
 */
export function isElementContext(context) {
    return context.level === "element";
}
/**
 * Helper to extract text content from an item or element for analysis
 */
export function extractTextContent(context) {
    if (isElementContext(context)) {
        const config = context.item.config;
        if (!config)
            return "";
        const textChunks = [];
        const stripHtml = (value) => value.replace(/<[^>]*>/g, " ").trim();
        // Try to find element markup by element id.
        const elementMarkup = config.elements?.[context.elementId];
        if (elementMarkup) {
            if (typeof elementMarkup === "string") {
                textChunks.push(stripHtml(elementMarkup));
            }
        }
        // Also inspect model data keyed by this element id.
        // In many items, math appears in model.prompt/labels rather than elements[elementId].
        const modelsRaw = config.models;
        const models = Array.isArray(modelsRaw)
            ? modelsRaw
            : modelsRaw && typeof modelsRaw === "object"
                ? Object.values(modelsRaw)
                : [];
        const model = models.find((m) => m && typeof m === "object" && m.id === context.elementId);
        if (model) {
            for (const value of Object.values(model)) {
                if (typeof value === "string") {
                    textChunks.push(stripHtml(value));
                }
                if (Array.isArray(value)) {
                    for (const entry of value) {
                        if (entry && typeof entry === "object") {
                            for (const nested of Object.values(entry)) {
                                if (typeof nested === "string") {
                                    textChunks.push(stripHtml(nested));
                                }
                            }
                        }
                    }
                }
            }
        }
        return textChunks.filter(Boolean).join(" ").trim();
    }
    if (isItemContext(context)) {
        const item = context.item;
        if (!item?.config)
            return "";
        const config = item.config;
        const textChunks = [];
        const stripHtml = (value) => value.replace(/<[^>]*>/g, " ").trim();
        // Primary item markup
        if (typeof config.markup === "string") {
            textChunks.push(stripHtml(config.markup));
        }
        // Element markup snippets
        const elements = config.elements;
        if (elements && typeof elements === "object") {
            for (const elementMarkup of Object.values(elements)) {
                if (typeof elementMarkup === "string") {
                    textChunks.push(stripHtml(elementMarkup));
                }
            }
        }
        // Model-level text (prompts, labels, etc.)
        const modelsRaw = config.models;
        const models = Array.isArray(modelsRaw)
            ? modelsRaw
            : modelsRaw && typeof modelsRaw === "object"
                ? Object.values(modelsRaw)
                : [];
        for (const model of models) {
            if (!model || typeof model !== "object")
                continue;
            for (const value of Object.values(model)) {
                if (typeof value === "string") {
                    textChunks.push(stripHtml(value));
                }
                if (Array.isArray(value)) {
                    for (const entry of value) {
                        if (entry && typeof entry === "object") {
                            for (const nested of Object.values(entry)) {
                                if (typeof nested === "string") {
                                    textChunks.push(stripHtml(nested));
                                }
                            }
                        }
                    }
                }
            }
        }
        return textChunks.filter(Boolean).join(" ").trim();
    }
    if (isPassageContext(context)) {
        const passage = context.passage;
        if (!passage?.config)
            return "";
        const config = passage.config;
        const textChunks = [];
        const stripHtml = (value) => value.replace(/<[^>]*>/g, " ").trim();
        // Primary passage markup/content
        if (typeof config.markup === "string") {
            textChunks.push(stripHtml(config.markup));
        }
        if (typeof config.content === "string") {
            textChunks.push(stripHtml(config.content));
        }
        if (typeof config.prompt === "string") {
            textChunks.push(stripHtml(config.prompt));
        }
        // Element markup snippets
        const elements = config.elements;
        if (elements && typeof elements === "object") {
            for (const elementMarkup of Object.values(elements)) {
                if (typeof elementMarkup === "string") {
                    textChunks.push(stripHtml(elementMarkup));
                }
            }
        }
        // Model-level text (prompts, labels, etc.)
        const modelsRaw = config.models;
        const models = Array.isArray(modelsRaw)
            ? modelsRaw
            : modelsRaw && typeof modelsRaw === "object"
                ? Object.values(modelsRaw)
                : [];
        for (const model of models) {
            if (!model || typeof model !== "object")
                continue;
            for (const value of Object.values(model)) {
                if (typeof value === "string") {
                    textChunks.push(stripHtml(value));
                }
                if (Array.isArray(value)) {
                    for (const entry of value) {
                        if (entry && typeof entry === "object") {
                            for (const nested of Object.values(entry)) {
                                if (typeof nested === "string") {
                                    textChunks.push(stripHtml(nested));
                                }
                            }
                        }
                    }
                }
            }
        }
        return textChunks.filter(Boolean).join(" ").trim();
    }
    if (isRubricContext(context)) {
        const rubric = context.rubricBlock;
        // If rubric has embedded passage, extract from passage config
        if (rubric.passage?.config) {
            const markup = rubric.passage.config.markup || "";
            return markup.replace(/<[^>]*>/g, " ").trim();
        }
        // Otherwise, use simple content string
        const content = rubric.content || "";
        return content.replace(/<[^>]*>/g, " ").trim();
    }
    return "";
}
/**
 * Helper to check if context contains mathematical content
 * (Basic heuristic - can be overridden by tools)
 */
export function hasMathContent(context) {
    const text = extractTextContent(context);
    // Look for common math indicators
    const mathIndicators = [
        /<math[>\s]/i, // MathML
        /\\\[([^\]]+)\\\]/, // LaTeX display math
        /\$\$[^$]+\$\$/, // LaTeX display math ($$...$$)
        /\\\(/, // LaTeX inline math
        /[+\-*/=<>≤≥∑∫√π]/, // Math symbols
        /\d+\s*[+\-*/=]\s*\d+/, // Simple arithmetic
    ];
    return mathIndicators.some((pattern) => pattern.test(text));
}
/**
 * Helper to check if context contains choice-based interactions
 */
export function hasChoiceInteraction(context) {
    const interactionTypes = [
        "pie-multiple-choice",
        "pie-inline-choice",
        "pie-select-text",
        "multiple-choice",
        "inline-choice",
        "select-text",
    ];
    if (isElementContext(context)) {
        const config = context.item.config;
        if (!config?.models)
            return false;
        // Find model for this element
        const models = Array.isArray(config.models)
            ? config.models
            : Object.values(config.models);
        const model = models.find((m) => m && typeof m === "object" && m.id === context.elementId);
        if (!model)
            return false;
        const type = model.element || "";
        return interactionTypes.includes(type);
    }
    if (isItemContext(context)) {
        const modelsRaw = context.item.config?.models;
        const models = Array.isArray(modelsRaw)
            ? modelsRaw
            : modelsRaw && typeof modelsRaw === "object"
                ? Object.values(modelsRaw)
                : [];
        return models.some((m) => {
            if (!m || typeof m !== "object")
                return false;
            const type = m.element || "";
            if (interactionTypes.includes(type))
                return true;
            // Fallback for configs that don't provide canonical element names.
            return Array.isArray(m.choices) && m.choices.length > 0;
        });
    }
    return false;
}
/**
 * Helper to check if context contains text that can be read aloud
 */
export function hasReadableText(context) {
    const text = extractTextContent(context);
    // Must have at least 10 characters of text (arbitrary threshold)
    return text.trim().length >= 10;
}
/**
 * Helper to check if context contains science content
 * (Basic heuristic - can be overridden by tools)
 */
export function hasScienceContent(context) {
    const text = extractTextContent(context);
    // Look for common science indicators
    const scienceIndicators = [
        /chemistry|chemical|element|atom|molecule|compound/i,
        /periodic\s+table/i,
        /H₂O|CO₂|NaCl|O₂|N₂/i, // Chemical formulas
        /\b[A-Z][a-z]?\d*\b/, // Element symbols (H, He, Li, etc.)
        /biology|organism|cell|DNA|RNA|protein/i,
        /physics|force|energy|velocity|acceleration/i,
    ];
    return scienceIndicators.some((pattern) => pattern.test(text));
}
//# sourceMappingURL=tool-context.js.map