File size: 9,419 Bytes
adca48b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
/**
 * PIPS - Main Application Bootstrap
 * Initializes the modular PIPS application
 */

// Import core modules
import { Logger } from './core/logger.js';
import { appState } from './core/state.js';
import { socketManager } from './network/socket.js';
import { storageManager } from './core/storage.js';

// Import UI modules
import { domManager } from './ui/dom-manager.js';
import { messageManager } from './ui/message-manager.js';
import { settingsManager } from './ui/settings-manager.js';
import { sessionManager } from './ui/session-manager.js';
import { imageHandler } from './ui/image-handler.js';

// Import handlers
import { socketEventHandlers } from './handlers/socket-handlers.js';

// Global error handlers
window.addEventListener('error', (event) => {
    Logger.error('Global JavaScript error:', event.error);
    Logger.error('Error message:', event.message);
    Logger.error('Error filename:', event.filename);
    Logger.error('Error line:', event.lineno);
    Logger.error('Error column:', event.colno);
});

window.addEventListener('unhandledrejection', (event) => {
    Logger.error('Unhandled promise rejection:', event.reason);
});

/**
 * Main Application class - Coordinates all modules
 */
class PIPSApplication {
    constructor() {
        this.isInitialized = false;
    }

    async initialize() {
        if (this.isInitialized) {
            Logger.warn('App', 'Application already initialized');
            return;
        }

        try {
            Logger.log('App', 'Initializing PIPS application...');
            
            // Initialize managers
            domManager.setupDOMReferences();
            await domManager.initializeIcons();
            
            // Set up event handlers
            socketManager.initialize();
            sessionManager.initialize();
            settingsManager.initialize();
            imageHandler.initialize();
            
            // Load user settings from storage
            settingsManager.loadUserSettingsFromStorage();
            
            // Perform first-run seeding of default sessions
            await this.performFirstRunSeeding();
            
            // Set up additional image features
            imageHandler.setupPasteHandler();
            
            // Set up core functionality event listeners
            this.setupCoreEventListeners();
            
            // Register *all* socket & connection handlers BEFORE connecting
            this.setupSocketHandlers();
            
            // Connect socket *after* handlers are registered
            await socketManager.initialize();
            
            // Set initial status
            domManager.updateStatus('Connecting to PIPS server...', 'info');
            
            this.isInitialized = true;
            Logger.log('App', 'PIPS application initialized successfully');
            
        } catch (error) {
            Logger.error('App', 'Error during initialization:', error);
            domManager.updateStatus('Failed to initialize application', 'error');
        }
    }

    async performFirstRunSeeding() {
        try {
            // Check if this is the first run
            if (!localStorage.getItem('pips_first_run_completed')) {
                Logger.debug('App', 'First run detected, seeding default sessions...');
                
                try {
                    const result = await storageManager.importSessionsFromUrl('/static/default_sessions/builtin_sessions.json');
                    Logger.log('App', `Seeded ${result.imported} default sessions successfully`);
                    
                    // Track which sessions are defaults by storing their IDs
                    if (result.imported > 0) {
                        const sessions = storageManager.loadSessions();
                        const defaultSessionIds = Object.keys(sessions);
                        storageManager.saveDefaultSessionIds(defaultSessionIds);
                        Logger.debug('App', `Tracked ${defaultSessionIds.length} default session IDs`);
                    }
                    
                    // Mark first run as completed
                    localStorage.setItem('pips_first_run_completed', 'yes');
                    localStorage.setItem('pips_default_sessions_loaded', new Date().toISOString());
                    
                } catch (error) {
                    Logger.warn('App', 'Could not load default sessions (this is normal in development):', error.message);
                    // Still mark as completed to avoid repeated attempts
                    localStorage.setItem('pips_first_run_completed', 'yes');
                }
            } else {
                Logger.debug('App', 'Not first run, skipping default session seeding');
            }
        } catch (error) {
            Logger.error('App', 'Error during first-run seeding:', error);
        }
    }

    setupCoreEventListeners() {
        // Core problem solving functionality
        domManager.getElement('solveBtn')?.addEventListener('click', () => this.solveProblem());
        domManager.getElement('interruptBtn')?.addEventListener('click', () => this.interruptSolving());
        domManager.getElement('downloadBtn')?.addEventListener('click', () => messageManager.downloadChat());

        Logger.debug('App', 'Core event listeners set up');
        
        // Set up emergency cleanup handler for page unload
        window.addEventListener('beforeunload', () => {
            Logger.debug('App', 'Page unloading - performing emergency cleanup');
            sessionManager.emergencyCleanupAndSave();
        });
        

    }

    setupSocketHandlers() {
        console.log('[DEBUG] Setting up socket handlers...');
        
        // Register all socket event handlers (these are real Socket.IO events)
        const eventHandlers = socketEventHandlers.getEventHandlers();
        console.log('[DEBUG] Event handlers to register:', Object.keys(eventHandlers));
        socketManager.registerEventHandlers(eventHandlers);
        
        // Register connection handlers (these are internal socketManager events)
        const connectionHandlers = socketEventHandlers.getConnectionHandlers();
        console.log('[DEBUG] Connection handlers to register:', Object.keys(connectionHandlers));
        Object.entries(connectionHandlers).forEach(([event, handler]) => {
            socketManager.on(event, handler);
        });

        Logger.debug('App', 'Socket event handlers set up successfully');
    }

    // Core functionality methods
    solveProblem() {
        const questionInput = domManager.getElement('questionInput');
        const text = questionInput?.value.trim();
        
        if (!text) {
            domManager.updateStatus('Please enter a problem description', 'warning');
            return;
        }

        // Check if the current session is used and should be read-only
        if (appState.currentSessionData && sessionManager.isSessionUsed(appState.currentSessionData)) {
            domManager.updateStatus('This session has been used. Please start a new session to solve another problem.', 'warning');
            // Automatically start a new session
            sessionManager.startNewSession();
            return;
        }

        // Get image data if available
        const imageData = imageHandler.getImageForSubmission();

        // Handle session creation/management through session manager
        const sessionId = sessionManager.handleSolveProblem(text, imageData);

        // Send current settings to server first to ensure PIPS mode is included
        settingsManager.sendCurrentSettingsToServer();

        // Send problem to server
        socketManager.send('solve_problem', {
            text: text,
            image: imageData,
            session_id: sessionId
        });

        Logger.debug('App', 'Problem submitted for solving');
    }

    interruptSolving() {
        Logger.debug('App', 'Interrupt button clicked');
        socketManager.send('interrupt_solving');
        domManager.updateStatus('Interrupting current task...', 'warning');
    }

    // Global method for message expansion (called from HTML)
    toggleExpandMessage(button) {
        messageManager.toggleExpandMessage(button);
    }

    // Global methods for session management (called from HTML)
    get sessionManager() {
        return sessionManager;
    }

    // Expose modules for debugging and external access
    getModules() {
        return {
            domManager,
            messageManager,
            settingsManager,
            sessionManager,
            imageHandler,
            socketEventHandlers,
            appState,
            socketManager,
            storageManager
        };
    }
}

// Initialize application when DOM is ready
document.addEventListener('DOMContentLoaded', async () => {
    Logger.log('DOM content loaded');
    
    try {
        const app = new PIPSApplication();
        await app.initialize();
        
        // Store app instance globally for debugging and HTML callbacks
        window.pipsApp = app;
        
        // Also expose key functions globally for HTML access
        window.toggleExpandMessage = (button) => app.toggleExpandMessage(button);
        

        
    } catch (error) {
        Logger.error('Failed to initialize PIPS application:', error);
    }
});