"use strict";
/**
 * Generator Registry
 * Manages available code generators
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.globalRegistry = exports.GeneratorRegistry = void 0;
class GeneratorRegistry {
    frontendGenerators = new Map();
    backendGenerators = new Map();
    documentationGenerators = new Map();
    databaseGenerators = new Map();
    testGenerators = new Map();
    cliGenerators = new Map();
    customGenerators = new Map();
    validationWarnings = [];
    /**
     * Get all validation warnings from generator registration
     */
    getValidationWarnings() {
        return [...this.validationWarnings];
    }
    /**
     * Clear validation warnings
     */
    clearValidationWarnings() {
        this.validationWarnings = [];
    }
    /**
     * Validate base generator fields
     */
    validateBaseGenerator(generator, type) {
        const warnings = [];
        if (!generator.id || generator.id.trim() === '') {
            warnings.push(`[${type}] Generator missing required field: id`);
        }
        if (!generator.name || generator.name.trim() === '') {
            warnings.push(`[${type}] Generator missing required field: name`);
        }
        if (!generator.description || generator.description.trim() === '') {
            warnings.push(`[${type}] Generator missing recommended field: description`);
        }
        if (!generator.generate || typeof generator.generate !== 'function') {
            warnings.push(`[${type}] Generator missing required method: generate()`);
        }
        // Check for reasonable ID format (lowercase, alphanumeric, hyphens)
        if (generator.id && !/^[a-z0-9-]+$/.test(generator.id)) {
            warnings.push(`[${type}] Generator ID "${generator.id}" should be lowercase alphanumeric with hyphens only`);
        }
        return warnings;
    }
    /**
     * Register a frontend generator
     */
    registerFrontendGenerator(generator) {
        // Validate base fields
        const warnings = this.validateBaseGenerator(generator, 'Frontend');
        // Validate frontend-specific fields
        if (!generator.framework || generator.framework.trim() === '') {
            warnings.push('[Frontend] Generator missing required field: framework');
        }
        // Check for generateComponent method (recommended)
        if (!generator.generateComponent) {
            warnings.push(`[Frontend] Generator "${generator.name}" missing recommended method: generateComponent()`);
        }
        // Add warnings to collection
        this.validationWarnings.push(...warnings);
        // Log warnings if any
        if (warnings.length > 0) {
            console.warn(`⚠️  Frontend generator "${generator.name}" has validation warnings:`);
            warnings.forEach(w => console.warn(`   ${w}`));
        }
        if (this.frontendGenerators.has(generator.framework)) {
            throw new Error(`Frontend generator for ${generator.framework} already registered`);
        }
        this.frontendGenerators.set(generator.framework, generator);
    }
    /**
     * Register a backend generator
     */
    registerBackendGenerator(generator) {
        // Validate base fields
        const warnings = this.validateBaseGenerator(generator, 'Backend');
        // Validate backend-specific fields
        if (!generator.language || generator.language.trim() === '') {
            warnings.push('[Backend] Generator missing required field: language');
        }
        // Check for generateEndpoint method (recommended)
        if (!generator.generateEndpoint) {
            warnings.push(`[Backend] Generator "${generator.name}" missing recommended method: generateEndpoint()`);
        }
        // Add warnings to collection
        this.validationWarnings.push(...warnings);
        // Log warnings if any
        if (warnings.length > 0) {
            console.warn(`⚠️  Backend generator "${generator.name}" has validation warnings:`);
            warnings.forEach(w => console.warn(`   ${w}`));
        }
        const language = generator.language;
        const framework = generator.framework || 'default';
        if (!this.backendGenerators.has(language)) {
            this.backendGenerators.set(language, new Map());
        }
        const languageGenerators = this.backendGenerators.get(language);
        if (languageGenerators.has(framework)) {
            throw new Error(`Backend generator for ${language}/${framework} already registered`);
        }
        languageGenerators.set(framework, generator);
    }
    /**
     * Register a documentation generator
     */
    registerDocumentationGenerator(generator) {
        // Validate base fields
        const warnings = this.validateBaseGenerator(generator, 'Documentation');
        // Validate documentation-specific fields
        if (!generator.format || generator.format.trim() === '') {
            warnings.push('[Documentation] Generator missing required field: format');
        }
        // Add warnings to collection
        this.validationWarnings.push(...warnings);
        // Log warnings if any
        if (warnings.length > 0) {
            console.warn(`⚠️  Documentation generator "${generator.name}" has validation warnings:`);
            warnings.forEach(w => console.warn(`   ${w}`));
        }
        if (this.documentationGenerators.has(generator.format)) {
            throw new Error(`Documentation generator for ${generator.format} already registered`);
        }
        this.documentationGenerators.set(generator.format, generator);
    }
    /**
     * Register a database generator
     */
    registerDatabaseGenerator(generator) {
        // Validate base fields
        const warnings = this.validateBaseGenerator(generator, 'Database');
        // Validate database-specific fields
        if (!generator.database || generator.database.trim() === '') {
            warnings.push('[Database] Generator missing required field: database');
        }
        // Add warnings to collection
        this.validationWarnings.push(...warnings);
        // Log warnings if any
        if (warnings.length > 0) {
            console.warn(`⚠️  Database generator "${generator.name}" has validation warnings:`);
            warnings.forEach(w => console.warn(`   ${w}`));
        }
        if (this.databaseGenerators.has(generator.database)) {
            throw new Error(`Database generator for ${generator.database} already registered`);
        }
        this.databaseGenerators.set(generator.database, generator);
    }
    /**
     * Register a test generator
     */
    registerTestGenerator(generator) {
        // Validate base fields
        const warnings = this.validateBaseGenerator(generator, 'Test');
        // Validate test-specific fields
        if (!generator.testFramework || generator.testFramework.trim() === '') {
            warnings.push('[Test] Generator missing required field: testFramework');
        }
        // Add warnings to collection
        this.validationWarnings.push(...warnings);
        // Log warnings if any
        if (warnings.length > 0) {
            console.warn(`⚠️  Test generator "${generator.name}" has validation warnings:`);
            warnings.forEach(w => console.warn(`   ${w}`));
        }
        if (this.testGenerators.has(generator.testFramework)) {
            throw new Error(`Test generator for ${generator.testFramework} already registered`);
        }
        this.testGenerators.set(generator.testFramework, generator);
    }
    /**
     * Register a CLI generator
     */
    registerCliGenerator(generator) {
        // Validate base fields
        const warnings = this.validateBaseGenerator(generator, 'CLI');
        // Validate CLI-specific fields
        if (!generator.framework || generator.framework.trim() === '') {
            warnings.push('[CLI] Generator missing required field: framework');
        }
        if (!generator.language || generator.language.trim() === '') {
            warnings.push('[CLI] Generator missing required field: language');
        }
        // Add warnings to collection
        this.validationWarnings.push(...warnings);
        // Log warnings if any
        if (warnings.length > 0) {
            console.warn(`⚠️  CLI generator "${generator.name}" has validation warnings:`);
            warnings.forEach(w => console.warn(`   ${w}`));
        }
        if (this.cliGenerators.has(generator.framework)) {
            throw new Error(`CLI generator for ${generator.framework} already registered`);
        }
        this.cliGenerators.set(generator.framework, generator);
    }
    /**
     * Register a custom generator
     */
    registerCustomGenerator(generator) {
        // Validate base fields
        const warnings = this.validateBaseGenerator(generator, 'Custom');
        // Add warnings to collection
        this.validationWarnings.push(...warnings);
        // Log warnings if any
        if (warnings.length > 0) {
            console.warn(`⚠️  Custom generator "${generator.name}" has validation warnings:`);
            warnings.forEach(w => console.warn(`   ${w}`));
        }
        if (this.customGenerators.has(generator.id)) {
            throw new Error(`Custom generator ${generator.id} already registered`);
        }
        this.customGenerators.set(generator.id, generator);
    }
    /**
     * Get a frontend generator by framework
     */
    getFrontendGenerator(framework) {
        return this.frontendGenerators.get(framework);
    }
    /**
     * Get a frontend generator with helpful error message if not found
     */
    getFrontendGeneratorOrThrow(framework) {
        const generator = this.getFrontendGenerator(framework);
        if (!generator) {
            const available = this.listFrontendFrameworks();
            const suggestions = this.findSimilar(framework, available);
            let errorMsg = `Frontend generator for "${framework}" not found.`;
            if (suggestions.length > 0) {
                errorMsg += `\n\nDid you mean: ${suggestions.join(', ')}?`;
            }
            errorMsg += `\n\nAvailable frontend frameworks: ${available.join(', ')}`;
            errorMsg += `\n\nRun "bang list-generators" to see all available generators.`;
            throw new Error(errorMsg);
        }
        return generator;
    }
    /**
     * Get a backend generator by language and optional framework
     */
    getBackendGenerator(language, framework) {
        const languageGenerators = this.backendGenerators.get(language);
        if (!languageGenerators) {
            return undefined;
        }
        // Try specific framework first, then fall back to default
        const targetFramework = framework || 'default';
        return languageGenerators.get(targetFramework) || languageGenerators.get('default');
    }
    /**
     * Get a backend generator with helpful error message if not found
     */
    getBackendGeneratorOrThrow(language, framework) {
        const generator = this.getBackendGenerator(language, framework);
        if (!generator) {
            const available = this.listBackendLanguages();
            const suggestions = this.findSimilar(language, available);
            let errorMsg = `Backend generator for "${language}${framework ? `/${framework}` : ''}" not found.`;
            if (suggestions.length > 0) {
                errorMsg += `\n\nDid you mean: ${suggestions.join(', ')}?`;
            }
            errorMsg += `\n\nAvailable backend languages: ${available.join(', ')}`;
            errorMsg += `\n\nRun "bang list-generators" to see all available generators.`;
            throw new Error(errorMsg);
        }
        return generator;
    }
    /**
     * Get a documentation generator by format
     */
    getDocumentationGenerator(format) {
        return this.documentationGenerators.get(format);
    }
    /**
     * Get a database generator
     */
    getDatabaseGenerator(database) {
        return this.databaseGenerators.get(database);
    }
    /**
     * Get a database generator with helpful error message if not found
     */
    getDatabaseGeneratorOrThrow(database) {
        const generator = this.getDatabaseGenerator(database);
        if (!generator) {
            const available = this.listDatabases();
            const suggestions = this.findSimilar(database, available);
            let errorMsg = `Database generator for "${database}" not found.`;
            if (suggestions.length > 0) {
                errorMsg += `\n\nDid you mean: ${suggestions.join(', ')}?`;
            }
            errorMsg += `\n\nAvailable database generators: ${available.join(', ')}`;
            errorMsg += `\n\nRun "bang list-generators" to see all available generators.`;
            throw new Error(errorMsg);
        }
        return generator;
    }
    /**
     * Get a test generator
     */
    getTestGenerator(testFramework) {
        return this.testGenerators.get(testFramework);
    }
    /**
     * Get a CLI generator
     */
    getCliGenerator(framework) {
        return this.cliGenerators.get(framework);
    }
    /**
     * Get a custom generator
     */
    getCustomGenerator(id) {
        return this.customGenerators.get(id);
    }
    /**
     * Get a component generator by type and technology
     * This is the flexible stack system lookup
     */
    getComponentGenerator(type, technology) {
        // Defensive: handle empty/invalid inputs
        if (!type || !technology || type.trim() === '' || technology.trim() === '') {
            return undefined;
        }
        // For now, map common types to existing generators
        // Later, we'll have a proper component generator registry
        if (type === 'frontend') {
            return this.getFrontendGenerator(technology);
        }
        if (type === 'backend') {
            // Parse technology string (e.g., "typescript/express" -> language=typescript, framework=express)
            const parts = technology.split('/');
            const language = parts[0];
            const framework = parts[1];
            return this.getBackendGenerator(language, framework);
        }
        if (type === 'cli') {
            // Parse technology string (e.g., "typescript/node" -> use typescript CLI generator)
            // For now, just use commander framework
            return this.getCliGenerator('commander');
        }
        if (type === 'database') {
            // Parse technology string (e.g., "postgresql/prisma" -> try "prisma" first)
            if (technology.includes('/')) {
                const parts = technology.split('/');
                const orm = parts[1]; // e.g., "prisma" or "drizzle"
                const generator = this.getDatabaseGenerator(orm);
                if (generator) {
                    return generator;
                }
            }
            // Try direct lookup (e.g., "prisma" or "drizzle")
            const directGenerator = this.getDatabaseGenerator(technology);
            if (directGenerator) {
                return directGenerator;
            }
            // For plain database types (postgresql, mysql, etc.), default to Prisma
            const plainDatabases = ['postgresql', 'postgres', 'mysql', 'sqlite', 'mongodb', 'sqlserver'];
            if (plainDatabases.includes(technology.toLowerCase())) {
                return this.getDatabaseGenerator('prisma');
            }
            return undefined;
        }
        // Check custom generators
        return this.getCustomGenerator(`${type}/${technology}`);
    }
    /**
     * List all registered frontend frameworks
     */
    listFrontendFrameworks() {
        return Array.from(this.frontendGenerators.keys());
    }
    /**
     * List all registered backend languages
     */
    listBackendLanguages() {
        return Array.from(this.backendGenerators.keys());
    }
    /**
     * List all registered documentation formats
     */
    listDocumentationFormats() {
        return Array.from(this.documentationGenerators.keys());
    }
    /**
     * List all registered databases
     */
    listDatabases() {
        return Array.from(this.databaseGenerators.keys());
    }
    /**
     * List all registered test frameworks
     */
    listTestFrameworks() {
        return Array.from(this.testGenerators.keys());
    }
    /**
     * List all registered CLI frameworks
     */
    listCliFrameworks() {
        return Array.from(this.cliGenerators.keys());
    }
    /**
     * Get all custom generators
     */
    getCustomGenerators() {
        return Array.from(this.customGenerators.values());
    }
    /**
     * Find similar strings using Levenshtein distance
     * Returns top 3 most similar strings
     */
    findSimilar(target, candidates) {
        if (candidates.length === 0)
            return [];
        const targetLower = target.toLowerCase();
        const scored = candidates.map(candidate => {
            const candidateLower = candidate.toLowerCase();
            const distance = this.levenshteinDistance(targetLower, candidateLower);
            // Consider it similar if distance is less than 3 or less than half the target length
            const isSimilar = distance < 3 || distance < target.length / 2;
            return { candidate, distance, isSimilar };
        });
        // Filter to only similar ones and sort by distance
        return scored
            .filter(s => s.isSimilar)
            .sort((a, b) => a.distance - b.distance)
            .slice(0, 3)
            .map(s => s.candidate);
    }
    /**
     * Calculate Levenshtein distance between two strings
     */
    levenshteinDistance(str1, str2) {
        const matrix = [];
        // Initialize matrix
        for (let i = 0; i <= str2.length; i++) {
            matrix[i] = [i];
        }
        for (let j = 0; j <= str1.length; j++) {
            matrix[0][j] = j;
        }
        // Fill matrix
        for (let i = 1; i <= str2.length; i++) {
            for (let j = 1; j <= str1.length; j++) {
                if (str2.charAt(i - 1) === str1.charAt(j - 1)) {
                    matrix[i][j] = matrix[i - 1][j - 1];
                }
                else {
                    matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, // substitution
                    matrix[i][j - 1] + 1, // insertion
                    matrix[i - 1][j] + 1 // deletion
                    );
                }
            }
        }
        return matrix[str2.length][str1.length];
    }
    /**
     * Get detailed information about a generator
     */
    getGeneratorInfo(type, technology) {
        // Defensive: handle empty/invalid inputs
        if (!type || !technology || type.trim() === '' || technology.trim() === '') {
            return {
                exists: false,
                suggestions: [],
                availableOptions: [],
            };
        }
        const generator = this.getComponentGenerator(type, technology);
        if (generator) {
            return { exists: true, generator };
        }
        // Provide helpful suggestions
        let availableOptions = [];
        let suggestions = [];
        if (type === 'frontend') {
            availableOptions = this.listFrontendFrameworks();
            suggestions = this.findSimilar(technology, availableOptions);
        }
        else if (type === 'backend') {
            availableOptions = this.listBackendLanguages();
            const parts = technology.split('/');
            suggestions = this.findSimilar(parts[0], availableOptions);
        }
        else if (type === 'database') {
            availableOptions = this.listDatabases();
            suggestions = this.findSimilar(technology, availableOptions);
        }
        return {
            exists: false,
            suggestions,
            availableOptions,
        };
    }
}
exports.GeneratorRegistry = GeneratorRegistry;
// Global registry instance
exports.globalRegistry = new GeneratorRegistry();
//# sourceMappingURL=generator-registry.js.map