import { EventEmitter } from "node:events"
import child_process from "node:child_process"

function getBinaryPath(name) {
	try {
		return child_process
			.execSync(`which ${name}`, { encoding: "utf8" })
			.trim()
	} catch (error) {
		return null
	}
}

export class FFMPEGLib extends EventEmitter {
	constructor() {
		super()
		this.ffmpegBin = getBinaryPath("ffmpeg")
		this.ffprobeBin = getBinaryPath("ffprobe")
	}

	handleProgress(stdout, endTime, onProgress = () => {}) {
		let currentTime = 0

		stdout.on("data", (data) => {
			for (const line of data.toString().split("\n")) {
				if (line.startsWith("out_time_ms=")) {
					currentTime = parseInt(line.split("=")[1]) / 1000000
				} else if (line.startsWith("progress=")) {
					const status = line.split("=")[1]

					if (status === "end") {
						onProgress(100)
					} else if (endTime > 0 && currentTime > 0) {
						onProgress(
							Math.min(
								100,
								Math.round((currentTime / endTime) * 100),
							),
						)
					}
				}
			}
		})
	}

	ffmpeg(payload) {
		return this.exec(this.ffmpegBin, payload)
	}

	ffprobe(payload) {
		return this.exec(this.ffprobeBin, payload)
	}

	exec(bin, { args, onProcess, cwd }) {
		if (Array.isArray(args)) {
			args = args.join(" ")
		}

		return new Promise((resolve, reject) => {
			if (!bin) {
				return reject("No binary provided")
			}

			const process = child_process.exec(
				`${bin} ${args}`,
				{
					cwd: cwd,
				},
				(error, stdout, stderr) => {
					if (error) {
						reject(stderr)
					} else {
						resolve(stdout.toString())
					}
				},
			)

			if (typeof onProcess === "function") {
				onProcess(process)
			}
		})
	}
}

export class Utils {
	static async probe(input) {
		const lib = new FFMPEGLib()

		const result = await lib
			.ffprobe({
				args: [
					"-v",
					"error",
					"-print_format",
					"json",
					"-show_format",
					"-show_streams",
					input,
				],
			})
			.catch((err) => {
				console.log(err)
				return null
			})

		if (!result) {
			return null
		}

		return JSON.parse(result)
	}
}

export default FFMPEGLib
