import { extractTypeScriptSymbols } from "./extractors/typescript.js";
import { extractPythonSymbols } from "./extractors/python.js";
import { extractGoSymbols } from "./extractors/go.js";
import { extractRustSymbols } from "./extractors/rust.js";
import { extractJavaScriptSymbols } from "./extractors/javascript.js";
import { extractKotlinSymbols } from "./extractors/kotlin.js";
import { extractGradleKtsSymbols } from "./extractors/gradle-kts.js";
import { extractPhpSymbols } from "./extractors/php.js";
// --- Public API ---
/**
 * Extract symbols from a tree-sitter parse tree.
 * For markdown files, use `extractMarkdownSymbols` directly (no tree-sitter needed).
 */
export function extractSymbols(tree, filePath, source, repo, language) {
    switch (language) {
        case "typescript":
        case "tsx":
            return extractTypeScriptSymbols(tree, filePath, source, repo);
        case "python":
            return extractPythonSymbols(tree, filePath, source, repo);
        case "go":
            return extractGoSymbols(tree, filePath, source, repo);
        case "rust":
            return extractRustSymbols(tree, filePath, source, repo);
        case "javascript":
            return extractJavaScriptSymbols(tree, filePath, source, repo);
        case "kotlin":
            return extractKotlinSymbols(tree, filePath, source, repo);
        case "gradle-kts":
            return extractGradleKtsSymbols(tree, filePath, source, repo);
        case "php":
            return extractPhpSymbols(tree, filePath, source, repo);
        case "astro":
            // Astro extraction is regex-based (no tree-sitter grammar).
            // The indexing pipeline calls extractAstroSymbols(source, filePath, repo) directly
            // and never reaches extractSymbols for astro files.
            // This case prevents accidental fallthrough to extractGenericSymbols if
            // extractSymbols is ever called with language="astro" outside the pipeline.
            return [];
        default:
            return extractGenericSymbols(tree, filePath, source, repo);
    }
}
// Re-export custom extractors for use by the indexing pipeline (no tree-sitter grammar)
export { extractMarkdownSymbols } from "./extractors/markdown.js";
export { extractPrismaSymbols } from "./extractors/prisma.js";
export { extractAstroSymbols } from "./extractors/astro.js";
export { extractConversationSymbols } from "./extractors/conversation.js";
/**
 * Splits camelCase, PascalCase, UPPER_SNAKE, and snake_case identifiers
 * into lowercase tokens.
 *
 * Examples:
 *   getUserById   → ["get", "user", "by", "id"]
 *   user_name     → ["user", "name"]
 *   HTMLParser    → ["html", "parser"]
 *   fetchAPIData  → ["fetch", "api", "data"]
 */
export function tokenizeIdentifier(name) {
    // Step 1: split on underscores
    const parts = name.split("_").filter(Boolean);
    const tokens = [];
    for (const part of parts) {
        // Step 2: split camelCase / PascalCase
        // Insert boundary between:
        //   lowercase→uppercase  (get|User)
        //   uppercase sequence→uppercase+lowercase  (HTM|L→P|arser → HTML|Parser)
        const subParts = part
            .replace(/([a-z0-9])([A-Z])/g, "$1\0$2")
            .replace(/([A-Z]+)([A-Z][a-z])/g, "$1\0$2")
            .split("\0");
        for (const sub of subParts) {
            if (sub.length > 0) {
                tokens.push(sub.toLowerCase());
            }
        }
    }
    return tokens;
}
export function makeSymbolId(repo, file, name, startLine) {
    return `${repo}:${file}:${name}:${startLine}`;
}
// --- Generic extraction (fallback for unsupported languages) ---
const GENERIC_NODE_KIND_MAP = {
    function_declaration: "function",
    function_definition: "function",
    class_declaration: "class",
    class_definition: "class",
    method_definition: "method",
    method_declaration: "method",
};
function extractGenericSymbols(tree, filePath, source, repo) {
    const symbols = [];
    function walk(node, parentId) {
        const kind = GENERIC_NODE_KIND_MAP[node.type];
        if (kind) {
            const nameNode = node.childForFieldName("name")
                ?? node.namedChildren.find((c) => c.type === "identifier");
            const name = nameNode?.text ?? "<anonymous>";
            const startLine = node.startPosition.row + 1;
            const endLine = node.endPosition.row + 1;
            const id = makeSymbolId(repo, filePath, name, startLine);
            const nodeSource = source.slice(node.startIndex, node.endIndex);
            const sym = {
                id,
                repo,
                name,
                kind,
                file: filePath,
                start_line: startLine,
                end_line: endLine,
                source: nodeSource.length > 5000
                    ? nodeSource.slice(0, 5000) + "..."
                    : nodeSource,
                tokens: tokenizeIdentifier(name),
            };
            if (parentId)
                sym.parent = parentId;
            symbols.push(sym);
            for (const child of node.namedChildren) {
                walk(child, id);
            }
        }
        else {
            for (const child of node.namedChildren) {
                walk(child, parentId);
            }
        }
    }
    walk(tree.rootNode);
    return symbols;
}
//# sourceMappingURL=symbol-extractor.js.map