import { createReadStream } from "fs";

export type SwapPoint = {
	position_start: number;
	duration: number;
	loud: boolean;
	label: string;
};

export default async function (
	file: import("fs").PathLike,
	threshold_at_point: number,
	inertia_samples: number,
	label: string
): Promise<SwapPoint[]> {
	const stream = createReadStream(file);
	let position = 0;
	const results: SwapPoint[] = [];
	let last_swap_position = 0;
	let keep_loud_until = 0;
	let was_loud_last_time = false;
	return new Promise((resolve, reject) => {
		stream.on("readable", () => {
			let chunk: Buffer | null;
			while ((chunk = stream.read()) !== null) {
				for (let i = 0; i < chunk.byteLength; i++) {
					position++;
					const byte = chunk[i];
					const volume = Math.abs(byte - 128);
					if (position >= keep_loud_until) {
						const is_loud: boolean = volume > threshold_at_point;
						if (is_loud != was_loud_last_time) {
							const swap_point = {
								position_start: last_swap_position,
								duration: position - last_swap_position,
								loud: was_loud_last_time,
								label,
							};
							results.push(swap_point);
							last_swap_position = position;
							was_loud_last_time = is_loud;
						}
					}
					if (volume > threshold_at_point) {
						keep_loud_until = position + inertia_samples;
					}
				}
			}
		});
		stream.on("end", () => {
			resolve(results);
		});

		stream.on("error", reject);
	});
}
