import { CodeSnippetsCodebaseIndex } from "./CodeSnippetsIndex.js";
import { FullTextSearchCodebaseIndex } from "./FullTextSearch.js";
import { LanceDbIndex } from "./LanceDbIndex.js";
import { ChunkCodebaseIndex } from "./chunk/ChunkCodebaseIndex.js";
import { getComputeDeleteAddRemove } from "./refreshIndex.js";
export class PauseToken {
    _paused;
    constructor(_paused) {
        this._paused = _paused;
    }
    set paused(value) {
        this._paused = value;
    }
    get paused() {
        return this._paused;
    }
}
export class CodebaseIndexer {
    configHandler;
    ide;
    pauseToken;
    continueServerClient;
    constructor(configHandler, ide, pauseToken, continueServerClient) {
        this.configHandler = configHandler;
        this.ide = ide;
        this.pauseToken = pauseToken;
        this.continueServerClient = continueServerClient;
    }
    async getIndexesToBuild() {
        const config = await this.configHandler.loadConfig();
        const indexes = [
            new ChunkCodebaseIndex(this.ide.readFile.bind(this.ide), this.continueServerClient), // Chunking must come first
            new LanceDbIndex(config.embeddingsProvider, this.ide.readFile.bind(this.ide), this.continueServerClient),
            new FullTextSearchCodebaseIndex(),
            new CodeSnippetsCodebaseIndex(this.ide),
        ];
        return indexes;
    }
    async *refresh(workspaceDirs, abortSignal) {
        if (workspaceDirs.length === 0) {
            yield {
                progress: 0,
                desc: "Nothing to index",
                status: "disabled",
            };
            return;
        }
        const config = await this.configHandler.loadConfig();
        if (config.disableIndexing) {
            yield {
                progress: 0,
                desc: "Indexing is disabled in the config.json",
                status: "disabled",
            };
            return;
        }
        else {
            yield {
                progress: 0,
                desc: "Starting indexing",
                status: "starting",
            };
        }
        const indexesToBuild = await this.getIndexesToBuild();
        let completedDirs = 0;
        // Wait until Git Extension has loaded to report progress
        // so we don't appear stuck at 0% while waiting
        await this.ide.getRepoName(workspaceDirs[0]);
        yield {
            progress: 0,
            desc: "Starting indexing...",
            status: "starting",
        };
        for (const directory of workspaceDirs) {
            // const scheme = vscode.workspace.workspaceFolders?.[0].uri.scheme;
            // const files = await this.listWorkspaceContents(directory);
            const files = await this.ide.listWorkspaceContents(directory);
            const stats = await this.ide.getLastModified(files);
            const branch = await this.ide.getBranch(directory);
            const repoName = await this.ide.getRepoName(directory);
            let completedIndexes = 0;
            for (const codebaseIndex of indexesToBuild) {
                // TODO: IndexTag type should use repoName rather than directory
                const tag = {
                    directory,
                    branch,
                    artifactId: codebaseIndex.artifactId,
                };
                const [results, markComplete] = await getComputeDeleteAddRemove(tag, { ...stats }, (filepath) => this.ide.readFile(filepath), repoName);
                try {
                    for await (let { progress, desc } of codebaseIndex.update(tag, results, markComplete, repoName)) {
                        // Handle pausing in this loop because it's the only one really taking time
                        if (abortSignal.aborted) {
                            yield {
                                progress: 1,
                                desc: "Indexing cancelled",
                                status: "disabled",
                            };
                            return;
                        }
                        if (this.pauseToken.paused) {
                            yield {
                                progress: completedDirs / workspaceDirs.length,
                                desc: "Paused",
                                status: "paused",
                            };
                            while (this.pauseToken.paused) {
                                await new Promise((resolve) => setTimeout(resolve, 100));
                            }
                        }
                        yield {
                            progress: (completedDirs +
                                (completedIndexes + progress) / indexesToBuild.length) /
                                workspaceDirs.length,
                            desc,
                            status: "indexing",
                        };
                    }
                    completedIndexes++;
                    yield {
                        progress: (completedDirs + completedIndexes / indexesToBuild.length) /
                            workspaceDirs.length,
                        desc: "Completed indexing " + codebaseIndex.artifactId,
                        status: "indexing",
                    };
                }
                catch (e) {
                    console.warn(`Error updating the ${codebaseIndex.artifactId} index: ${e}`);
                }
            }
            completedDirs++;
            yield {
                progress: completedDirs / workspaceDirs.length,
                desc: "Indexing Complete",
                status: "done",
            };
        }
    }
}
