"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;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ContextManager = void 0;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const chalk_1 = __importDefault(require("chalk"));
const fileNames_1 = require("../constants/fileNames");
class ContextManager {
    constructor(workingDirectory) {
        this.contextDir = path.join(workingDirectory || process.cwd(), '.mycontext');
        this.contextFile = path.join(this.contextDir, fileNames_1.CONTEXT_FILES.CONTEXT_MEMORY);
        this.maxContextSize = 50000; // Default 50KB context limit
        this.compressionLevel = 'medium';
    }
    /**
     * Load project context from files and memory
     */
    async loadContext() {
        const context = {
            workingDirectory: this.contextDir.replace('/.mycontext', ''),
            contextVersion: '1.0',
            lastUpdated: new Date().toISOString(),
        };
        try {
            // Load from context files
            await this.loadContextFiles(context);
            // Load from memory file if exists
            await this.loadMemoryContext(context);
            console.log(chalk_1.default.green('✅ Context loaded successfully'));
            return context;
        }
        catch (error) {
            console.log(chalk_1.default.yellow(`⚠️ Context loading warning: ${error.message}`));
            return context;
        }
    }
    /**
     * Save context to memory for persistence
     */
    async saveContext(context) {
        try {
            // Ensure context directory exists
            if (!fs.existsSync(this.contextDir)) {
                fs.mkdirSync(this.contextDir, { recursive: true });
            }
            // Update metadata
            context.lastUpdated = new Date().toISOString();
            context.contextVersion = context.contextVersion || '1.0';
            // Save to memory file
            fs.writeFileSync(this.contextFile, JSON.stringify(context, null, 2));
            console.log(chalk_1.default.green('✅ Context saved successfully'));
        }
        catch (error) {
            console.log(chalk_1.default.red(`❌ Context save failed: ${error.message}`));
        }
    }
    /**
     * Compact context to reduce size while preserving important information
     */
    async compactContext(context, options = {}) {
        const maxSize = options.maxContextSize || this.maxContextSize;
        const preserveRecent = options.preserveRecent !== false;
        const compressionLevel = options.compressionLevel || this.compressionLevel;
        const compactedContext = { ...context };
        try {
            // Calculate current context size
            const currentSize = this.calculateContextSize(context);
            if (currentSize <= maxSize) {
                console.log(chalk_1.default.green('✅ Context size is within limits'));
                return context;
            }
            console.log(chalk_1.default.yellow(`⚠️ Context size (${currentSize} bytes) exceeds limit (${maxSize} bytes). Compacting...`));
            // Apply compression based on level
            switch (compressionLevel) {
                case 'low':
                    compactedContext.prd = this.compressText(context.prd || '', 0.8);
                    compactedContext.brand = this.compressText(context.brand || '', 0.8);
                    break;
                case 'medium':
                    compactedContext.prd = this.compressText(context.prd || '', 0.6);
                    compactedContext.brand = this.compressText(context.brand || '', 0.6);
                    compactedContext.projectStructure = this.compressText(context.projectStructure || '', 0.7);
                    break;
                case 'high':
                    compactedContext.prd = this.compressText(context.prd || '', 0.4);
                    compactedContext.brand = this.compressText(context.brand || '', 0.4);
                    compactedContext.projectStructure = this.compressText(context.projectStructure || '', 0.5);
                    compactedContext.types = this.compressText(context.types || '', 0.6);
                    break;
            }
            // Preserve recent outputs if requested
            if (preserveRecent && context.previousOutputs) {
                compactedContext.previousOutputs = this.preserveRecentOutputs(context.previousOutputs);
            }
            // Update metadata
            compactedContext.lastUpdated = new Date().toISOString();
            compactedContext.contextVersion = '1.0-compacted';
            const newSize = this.calculateContextSize(compactedContext);
            console.log(chalk_1.default.green(`✅ Context compacted: ${currentSize} → ${newSize} bytes`));
            return compactedContext;
        }
        catch (error) {
            console.log(chalk_1.default.red(`❌ Context compaction failed: ${error.message}`));
            return context;
        }
    }
    /**
     * Merge new context with existing context
     */
    async mergeContext(existingContext, newContext) {
        const mergedContext = {
            ...existingContext,
            ...newContext,
            lastUpdated: new Date().toISOString(),
        };
        // Merge previous outputs intelligently
        if (existingContext.previousOutputs && newContext.previousOutputs) {
            mergedContext.previousOutputs = {
                ...existingContext.previousOutputs,
                ...newContext.previousOutputs,
            };
        }
        // Check if compaction is needed
        const size = this.calculateContextSize(mergedContext);
        if (size > this.maxContextSize) {
            console.log(chalk_1.default.yellow('⚠️ Merged context exceeds size limit, compacting...'));
            return await this.compactContext(mergedContext);
        }
        return mergedContext;
    }
    /**
     * Get context summary for debugging
     */
    getContextSummary(context) {
        const summary = {
            prd: context.prd ? `${context.prd.length} chars` : 'Not loaded',
            types: context.types ? `${context.types.length} chars` : 'Not loaded',
            brand: context.brand ? `${context.brand.length} chars` : 'Not loaded',
            componentList: context.componentList ? `${Object.keys(context.componentList).length} components` : 'Not loaded',
            projectStructure: context.projectStructure ? `${context.projectStructure.length} chars` : 'Not loaded',
            previousOutputs: context.previousOutputs ? `${Object.keys(context.previousOutputs).length} outputs` : 'None',
            totalSize: `${this.calculateContextSize(context)} bytes`,
            lastUpdated: context.lastUpdated || 'Unknown',
        };
        return JSON.stringify(summary, null, 2);
    }
    /**
     * Clear context memory
     */
    async clearContext() {
        try {
            if (fs.existsSync(this.contextFile)) {
                fs.unlinkSync(this.contextFile);
                console.log(chalk_1.default.green('✅ Context memory cleared'));
            }
        }
        catch (error) {
            console.log(chalk_1.default.red(`❌ Context clear failed: ${error.message}`));
        }
    }
    /**
     * Load context from individual files
     */
    async loadContextFiles(context) {
        const files = [
            { key: 'prd', file: fileNames_1.CONTEXT_FILES.PRD },
            { key: 'types', file: fileNames_1.CONTEXT_FILES.TYPES },
            { key: 'brand', file: fileNames_1.CONTEXT_FILES.BRANDING },
            { key: 'projectStructure', file: fileNames_1.CONTEXT_FILES.PROJECT_STRUCTURE },
            { key: 'features', file: fileNames_1.CONTEXT_FILES.FEATURES },
            { key: 'userFlows', file: fileNames_1.CONTEXT_FILES.USER_FLOWS },
            { key: 'edgeCases', file: fileNames_1.CONTEXT_FILES.EDGE_CASES },
            { key: 'technicalSpecs', file: fileNames_1.CONTEXT_FILES.TECHNICAL_SPECS },
        ];
        for (const { key, file } of files) {
            const filePath = path.join(this.contextDir, file);
            if (fs.existsSync(filePath)) {
                try {
                    const content = fs.readFileSync(filePath, 'utf8');
                    context[key] = content;
                }
                catch (error) {
                    console.log(chalk_1.default.yellow(`⚠️ Could not load ${file}`));
                }
            }
        }
        // Load component list
        const componentListPath = path.join(this.contextDir, fileNames_1.CONTEXT_FILES.COMPONENT_LIST);
        if (fs.existsSync(componentListPath)) {
            try {
                const content = fs.readFileSync(componentListPath, 'utf8');
                context.componentList = JSON.parse(content);
            }
            catch (error) {
                console.log(chalk_1.default.yellow('⚠️ Could not load component list'));
            }
        }
    }
    /**
     * Load context from memory file
     */
    async loadMemoryContext(context) {
        if (fs.existsSync(this.contextFile)) {
            try {
                const content = fs.readFileSync(this.contextFile, 'utf8');
                const memoryContext = JSON.parse(content);
                // Merge memory context with file context
                Object.assign(context, memoryContext);
            }
            catch (error) {
                console.log(chalk_1.default.yellow('⚠️ Could not load memory context'));
            }
        }
    }
    /**
     * Calculate context size in bytes
     */
    calculateContextSize(context) {
        return JSON.stringify(context).length;
    }
    /**
     * Compress text by removing unnecessary whitespace and comments
     */
    compressText(text, compressionRatio) {
        if (!text)
            return '';
        // Remove excessive whitespace
        let compressed = text.replace(/\s+/g, ' ').trim();
        // Remove comments if compression ratio is high
        if (compressionRatio < 0.7) {
            compressed = compressed.replace(/\/\*[\s\S]*?\*\//g, '');
            compressed = compressed.replace(/\/\/.*$/gm, '');
        }
        // Truncate if still too long
        const targetLength = Math.floor(text.length * compressionRatio);
        if (compressed.length > targetLength) {
            compressed = compressed.substring(0, targetLength) + '...';
        }
        return compressed;
    }
    /**
     * Preserve only recent outputs
     */
    preserveRecentOutputs(outputs) {
        const sortedEntries = Object.entries(outputs)
            .sort(([, a], [, b]) => {
            const timestampA = a.timestamp || '0';
            const timestampB = b.timestamp || '0';
            return new Date(timestampB).getTime() - new Date(timestampA).getTime();
        })
            .slice(0, 10); // Keep only 10 most recent
        return Object.fromEntries(sortedEntries);
    }
    /**
     * Set context size limits
     */
    setContextLimits(maxSize, compressionLevel) {
        this.maxContextSize = maxSize;
        this.compressionLevel = compressionLevel;
    }
    /**
     * Get context statistics
     */
    getContextStats(context) {
        const totalSize = this.calculateContextSize(context);
        const fileCount = [
            context.prd,
            context.types,
            context.brand,
            context.componentList,
            context.projectStructure,
        ].filter(Boolean).length;
        const originalSize = this.calculateOriginalSize(context);
        const compressionRatio = originalSize > 0 ? totalSize / originalSize : 1;
        return {
            totalSize,
            fileCount,
            lastUpdated: context.lastUpdated || 'Unknown',
            compressionRatio,
        };
    }
    /**
     * Calculate original size before compression
     */
    calculateOriginalSize(context) {
        // This is an approximation - in a real implementation, you'd track original sizes
        return this.calculateContextSize(context) * 1.5;
    }
}
exports.ContextManager = ContextManager;
//# sourceMappingURL=contextManager.js.map