import watchReporter from '../reporters/watch.js';
import { debugLog } from './debug.js';
import { updateImportMap } from './dependency-graph.js';
import { isFile } from './fs.js';
import { join, toPosix } from './path.js';
export const getWatchHandler = async ({ analyzedFiles, analyzeSourceFile, chief, collector, collectUnusedExports, cwd, factory, graph, isDebug, isIgnored, report, streamer, unreferencedFiles, }) => {
    const reportIssues = async (startTime) => {
        const { issues } = collector.getIssues();
        watchReporter({ report, issues, streamer, startTime, size: analyzedFiles.size, isDebug });
    };
    const listener = async (eventType, filename) => {
        debugLog('*', `(raw) ${eventType} ${filename}`);
        if (typeof filename === 'string') {
            const startTime = performance.now();
            const filePath = join(cwd, toPosix(filename));
            if (isIgnored(filePath)) {
                debugLog('*', `ignoring ${eventType} ${filename}`);
                return;
            }
            const workspace = chief.findWorkspaceByFilePath(filePath);
            if (workspace) {
                const principal = factory.getPrincipalByPackageName(workspace.pkgName);
                if (principal) {
                    const event = eventType === 'rename' ? (isFile(filePath) ? 'added' : 'deleted') : 'modified';
                    principal.invalidateFile(filePath);
                    unreferencedFiles.clear();
                    const cachedUnusedFiles = collector.purge();
                    switch (event) {
                        case 'added':
                            principal.addProjectPath(filePath);
                            principal.deletedFiles.delete(filePath);
                            cachedUnusedFiles.add(filePath);
                            debugLog(workspace.name, `Watcher: + ${filename}`);
                            break;
                        case 'deleted':
                            analyzedFiles.delete(filePath);
                            principal.removeProjectPath(filePath);
                            cachedUnusedFiles.delete(filePath);
                            debugLog(workspace.name, `Watcher: - ${filename}`);
                            break;
                        case 'modified':
                            debugLog(workspace.name, `Watcher: ± ${filename}`);
                            break;
                    }
                    const filePaths = principal.getUsedResolvedFiles();
                    if (event === 'added' || event === 'deleted') {
                        graph.clear();
                        for (const filePath of filePaths)
                            analyzeSourceFile(filePath, principal);
                    }
                    else {
                        for (const [filePath, file] of graph) {
                            if (filePaths.includes(filePath)) {
                                file.imported = undefined;
                            }
                            else {
                                graph.delete(filePath);
                                analyzedFiles.delete(filePath);
                                if (filePath.startsWith(cwd))
                                    cachedUnusedFiles.add(filePath);
                            }
                        }
                        for (const filePath of filePaths)
                            if (!graph.has(filePath))
                                analyzeSourceFile(filePath, principal);
                        if (!cachedUnusedFiles.has(filePath))
                            analyzeSourceFile(filePath, principal);
                        for (const filePath of filePaths) {
                            const file = graph.get(filePath);
                            if (file?.internalImportCache)
                                updateImportMap(file, file.internalImportCache, graph);
                        }
                    }
                    await collectUnusedExports();
                    const unusedFiles = [...cachedUnusedFiles].filter(filePath => !analyzedFiles.has(filePath));
                    collector.addFilesIssues(unusedFiles);
                    collector.addFileCounts({ processed: analyzedFiles.size, unused: unusedFiles.length });
                    await reportIssues(startTime);
                }
            }
        }
    };
    await collectUnusedExports();
    await reportIssues();
    return listener;
};
