import MiniSearch from 'minisearch';
import { Vfs } from "./fs";
export const validFields = ['path', 'basename', 'dirname', 'extension'];
export const defaultFields = ['path', 'basename', 'dirname', 'extension'];
export const defaultFilter = (path) => {
    return !path.endsWith('.crswap');
};
export class SearchIndex {
    index;
    constructor(index) {
        this.index = index;
    }
    search(...params) {
        const results = this.index.search(...params);
        const highlights = this.highlight(results);
        return results.map((result, i) => ({
            ...result,
            highlights: highlights[i]
        }));
    }
    /**
     *
     * @param results
     * @returns ranges of found term matched by each field
     */
    highlight(_results) {
        // TODO: implement
        return [];
    }
    async save(fs, path) {
        try {
            // Extract directory from the file path and create it
            const dir = path.substring(0, path.lastIndexOf('/'));
            if (dir) {
                await fs.mkdir(dir, { recursive: true });
            }
            await fs.writeFile(path, JSON.stringify(this.index));
        }
        catch (error) {
            console.error('Failed to save search index:', error);
        }
        finally {
            return this;
        }
    }
    static from(fs, fields) {
        const index = MiniSearch.loadJSON(fs, { fields, idField: 'path' });
        return new SearchIndex(index);
    }
    static async get(fs, path, fields = defaultFields) {
        const index = await fs.exists(path) ? await fs.readFile(path) : null;
        return index ?
            SearchIndex.from(index, fields) :
            SearchIndex.build(fs, { fields, idField: 'path' }).then(index => index.save(fs, path));
    }
    static async build(fs, { filter = defaultFilter, ...rest }) {
        const index = new MiniSearch({ ...rest });
        for await (const path of Vfs.walk(fs, '/')) {
            if (!filter(path)) {
                continue;
            }
            if (!index.has(path.slice(1))) {
                index.add({ path: path.slice(1) });
            }
        }
        return new SearchIndex(index);
    }
}
