"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.indexGff3 = indexGff3;
const readline_1 = __importDefault(require("readline"));
const zlib_1 = require("zlib");
const cli_progress_1 = require("cli-progress");
const util_1 = require("../util");
async function* indexGff3({ config, attributesToIndex, inLocation, outLocation, typesToExclude, quiet, }) {
    const { trackId } = config;
    // progress bar code was aided by blog post at
    // https://webomnizz.com/download-a-file-with-progressbar-using-node-js/
    const progressBar = new cli_progress_1.SingleBar({
        format: `{bar} ${trackId} {percentage}% | ETA: {eta}s`,
        etaBuffer: 2000,
    }, cli_progress_1.Presets.shades_classic);
    let receivedBytes = 0;
    const { totalBytes, stream } = await (0, util_1.getLocalOrRemoteStream)(inLocation, outLocation);
    if (!quiet) {
        progressBar.start(totalBytes, 0);
    }
    // @ts-expect-error
    stream.on('data', chunk => {
        receivedBytes += chunk.length;
        progressBar.update(receivedBytes);
    });
    const rl = readline_1.default.createInterface({
        // @ts-expect-error
        input: /.b?gz$/.exec(inLocation) ? stream.pipe((0, zlib_1.createGunzip)()) : stream,
    });
    for await (const line of rl) {
        if (!line.trim()) {
            continue;
        }
        else if (line.startsWith('#')) {
            continue;
        }
        else if (line.startsWith('>')) {
            break;
        }
        const [seq_id, , type, start, end, , , , col9] = line.split('\t');
        const locStr = `${seq_id}:${start}..${end}`;
        if (!typesToExclude.includes(type)) {
            // turns gff3 attrs into a map, and converts the arrays into space
            // separated strings
            const col9attrs = Object.fromEntries(col9
                .split(';')
                .map(f => f.trim())
                .filter(f => !!f)
                .map(f => f.split('='))
                .map(([key, val]) => [
                key.trim(),
                val
                    ? (0, util_1.decodeURIComponentNoThrow)(val).trim().split(',').join(' ')
                    : undefined,
            ]));
            const attrs = attributesToIndex
                .map(attr => col9attrs[attr])
                .filter((f) => !!f);
            if (attrs.length) {
                const record = JSON.stringify([
                    encodeURIComponent(locStr),
                    encodeURIComponent(trackId),
                    ...attrs.map(a => encodeURIComponent(a)),
                ]).replaceAll(',', '|');
                yield `${record} ${[...new Set(attrs)].join(' ')}\n`;
            }
        }
    }
    progressBar.stop();
}
