import { Injectable } from '@angular/core'; import { BehaviorSubject, Observable } from 'rxjs'; import { FontTheme, FontDefinition } from '../types/font-types'; import { UiFontManagerService } from '../ui-font-manager.service'; @Injectable({ providedIn: 'root' }) export class FontThemeService { private themes = new Map(); private activeThemeSubject = new BehaviorSubject(null); constructor(private fontManager: UiFontManagerService) { this.initializeDefaultThemes(); } /** * Get all available themes */ getThemes(): FontTheme[] { return Array.from(this.themes.values()); } /** * Get theme by name */ getTheme(name: string): FontTheme | undefined { return this.themes.get(name); } /** * Add or update a theme */ addTheme(theme: FontTheme): void { this.themes.set(theme.name, theme); } /** * Remove a theme */ removeTheme(name: string): boolean { return this.themes.delete(name); } /** * Apply a theme by name */ applyTheme(themeName: string): Observable { const theme = this.themes.get(themeName); if (!theme) { console.warn(`Theme "${themeName}" not found`); return new BehaviorSubject(false).asObservable(); } return new Observable(observer => { this.fontManager.applyTheme(theme).subscribe({ next: (success) => { if (success) { this.activeThemeSubject.next(theme); } observer.next(success); observer.complete(); }, error: (error) => observer.error(error) }); }); } /** * Get currently active theme */ getActiveTheme(): Observable { return this.activeThemeSubject.asObservable(); } /** * Create theme from font combination */ createThemeFromCombination(name: string, combinationName: string, description?: string): FontTheme | null { const theme = this.fontManager.createThemeFromCombination(name, combinationName); if (theme && description) { theme.description = description; } if (theme) { this.addTheme(theme); } return theme; } /** * Create custom theme */ createCustomTheme( name: string, fonts: { sans: string; serif: string; mono: string; display: string; }, description?: string ): FontTheme | null { const allFonts = this.fontManager.getAllFonts(); // Validate all fonts exist const fontDefinitions: { [key: string]: FontDefinition } = {}; for (const [type, fontName] of Object.entries(fonts)) { const font = allFonts[fontName]; if (!font) { console.warn(`Font "${fontName}" not found for type "${type}"`); return null; } fontDefinitions[type] = font; } const theme: FontTheme = { name, description, fonts: { sans: fontDefinitions['sans'], serif: fontDefinitions['serif'], mono: fontDefinitions['mono'], display: fontDefinitions['display'] } }; this.addTheme(theme); return theme; } /** * Export theme configuration */ exportTheme(themeName: string): string | null { const theme = this.themes.get(themeName); if (!theme) return null; return JSON.stringify(theme, null, 2); } /** * Import theme from configuration */ importTheme(themeJson: string): FontTheme | null { try { const theme: FontTheme = JSON.parse(themeJson); // Validate theme structure if (!theme.name || !theme.fonts) { throw new Error('Invalid theme structure'); } this.addTheme(theme); return theme; } catch (error) { console.error('Failed to import theme:', error); return null; } } private initializeDefaultThemes(): void { const combinations = this.fontManager.getFontCombinations(); // Create default themes from combinations Object.entries(combinations).forEach(([name, combo]) => { const theme = this.fontManager.createThemeFromCombination(name, name); if (theme) { this.addTheme(theme); } }); // Add system fonts theme const systemTheme: FontTheme = { name: 'System', description: 'Use system default fonts for optimal performance', fonts: { sans: { family: 'system-ui', weights: [400, 500, 600, 700], fallbacks: ['-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Roboto', 'sans-serif'], loadingStrategy: 'swap', category: 'sans-serif' }, serif: { family: 'ui-serif', weights: [400, 700], fallbacks: ['Georgia', 'Cambria', 'Times New Roman', 'Times', 'serif'], loadingStrategy: 'swap', category: 'serif' }, mono: { family: 'ui-monospace', weights: [400, 700], fallbacks: ['SFMono-Regular', 'Monaco', 'Consolas', 'Liberation Mono', 'Courier New', 'monospace'], loadingStrategy: 'swap', category: 'monospace' }, display: { family: 'system-ui', weights: [400, 700], fallbacks: ['-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Roboto', 'sans-serif'], loadingStrategy: 'swap', category: 'display' } } }; this.addTheme(systemTheme); } }