import { GameTheme } from '../core/types'; import { DEFAULT_THEME } from '../core/config'; /** * CustomizationService - handles theming and visual customization */ export class CustomizationService { private currentTheme: GameTheme; private customAssets: Map = new Map(); private themeListeners: Set<(theme: GameTheme) => void> = new Set(); constructor(defaultTheme: GameTheme = DEFAULT_THEME) { this.currentTheme = { ...defaultTheme }; } /** * Initialize the service */ async initialize(): Promise { // Load saved theme and assets if any try { // Implementation would load from storage // const savedTheme = await storage.getCustomTheme(); // if (savedTheme) { // this.currentTheme = savedTheme; // } } catch (error) { console.warn('Failed to load saved theme:', error); } } /** * Set a new theme */ setTheme(theme: GameTheme): void { this.currentTheme = { ...theme }; this.notifyThemeListeners(); } /** * Get current theme */ getCurrentTheme(): GameTheme { return { ...this.currentTheme }; } /** * Update specific theme properties */ updateTheme(updates: Partial): void { this.currentTheme = { ...this.currentTheme, ...updates, colors: { ...this.currentTheme.colors, ...updates.colors }, fonts: { ...this.currentTheme.fonts, ...updates.fonts }, spacing: { ...this.currentTheme.spacing, ...updates.spacing } }; this.notifyThemeListeners(); } /** * Set custom assets */ setCustomAssets(assets: Record): void { Object.entries(assets).forEach(([key, value]) => { this.customAssets.set(key, value); }); } /** * Get custom asset */ getCustomAsset(key: string): string | undefined { return this.customAssets.get(key); } /** * Create style object for React Native components */ getStyles() { const theme = this.getCurrentTheme(); return { container: { backgroundColor: theme.colors.background, flex: 1 }, surface: { backgroundColor: theme.colors.surface, borderRadius: theme.spacing.md, padding: theme.spacing.lg }, primaryButton: { backgroundColor: theme.colors.primary, borderRadius: theme.spacing.sm, paddingHorizontal: theme.spacing.lg, paddingVertical: theme.spacing.md }, text: { color: theme.colors.text, fontFamily: theme.fonts.regular, fontSize: 16 }, titleText: { color: theme.colors.text, fontFamily: theme.fonts.title, fontSize: 24, fontWeight: 'bold' } }; } /** * Subscribe to theme changes */ onThemeChange(callback: (theme: GameTheme) => void): () => void { this.themeListeners.add(callback); // Return unsubscribe function return () => { this.themeListeners.delete(callback); }; } private notifyThemeListeners(): void { this.themeListeners.forEach(callback => { try { callback(this.currentTheme); } catch (error) { console.warn('Theme listener error:', error); } }); } }