import { EventBus } from '../core/EventBus.js'; import { EventTypes } from '../constants/EventTypes.js'; import { CalendarConfig } from '../core/CalendarConfig.js'; import { CalendarEvent, CalendarView, IEventBus } from '../types/CalendarTypes.js'; import { CalendarStateManager } from './CalendarStateManager.js'; import { StateEvents } from '../types/CalendarState.js'; /** * CalendarManager - Main coordinator for all calendar managers * Now delegates initialization to CalendarStateManager for better coordination */ export class CalendarManager { private eventBus: IEventBus; private config: CalendarConfig; private stateManager: CalendarStateManager; private currentView: CalendarView = 'week'; private currentDate: Date = new Date(); private isInitialized: boolean = false; constructor(eventBus: IEventBus, config: CalendarConfig) { this.eventBus = eventBus; this.config = config; this.stateManager = new CalendarStateManager(); this.setupEventListeners(); console.log('📋 CalendarManager: Created with state management'); } /** * Initialize calendar system using state-driven approach */ public async initialize(): Promise { if (this.isInitialized) { console.warn('CalendarManager is already initialized'); return; } console.log('🚀 CalendarManager: Starting state-driven initialization'); try { // Delegate to StateManager for coordinated initialization await this.stateManager.initialize(); // Set initial view and date after successful initialization this.setView(this.currentView); this.setCurrentDate(this.currentDate); this.isInitialized = true; console.log('✅ CalendarManager: Initialization complete'); } catch (error) { console.error('❌ CalendarManager initialization failed:', error); throw error; // Let the caller handle the error } } /** * Skift calendar view (dag/uge/måned) */ public setView(view: CalendarView): void { if (this.currentView === view) { return; } const previousView = this.currentView; this.currentView = view; console.log(`Changing view from ${previousView} to ${view}`); // Emit view change event this.eventBus.emit(EventTypes.VIEW_CHANGED, { previousView, currentView: view, date: this.currentDate }); } /** * Sæt aktuel dato */ public setCurrentDate(date: Date): void { const previousDate = this.currentDate; this.currentDate = new Date(date); console.log(`Changing date from ${previousDate.toISOString()} to ${date.toISOString()}`); // Emit date change event this.eventBus.emit(EventTypes.DATE_CHANGED, { previousDate, currentDate: this.currentDate, view: this.currentView }); } /** * Naviger til i dag */ public goToToday(): void { this.setCurrentDate(new Date()); } /** * Naviger til næste periode (dag/uge/måned afhængig af view) */ public goToNext(): void { const nextDate = this.calculateNextDate(); this.setCurrentDate(nextDate); } /** * Naviger til forrige periode (dag/uge/måned afhængig af view) */ public goToPrevious(): void { const previousDate = this.calculatePreviousDate(); this.setCurrentDate(previousDate); } /** * Hent aktuel view */ public getCurrentView(): CalendarView { return this.currentView; } /** * Hent aktuel dato */ public getCurrentDate(): Date { return new Date(this.currentDate); } /** * Hent calendar konfiguration */ public getConfig(): CalendarConfig { return this.config; } /** * Check om calendar er initialiseret */ public isCalendarInitialized(): boolean { return this.isInitialized && this.stateManager.isReady(); } /** * Get current calendar state */ public getCurrentState(): string { return this.stateManager.getCurrentState(); } /** * Get state manager for advanced operations */ public getStateManager(): CalendarStateManager { return this.stateManager; } /** * Get initialization report for debugging */ public getInitializationReport(): any { return this.stateManager.getInitializationReport(); } /** * Genindlæs calendar data */ public refresh(): void { console.log('Refreshing calendar...'); this.eventBus.emit(EventTypes.CALENDAR_REFRESH_REQUESTED, { view: this.currentView, date: this.currentDate }); } /** * Ryd calendar og nulstil til standard tilstand */ public reset(): void { console.log('Resetting calendar...'); this.currentView = 'week'; this.currentDate = new Date(); this.eventBus.emit(EventTypes.CALENDAR_RESET, { view: this.currentView, date: this.currentDate }); } /** * Setup event listeners for at håndtere events fra andre managers */ private setupEventListeners(): void { // Lyt efter navigation events this.eventBus.on(EventTypes.NAVIGATE_TO_DATE, (event) => { const customEvent = event as CustomEvent; const { date } = customEvent.detail; this.setCurrentDate(new Date(date)); }); // Lyt efter view change requests this.eventBus.on(EventTypes.VIEW_CHANGE_REQUESTED, (event) => { const customEvent = event as CustomEvent; const { view } = customEvent.detail; this.setView(view); }); // Lyt efter today navigation this.eventBus.on(EventTypes.NAVIGATE_TO_TODAY, () => { this.goToToday(); }); // Lyt efter next/previous navigation this.eventBus.on(EventTypes.NAVIGATE_NEXT, () => { this.goToNext(); }); this.eventBus.on(EventTypes.NAVIGATE_PREVIOUS, () => { this.goToPrevious(); }); // Lyt efter refresh requests this.eventBus.on(EventTypes.REFRESH_REQUESTED, () => { this.refresh(); }); // Lyt efter reset requests this.eventBus.on(EventTypes.RESET_REQUESTED, () => { this.reset(); }); } /** * Beregn næste dato baseret på aktuel view */ private calculateNextDate(): Date { const nextDate = new Date(this.currentDate); switch (this.currentView) { case 'day': nextDate.setDate(nextDate.getDate() + 1); break; case 'week': nextDate.setDate(nextDate.getDate() + 7); break; case 'month': nextDate.setMonth(nextDate.getMonth() + 1); break; } return nextDate; } /** * Beregn forrige dato baseret på aktuel view */ private calculatePreviousDate(): Date { const previousDate = new Date(this.currentDate); switch (this.currentView) { case 'day': previousDate.setDate(previousDate.getDate() - 1); break; case 'week': previousDate.setDate(previousDate.getDate() - 7); break; case 'month': previousDate.setMonth(previousDate.getMonth() - 1); break; } return previousDate; } }