"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.LivingDictionary = void 0;
const fs = __importStar(require("fs-extra"));
const path = __importStar(require("path"));
const core_1 = require("@myycontext/core");
class LivingDictionary {
    constructor(brainPath) {
        this.brainPath =
            brainPath || path.join(process.cwd(), ".mycontext", "context.json");
        this.dict = (0, core_1.createSemanticDictionary)();
    }
    defineTerm(term, definition, category = "concept", source = "system", context = "", aliases = []) {
        const existing = this.dict.entries.get(term);
        if (existing) {
            existing.definition = definition;
            existing.category = category;
            existing.aliases = [...new Set([...existing.aliases, ...aliases])];
            existing.context = context || existing.context;
            existing.lastUpdated = new Date().toISOString();
            existing.status = "defined";
            return existing;
        }
        const entry = (0, core_1.createDictionaryEntry)(term, definition, category, source, context, aliases);
        this.dict.entries.set(term, entry);
        this.detectAndRecordConflicts(term);
        return entry;
    }
    getAllEntries() {
        return Array.from(this.dict.entries.values());
    }
    lookupTerm(term) {
        return this.dict.entries.get(term);
    }
    searchTerms(query) {
        const lower = query.toLowerCase();
        const results = [];
        for (const [, entry] of this.dict.entries) {
            if (entry.term.toLowerCase().includes(lower)) {
                results.push(entry);
            }
            else if (entry.aliases.some(a => a.toLowerCase().includes(lower))) {
                results.push(entry);
            }
            else if (entry.definition.toLowerCase().includes(lower)) {
                results.push(entry);
            }
        }
        return results;
    }
    expandTerm(term) {
        const entry = this.dict.entries.get(term);
        if (!entry)
            return [];
        const expanded = [entry.definition];
        if (entry.aliases.length > 0) {
            expanded.push(...entry.aliases);
        }
        const related = this.findRelatedTerms(term);
        expanded.push(...related.map(r => `${r.term}: ${r.definition}`));
        return expanded;
    }
    getEntries() {
        return this.dict.entries;
    }
    getAllTerms() {
        return Array.from(this.dict.entries.keys());
    }
    getConflicts() {
        return this.dict.conflicts;
    }
    detectUndefinedTerms(terms) {
        return terms.filter(t => !this.dict.entries.has(t));
    }
    async discoverTerms(sourceText) {
        const discovered = [];
        const words = sourceText.split(/\s+/);
        const candidates = this.extractCandidateTerms(words);
        for (const candidate of candidates) {
            if (!this.dict.entries.has(candidate)) {
                const entry = (0, core_1.createDictionaryEntry)(candidate, `Auto-discovered from ${sourceText.substring(0, 50)}...`, "concept", "discovery", sourceText.substring(0, 200));
                entry.status = "needs-review";
                this.dict.entries.set(candidate, entry);
                discovered.push(entry);
            }
        }
        return discovered;
    }
    diff(other) {
        return (0, core_1.computeSemanticDiff)(this.dict, other);
    }
    async load() {
        if (!(await fs.pathExists(this.brainPath)))
            return;
        const brain = await fs.readJson(this.brainPath);
        const dictData = brain?.context?.semanticDictionary;
        if (!dictData)
            return;
        for (const entryData of dictData.entries || []) {
            const entry = {
                term: entryData.term,
                definition: entryData.definition,
                category: entryData.category || "concept",
                aliases: entryData.aliases || [],
                context: entryData.context || "",
                source: entryData.source || "system",
                firstSeen: entryData.firstSeen || new Date().toISOString(),
                lastUpdated: entryData.lastUpdated || new Date().toISOString(),
                status: entryData.status || "defined",
            };
            this.dict.entries.set(entry.term, entry);
        }
        this.dict.conflicts = dictData.conflicts || [];
        this.dict.lastSynced = dictData.lastSynced || new Date().toISOString();
    }
    async save() {
        if (!(await fs.pathExists(this.brainPath)))
            return;
        const brain = await fs.readJson(this.brainPath);
        const entriesData = Array.from(this.dict.entries.values()).map(e => ({
            term: e.term,
            definition: e.definition,
            category: e.category,
            aliases: e.aliases,
            context: e.context,
            source: e.source,
            firstSeen: e.firstSeen,
            lastUpdated: e.lastUpdated,
            status: e.status,
        }));
        brain.context = brain.context || {};
        brain.context.semanticDictionary = {
            entries: entriesData,
            conflicts: this.dict.conflicts,
            lastSynced: new Date().toISOString(),
        };
        await fs.writeJson(this.brainPath, brain, { spaces: 2 });
    }
    findRelatedTerms(term) {
        const entry = this.dict.entries.get(term);
        if (!entry)
            return [];
        const related = [];
        for (const [, other] of this.dict.entries) {
            if (other.term === term)
                continue;
            if (other.aliases.includes(term)) {
                related.push(other);
            }
            else if (entry.aliases.includes(other.term)) {
                related.push(other);
            }
            else if (other.category === entry.category &&
                other.definition.includes(entry.term)) {
                related.push(other);
            }
        }
        return related;
    }
    detectAndRecordConflicts(term) {
        const entry = this.dict.entries.get(term);
        if (!entry)
            return;
        const existingConflictIndex = this.dict.conflicts.findIndex(c => c.term === term);
        const conflicting = [];
        for (const [, other] of this.dict.entries) {
            if (other.term !== term &&
                other.aliases.includes(term) &&
                other.definition !== entry.definition) {
                conflicting.push({
                    definition: other.definition,
                    source: other.source,
                });
            }
        }
        if (conflicting.length > 0) {
            conflicting.push({
                definition: entry.definition,
                source: entry.source,
            });
            if (existingConflictIndex >= 0) {
                const existing = this.dict.conflicts[existingConflictIndex];
                if (existing)
                    existing.definitions = conflicting;
            }
            else {
                this.dict.conflicts.push({ term, definitions: conflicting });
            }
        }
        else if (existingConflictIndex >= 0) {
            this.dict.conflicts.splice(existingConflictIndex, 1);
        }
    }
    extractCandidateTerms(words) {
        const candidates = [];
        const skipWords = new Set([
            "the", "a", "an", "is", "are", "was", "were", "be", "been",
            "have", "has", "had", "do", "does", "did", "will", "would",
            "can", "could", "should", "may", "might", "shall",
            "this", "that", "these", "those", "it", "its",
            "of", "in", "on", "at", "to", "for", "with", "by", "from",
            "and", "or", "but", "not", "no", "if", "so", "as",
            "we", "you", "they", "our", "your", "their",
        ]);
        for (let i = 0; i < words.length; i++) {
            const w = words[i];
            if (!w)
                continue;
            const word = w.replace(/[^a-zA-Z0-9_-]/g, "").trim();
            if (!word || word.length < 3)
                continue;
            if (skipWords.has(word.toLowerCase()))
                continue;
            const isUpperCase = word[0] === word[0]?.toUpperCase() &&
                word[0] !== word[0]?.toLowerCase();
            const isCamelCase = /^[a-z]+[A-Z]/.test(word);
            const isPascalCase = /^[A-Z][a-z]+[A-Z]/.test(word);
            const isAllUpper = /^[A-Z_]{2,}$/.test(word);
            if (isPascalCase || isCamelCase || isAllUpper || isUpperCase) {
                candidates.push(word);
            }
            else if (i > 0 && isUpperCase) {
                candidates.push(word);
            }
        }
        return [...new Set(candidates)];
    }
}
exports.LivingDictionary = LivingDictionary;
//# sourceMappingURL=LivingDictionary.js.map