import { Injectable, EventEmitter } from '@angular/core';
import { RunView, CompositeKey, Metadata } from '@memberjunction/core';
import { ComponentMetadataEngine } from '@memberjunction/core-entities';
import { buildCuratedFormSchema } from '@memberjunction/interactive-component-types/forms';
import { ParseJSONRecursive } from '@memberjunction/global';
import * as i0 from "@angular/core";
/**
 * Central state management service for Component Studio.
 * Decouples state from components so sub-components can share state.
 */
export class ComponentStudioStateService {
    // --- Component Data ---
    _dbComponents = [];
    _fileLoadedComponents = [];
    get DbComponents() { return this._dbComponents; }
    get FileLoadedComponents() { return this._fileLoadedComponents; }
    /** Combined list of all components (file-loaded first, then DB) */
    get AllComponents() {
        return [
            ...this._fileLoadedComponents,
            ...this._dbComponents
        ];
    }
    // --- Filtered Components ---
    _filteredComponents = [];
    get FilteredComponents() { return this._filteredComponents; }
    // --- Selection & Running ---
    _selectedComponent = null;
    _expandedComponent = null;
    _componentSpec = null;
    _isRunning = false;
    get SelectedComponent() { return this._selectedComponent; }
    set SelectedComponent(value) { this._selectedComponent = value; }
    get ExpandedComponent() { return this._expandedComponent; }
    set ExpandedComponent(value) { this._expandedComponent = value; }
    get ComponentSpec() { return this._componentSpec; }
    set ComponentSpec(value) { this._componentSpec = value; }
    get IsRunning() { return this._isRunning; }
    set IsRunning(value) { this._isRunning = value; }
    // --- Form-role target entity (shared between Field Binding Inspector
    // and the fixture-record live preview) ---
    // Tracks which entity a form-role Component is being authored against.
    // Inspector writes; Preview reads to build fixture FormHostProps; either
    // can clear by setting to null. Independent of ComponentSpec because the
    // author may want to inspect Customer fields while editing a form for
    // Accounts, or simply hasn't decided yet.
    _formTargetEntityName = null;
    get FormTargetEntityName() { return this._formTargetEntityName; }
    set FormTargetEntityName(value) {
        if (value === this._formTargetEntityName)
            return;
        this._formTargetEntityName = value;
        // Schema is keyed by entity — invalidate when target changes.
        this._formSchema = null;
        this.StateChanged.emit();
    }
    // --- Form Builder canvas state (live inside the Form Builder tab). ---
    // The canvas is the source of truth WHILE the Form Builder tab is active;
    // on save we serialize it back to ComponentSpec.code via canvas-to-code.
    // When the user instead edits Code directly, the canvas is rebuilt via
    // code-to-canvas (lossy) on tab focus. Schema is cached per entity so
    // tab toggles don't pay the build cost repeatedly.
    _formCanvas = null;
    get FormCanvas() { return this._formCanvas; }
    set FormCanvas(value) {
        this._formCanvas = value;
        this.StateChanged.emit();
    }
    _formSchema = null;
    get FormSchema() { return this._formSchema; }
    _formSelectedElementId = null;
    get FormSelectedElementId() { return this._formSelectedElementId; }
    set FormSelectedElementId(value) {
        this._formSelectedElementId = value;
        this.StateChanged.emit();
    }
    _formSelectedSectionId = null;
    get FormSelectedSectionId() { return this._formSelectedSectionId; }
    set FormSelectedSectionId(value) {
        this._formSelectedSectionId = value;
        this.StateChanged.emit();
    }
    /** True when the parser couldn't fully round-trip code → canvas. UI shows a banner. */
    _formCodeOnlySectionsDetected = false;
    get FormCodeOnlySectionsDetected() { return this._formCodeOnlySectionsDetected; }
    set FormCodeOnlySectionsDetected(value) {
        this._formCodeOnlySectionsDetected = value;
        this.StateChanged.emit();
    }
    /** Preview mode for the Form Builder tab — drives the toolbar pills AND the preview pane. */
    _formPreviewMode = 'view';
    get FormPreviewMode() { return this._formPreviewMode; }
    set FormPreviewMode(value) {
        if (this._formPreviewMode === value)
            return;
        this._formPreviewMode = value;
        this.StateChanged.emit();
    }
    /** Build (and cache) the curated schema for the given entity. */
    BuildFormSchema(entityName) {
        if (!entityName) {
            this._formSchema = null;
            return null;
        }
        if (this._formSchema && this._formSchema.entityName === entityName) {
            return this._formSchema;
        }
        const schema = buildCuratedFormSchema(entityName, this.Provider);
        this._formSchema = schema;
        return schema;
    }
    // --- Loading ---
    _isLoading = true;
    get IsLoading() { return this._isLoading; }
    // --- Error ---
    _currentError = null;
    get CurrentError() { return this._currentError; }
    set CurrentError(value) { this._currentError = value; }
    // --- Filters ---
    _searchQuery = '';
    _selectedCategories = new Set();
    _showOnlyFavorites = false;
    _showDeprecatedComponents = false;
    _showAllCategories = false;
    _isFilterPanelExpanded = false;
    get SearchQuery() { return this._searchQuery; }
    set SearchQuery(value) {
        this._searchQuery = value;
        this.ApplyFilters();
    }
    get SelectedCategories() { return this._selectedCategories; }
    get ShowOnlyFavorites() { return this._showOnlyFavorites; }
    get ShowDeprecatedComponents() { return this._showDeprecatedComponents; }
    get ShowAllCategories() { return this._showAllCategories; }
    get IsFilterPanelExpanded() { return this._isFilterPanelExpanded; }
    // --- Favorites ---
    _favoriteComponents = new Set();
    get FavoriteComponents() { return this._favoriteComponents; }
    // --- Categories ---
    _availableCategories = [];
    get AvailableCategories() { return this._availableCategories; }
    // --- Editor State ---
    _editableSpec = '';
    _editableCode = '';
    _codeSections = [];
    _isEditingSpec = false;
    _isEditingCode = false;
    _activeTab = 0;
    _isDetailsPaneCollapsed = true;
    get EditableSpec() { return this._editableSpec; }
    set EditableSpec(value) { this._editableSpec = value; }
    get EditableCode() { return this._editableCode; }
    set EditableCode(value) { this._editableCode = value; }
    get CodeSections() { return this._codeSections; }
    get IsEditingSpec() { return this._isEditingSpec; }
    set IsEditingSpec(value) { this._isEditingSpec = value; }
    get IsEditingCode() { return this._isEditingCode; }
    set IsEditingCode(value) { this._isEditingCode = value; }
    get ActiveTab() { return this._activeTab; }
    set ActiveTab(value) { this._activeTab = value; }
    get IsDetailsPaneCollapsed() { return this._isDetailsPaneCollapsed; }
    set IsDetailsPaneCollapsed(value) { this._isDetailsPaneCollapsed = value; }
    // --- Unsaved changes tracking ---
    _hasUnsavedChanges = false;
    _hasResolvedSpec = false;
    get HasUnsavedChanges() { return this._hasUnsavedChanges; }
    set HasUnsavedChanges(value) { this._hasUnsavedChanges = value; }
    // --- AI Panel ---
    _isAIPanelCollapsed = false;
    get IsAIPanelCollapsed() { return this._isAIPanelCollapsed; }
    set IsAIPanelCollapsed(value) { this._isAIPanelCollapsed = value; }
    // --- Events ---
    /** Emitted when state changes require UI update */
    StateChanged = new EventEmitter();
    /** Emitted when the running component needs to refresh */
    RefreshComponent = new EventEmitter();
    /** Emitted when an error should be sent to AI for diagnosis */
    SendErrorToAI = new EventEmitter();
    /** Emitted when a component spec is updated (e.g. by AI) */
    SpecUpdated = new EventEmitter();
    /** Emitted when the Form Builder tab's "Open in Chat" button is clicked.
     * The dashboard subscribes and forwards to NavigationService.SetAgentContext. */
    OpenInChatRequested = new EventEmitter();
    _provider = null;
    /** Set the metadata provider this service should use. Components should call this after injection. */
    set Provider(value) {
        this._provider = value;
    }
    get Provider() {
        return this._provider ?? Metadata.Provider;
    }
    get metadata() {
        return this.Provider;
    }
    // ============================================================
    // DATA LOADING
    // ============================================================
    async LoadComponents() {
        this._isLoading = true;
        this.StateChanged.emit();
        try {
            const rv = RunView.FromMetadataProvider(this.Provider);
            const result = await rv.RunView({
                EntityName: 'MJ: Components',
                ExtraFilter: 'HasRequiredCustomProps = 0',
                OrderBy: 'Name',
                Fields: ['ID', 'Name', 'Namespace', 'Version', 'Type', 'Status', 'Description', 'HasRequiredCustomProps', '__mj_UpdatedAt'],
                MaxRows: 1000,
                ResultType: 'simple'
            });
            if (result.Success) {
                this._dbComponents = result.Results || [];
                this.ApplyFilters();
                this._isLoading = false;
                this.StateChanged.emit();
                // Load favorites in background
                this.loadFavorites();
            }
            else {
                console.error('Failed to load components:', result.ErrorMessage);
                this._isLoading = false;
                this.StateChanged.emit();
            }
        }
        catch (error) {
            console.error('Error loading components:', error);
            this._isLoading = false;
            this.StateChanged.emit();
        }
    }
    async loadFavorites() {
        const currentUserId = this.metadata.CurrentUser?.ID;
        if (!currentUserId)
            return;
        this._favoriteComponents.clear();
        try {
            // Batch-load all favorites for this user + entity in a single query
            // instead of one GetRecordFavoriteStatus call per component.
            const rv = RunView.FromMetadataProvider(this.Provider);
            const safeUserId = currentUserId.replace(/'/g, "''");
            const result = await rv.RunView({
                EntityName: 'MJ: User Favorites',
                ExtraFilter: `UserID='${safeUserId}' AND Entity='MJ: Components'`,
                Fields: ['RecordID'],
                ResultType: 'simple'
            });
            if (result.Success) {
                for (const row of result.Results) {
                    this._favoriteComponents.add(row.RecordID);
                }
            }
        }
        catch (error) {
            console.error('Error loading favorites:', error);
        }
        this.StateChanged.emit();
    }
    // ============================================================
    // FILTERING
    // ============================================================
    ApplyFilters() {
        this.buildCategories();
        let filtered = [...this.AllComponents];
        // Filter out deprecated
        if (!this._showDeprecatedComponents) {
            filtered = filtered.filter(c => this.GetComponentStatus(c) !== 'Deprecated');
        }
        // Favorites filter
        if (this._showOnlyFavorites) {
            filtered = filtered.filter(c => this.IsFavorite(c));
        }
        // Category filter
        if (this._selectedCategories.size > 0) {
            filtered = filtered.filter(c => {
                const namespace = this.GetComponentNamespace(c) || 'Uncategorized';
                const category = this.extractCategoryFromNamespace(namespace);
                return this._selectedCategories.has(category);
            });
        }
        // Search filter
        if (this._searchQuery) {
            const query = this._searchQuery.toLowerCase();
            filtered = filtered.filter(c => {
                const name = this.GetComponentName(c)?.toLowerCase() || '';
                const description = this.GetComponentDescription(c)?.toLowerCase() || '';
                const type = this.GetComponentType(c)?.toLowerCase() || '';
                const namespace = this.GetComponentNamespace(c)?.toLowerCase() || '';
                return name.includes(query) || description.includes(query) || type.includes(query) || namespace.includes(query);
            });
        }
        this._filteredComponents = filtered;
    }
    buildCategories() {
        const categoryMap = new Map();
        for (const component of this.AllComponents) {
            const namespace = this.GetComponentNamespace(component) || 'Uncategorized';
            const category = this.extractCategoryFromNamespace(namespace);
            categoryMap.set(category, (categoryMap.get(category) || 0) + 1);
        }
        this._availableCategories = Array.from(categoryMap.entries())
            .map(([name, count]) => ({
            name,
            count,
            color: this.getCategoryColor(name)
        }))
            .sort((a, b) => b.count - a.count);
    }
    extractCategoryFromNamespace(namespace) {
        if (!namespace || namespace === 'Uncategorized')
            return 'Uncategorized';
        const parts = namespace.split('/').filter(p => p.length > 0);
        return parts[0] || 'Uncategorized';
    }
    getCategoryColor(category) {
        const colors = [
            '#3B82F6', '#8B5CF6', '#10B981', '#F97316', '#06B6D4',
            '#EC4899', '#6366F1', '#14B8A6', '#EAB308', '#EF4444',
        ];
        let hash = 0;
        for (let i = 0; i < category.length; i++) {
            hash = category.charCodeAt(i) + ((hash << 5) - hash);
        }
        return colors[Math.abs(hash) % colors.length];
    }
    ToggleFilterPanel() {
        this._isFilterPanelExpanded = !this._isFilterPanelExpanded;
        this.StateChanged.emit();
    }
    ToggleCategory(category) {
        if (this._selectedCategories.has(category)) {
            this._selectedCategories.delete(category);
        }
        else {
            this._selectedCategories.add(category);
        }
        this.ApplyFilters();
        this.StateChanged.emit();
    }
    ToggleShowOnlyFavorites() {
        this._showOnlyFavorites = !this._showOnlyFavorites;
        this.ApplyFilters();
        this.StateChanged.emit();
    }
    ToggleShowDeprecatedComponents() {
        this._showDeprecatedComponents = !this._showDeprecatedComponents;
        this.ApplyFilters();
        this.StateChanged.emit();
    }
    ToggleShowAllCategories() {
        this._showAllCategories = !this._showAllCategories;
        this.StateChanged.emit();
    }
    ClearAllFilters() {
        this._selectedCategories.clear();
        this._showOnlyFavorites = false;
        this._showDeprecatedComponents = false;
        this.ApplyFilters();
        this.StateChanged.emit();
    }
    GetActiveFilterCount() {
        let count = 0;
        if (this._showOnlyFavorites)
            count++;
        if (this._showDeprecatedComponents)
            count++;
        count += this._selectedCategories.size;
        return count;
    }
    GetDeprecatedCount() {
        return this.AllComponents.filter(c => this.GetComponentStatus(c) === 'Deprecated').length;
    }
    GetVisibleCategories() {
        return this._showAllCategories ? this._availableCategories : this._availableCategories.slice(0, 5);
    }
    IsCategorySelected(category) {
        return this._selectedCategories.has(category);
    }
    // ============================================================
    // FAVORITES
    // ============================================================
    IsFavorite(component) {
        if (this.IsFileLoadedComponent(component))
            return false;
        return this._favoriteComponents.has(this.GetComponentId(component));
    }
    async ToggleFavorite(component) {
        if (this.IsFileLoadedComponent(component))
            return;
        const currentUserId = this.metadata.CurrentUser?.ID;
        if (!currentUserId)
            return;
        const componentId = this.GetComponentId(component);
        const isFavorite = this._favoriteComponents.has(componentId);
        try {
            await this.metadata.SetRecordFavoriteStatus(currentUserId, 'MJ: Components', CompositeKey.FromID(componentId), !isFavorite, this.metadata.CurrentUser);
            if (isFavorite) {
                this._favoriteComponents.delete(componentId);
            }
            else {
                this._favoriteComponents.add(componentId);
            }
            this.StateChanged.emit();
        }
        catch (error) {
            console.error('Error toggling favorite status:', error);
        }
    }
    // ============================================================
    // COMPONENT ACCESSORS (for union type)
    // ============================================================
    IsFileLoadedComponent(component) {
        return component.isFileLoaded === true;
    }
    GetComponentName(component) {
        return component.isFileLoaded ? component.name : component.Name;
    }
    GetComponentDescription(component) {
        return component.isFileLoaded ? component.description : (component.Description || undefined);
    }
    GetComponentType(component) {
        return component.isFileLoaded ? component.type : (component.Type || undefined);
    }
    GetComponentStatus(component) {
        return component.isFileLoaded ? component.status : (component.Status || undefined);
    }
    GetComponentVersion(component) {
        return component.isFileLoaded ? '1.0.0' : (component.Version || '1.0.0');
    }
    /**
     * Fetches the full component specification. For file-loaded components, returns
     * the in-memory spec. For database components, loads the full entity record
     * on demand via ComponentMetadataEngine.FindComponentByID() — the lightweight
     * summary loaded at startup does not include the Specification column.
     */
    async GetComponentSpec(component) {
        if (component.isFileLoaded) {
            return component.specification;
        }
        const fullEntity = await ComponentMetadataEngine.Instance.FindComponentByID(component.ID);
        if (!fullEntity || !fullEntity.Specification) {
            throw new Error(`Component specification not found for: ${component.Name}`);
        }
        return JSON.parse(fullEntity.Specification);
    }
    GetComponentId(component) {
        return component.isFileLoaded ? component.id : component.ID;
    }
    GetComponentNamespace(component) {
        if (component.isFileLoaded) {
            return component.specification.namespace;
        }
        return component.Namespace || undefined;
    }
    GetComponentFilename(component) {
        return component.isFileLoaded ? component.filename : undefined;
    }
    GetComponentLoadedAt(component) {
        return component.isFileLoaded ? component.loadedAt : undefined;
    }
    GetComponentUpdatedAt(component) {
        return !component.isFileLoaded && component.__mj_UpdatedAt ? component.__mj_UpdatedAt : undefined;
    }
    // ============================================================
    // COMPONENT RUNNING
    // ============================================================
    async StartComponent(component) {
        this._selectedComponent = component;
        this._componentSpec = await this.GetComponentSpec(component);
        this._isRunning = true;
        this._currentError = null;
        this._isDetailsPaneCollapsed = false;
        this._hasUnsavedChanges = false;
        this._hasResolvedSpec = false;
        this.InitializeEditors();
        this.StateChanged.emit();
    }
    StopComponent() {
        this._isRunning = false;
        this._selectedComponent = null;
        this._componentSpec = null;
        this._currentError = null;
        this._hasUnsavedChanges = false;
        this._hasResolvedSpec = false;
        this.StateChanged.emit();
    }
    async RunComponent(component) {
        const componentId = this.GetComponentId(component);
        const selectedId = this._selectedComponent ? this.GetComponentId(this._selectedComponent) : null;
        if (this._isRunning && selectedId !== componentId) {
            this.StopComponent();
        }
        await this.StartComponent(component);
    }
    // ============================================================
    // EDITORS
    // ============================================================
    InitializeEditors() {
        if (!this._selectedComponent || !this._componentSpec)
            return;
        const spec = this._componentSpec;
        const parseOptions = {
            extractInlineJson: true,
            maxDepth: 100,
            debug: false
        };
        const parsed = ParseJSONRecursive(spec, parseOptions);
        this._editableSpec = JSON.stringify(parsed, null, 2);
        this._editableCode = spec.code || '// No code available';
        this.BuildCodeSections();
        this._isEditingSpec = false;
        this._isEditingCode = false;
        this._hasUnsavedChanges = false;
    }
    BuildCodeSections() {
        if (!this._selectedComponent) {
            this._codeSections = [];
            return;
        }
        // Use the in-memory spec (which may be the resolved version from the React bridge)
        if (!this._componentSpec)
            return;
        const spec = this._componentSpec;
        const sections = [];
        const mainCode = spec.code || '// No code available';
        sections.push({
            title: spec.name || 'Main Component',
            code: mainCode,
            originalCode: mainCode,
            isDependency: false
        });
        if (spec.dependencies && Array.isArray(spec.dependencies)) {
            spec.dependencies.forEach((dep, index) => {
                const depCode = dep.code || '// No code available';
                sections.push({
                    title: dep.name || `Dependency ${index + 1}`,
                    code: depCode,
                    originalCode: depCode,
                    isDependency: true,
                    index
                });
            });
        }
        this._codeSections = sections;
    }
    /**
     * Apply spec changes from the JSON editor back to the component
     */
    ApplySpecChanges() {
        try {
            const parsed = JSON.parse(this._editableSpec);
            if (this._selectedComponent) {
                if (this.IsFileLoadedComponent(this._selectedComponent)) {
                    this._selectedComponent.specification = parsed;
                }
                this._componentSpec = parsed;
                this._editableCode = parsed.code || '// No code available';
                this.BuildCodeSections();
                this._isEditingSpec = false;
                this._hasUnsavedChanges = true;
                this.RefreshComponent.emit();
                this.StateChanged.emit();
                return true;
            }
        }
        catch (error) {
            console.error('Invalid JSON in spec editor:', error);
        }
        return false;
    }
    /**
     * Apply code changes from the code editor back to the spec
     */
    ApplyCodeChanges() {
        if (!this._selectedComponent)
            return false;
        try {
            const spec = JSON.parse(this._editableSpec);
            if (this._codeSections.length > 0) {
                spec.code = this._codeSections[0].code;
                if (this._codeSections.length > 1 && spec.dependencies) {
                    for (let i = 1; i < this._codeSections.length; i++) {
                        const section = this._codeSections[i];
                        if (section.index !== undefined && spec.dependencies[section.index]) {
                            spec.dependencies[section.index].code = section.code;
                        }
                    }
                }
            }
            const parseOptions = {
                extractInlineJson: true,
                maxDepth: 100,
                debug: false
            };
            const parsed = ParseJSONRecursive(spec, parseOptions);
            this._editableSpec = JSON.stringify(parsed, null, 2);
            if (this.IsFileLoadedComponent(this._selectedComponent)) {
                this._selectedComponent.specification = spec;
            }
            this._componentSpec = spec;
            this._isEditingCode = false;
            this._hasUnsavedChanges = true;
            this.RefreshComponent.emit();
            this.StateChanged.emit();
            return true;
        }
        catch (error) {
            console.error('Error applying code changes:', error);
        }
        return false;
    }
    /**
     * Update the internal spec with the fully resolved version returned by the
     * React bridge after it loads the component hierarchy.  This replaces
     * registry-reference stubs with real code so code sections show actual source.
     * Does NOT mark the component as having unsaved changes or trigger a re-render.
     *
     * Runs at most once per component load. The bridge re-resolves from the registry
     * on every refresh (including the refresh triggered by Apply Changes), and we
     * must not let that round-trip clobber edits the user has already applied.
     */
    UpdateWithResolvedSpec(resolvedSpec) {
        if (!this._selectedComponent)
            return;
        if (this._hasResolvedSpec)
            return;
        // Only update if the resolved spec actually differs (has real code)
        const current = this._componentSpec;
        if (!current || current === resolvedSpec)
            return;
        this._hasResolvedSpec = true;
        this._componentSpec = resolvedSpec;
        // Update editable spec JSON so Spec/Requirements/Design/Data tabs reflect resolved data
        const parseOptions = {
            extractInlineJson: true,
            maxDepth: 100,
            debug: false
        };
        const parsed = ParseJSONRecursive(resolvedSpec, parseOptions);
        this._editableSpec = JSON.stringify(parsed, null, 2);
        // Update editable code with the resolved main code
        this._editableCode = resolvedSpec.code || '// No code available';
        // Rebuild code sections so the editor shows resolved dependency code
        this.BuildCodeSections();
        this.StateChanged.emit();
    }
    /**
     * Update the component spec directly (e.g., from AI)
     */
    UpdateSpec(newSpec) {
        if (!this._selectedComponent)
            return;
        if (this.IsFileLoadedComponent(this._selectedComponent)) {
            this._selectedComponent.specification = newSpec;
        }
        this._componentSpec = newSpec;
        const parseOptions = {
            extractInlineJson: true,
            maxDepth: 100,
            debug: false
        };
        const parsed = ParseJSONRecursive(newSpec, parseOptions);
        this._editableSpec = JSON.stringify(parsed, null, 2);
        this._editableCode = newSpec.code || '// No code available';
        this.BuildCodeSections();
        this._isEditingSpec = false;
        this._isEditingCode = false;
        this._hasUnsavedChanges = true;
        this.SpecUpdated.emit(newSpec);
        this.RefreshComponent.emit();
        this.StateChanged.emit();
    }
    // ============================================================
    // FILE-LOADED COMPONENT MANAGEMENT
    // ============================================================
    AddFileLoadedComponent(component) {
        this._fileLoadedComponents.push(component);
        this.ApplyFilters();
        this.StateChanged.emit();
    }
    RemoveFileLoadedComponent(component) {
        const index = this._fileLoadedComponents.indexOf(component);
        if (index > -1) {
            this._fileLoadedComponents.splice(index, 1);
            if (this._selectedComponent === component) {
                this.StopComponent();
            }
            if (this._expandedComponent === component) {
                this._expandedComponent = null;
            }
            this.ApplyFilters();
            this.StateChanged.emit();
        }
    }
    GenerateId() {
        return 'file-' + Date.now() + '-' + Math.random().toString(36).substr(2, 9);
    }
    // ============================================================
    // UI HELPERS
    // ============================================================
    GetComponentTypeIcon(type) {
        const icons = {
            'Report': 'fa-file-alt',
            'Dashboard': 'fa-tachometer-alt',
            'Form': 'fa-edit',
            'Chart': 'fa-chart-bar',
            'Table': 'fa-table',
            'Widget': 'fa-cube',
            'Navigation': 'fa-compass',
            'Search': 'fa-search',
            'Utility': 'fa-cog'
        };
        return icons[type || ''] || 'fa-puzzle-piece';
    }
    GetComponentTypeColor(type) {
        const colors = {
            'Report': '#3B82F6',
            'Dashboard': '#8B5CF6',
            'Form': '#10B981',
            'Chart': '#F97316',
            'Table': '#06B6D4',
            'Widget': '#EC4899',
            'Navigation': '#6366F1',
            'Search': '#14B8A6',
            'Utility': '#64748B'
        };
        return colors[type || ''] || '#9CA3AF';
    }
    GetNamespaceColor(namespace) {
        if (!namespace || namespace === 'Uncategorized')
            return '#6C757D';
        const category = this.extractCategoryFromNamespace(namespace);
        return this.getCategoryColor(category);
    }
    FormatNamespace(namespace) {
        if (!namespace || namespace === 'Uncategorized')
            return 'Uncategorized';
        const parts = namespace.split('/').filter(p => p.length > 0);
        if (parts.length > 3) {
            return `${parts[0]} / ... / ${parts[parts.length - 1]}`;
        }
        return parts.join(' / ');
    }
    /**
     * Get the current spec, preferring edited version if available
     */
    GetCurrentSpec() {
        if (!this._selectedComponent || !this._componentSpec)
            return null;
        if (this._isEditingSpec || this._isEditingCode) {
            try {
                return JSON.parse(this._editableSpec);
            }
            catch {
                return this._componentSpec;
            }
        }
        return this._componentSpec;
    }
    static ɵfac = function ComponentStudioStateService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ComponentStudioStateService)(); };
    static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: ComponentStudioStateService, factory: ComponentStudioStateService.ɵfac });
}
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ComponentStudioStateService, [{
        type: Injectable
    }], null, null); })();
//# sourceMappingURL=component-studio-state.service.js.map