export default (modules, q, qa) => {
	let self

	let lastLoading = modules.globals.dlStatus > 0 && modules.globals.dlStatus < 3
	let videoSource = modules.globals.videoPath

	// Watch for incomplete downloaded video
	let downloading = false
	if (modules.globals.dlStatus > 0 && modules.globals.dlStatus < 3) {
		downloading = true
		modules.cacheInfo.pingCache(`${modules.globals.data.videoId}-${videoSource.split("&quality=")[1] || "360p"}`, () => {
			downloading = false
			self.reloadSource()
		}, 1000 * 2)
	}
	// If video is still downloading and skips to the end, try to reload source and rewind
	if (downloading) {
		let lastSafeTime
		function updateLastSafeTime() {
			lastSafeTime = modules.globals.video.currentTime
			if (downloading)
				setTimeout(updateLastSafeTime, 1000 * 1.5)
		}
		updateLastSafeTime()

		modules.globals.video.addEventListener("ended", () => {
			modules.controls.hideControls(false)
			if (downloading) {
				modules.globals.video.currentTime = lastSafeTime
				self.reloadSource()
			}
		})
	}

	self = {
		downloadMp4Btn: document.getElementById("download-btn"),
		downloadOggBtn: document.getElementById("download-ogg-btn"),

		safeQualities: {},

		lastToast: null,

		setQualityButtons: enable => {
			for (const btn of qa(".videoControls .settingsPopout .settingsPage[data-name='quality'] .setting.quality"))
				btn.toggleAttribute("disabled", !enable)
			self.downloadMp4Btn.toggleAttribute("disabled", !enable)
			self.downloadOggBtn.toggleAttribute("disabled", !enable)
		},

		startLoadingQuality: quality => {
			self.setQualityButtons(false)
			newToastWhenReady("yellow", "loading", `Loading ${quality}...`, true)
				.then(toast => {
					self.lastToast = toast;
					if (!lastLoading) {
						toast.container.remove()
						self.lastToast = null
					}
				})
		},
		qualitySelected: quality => {
			quality = quality || "360p"

			modules.controls.setQualityButtonActive(quality)

			if (lastLoading)
				return
			lastLoading = true

			self.startLoadingQuality(quality)

			let rateLimitToast
			let doFetch
			doFetch = () => {
				fetch(`/watch?v=${modules.globals.data.videoId}&quality=${quality}${modules.player.startingTime ? `&t=${modules.player.startingTime}` : ""}`)
					.then(r => {
						if (r.status == 200)
							self.waitForNewVideoLoad(`${modules.globals.data.videoId}`, quality)
						else if (r.status == 429) {
							newToastWhenReady("red", "loading", `Too many requests. Trying again in ${r.headers.get("retry-after")} seconds...`, true)
								.then(toast => rateLimitToast = toast)
							setTimeout(() => {
								if (rateLimitToast)
									setToastRemove(rateLimitToast.container)
								doFetch()
							}, 1000 * Number(r.headers.get("retry-after")))
						}
						else {
							newToastWhenReady("red", "x", `Failed to switch quality (${r.status}: ${r.statusText})`)
							setTimeout(doFetch, 1000 * 10)
						}
					})
			}
			doFetch()
		},
		waitForNewVideoLoad: (videoName, quality) => {
			modules.cacheInfo.pingCache(`${videoName}-${quality}`, () => self.videoDownloaded(`/getVideo?v=${videoName}&q=${quality}`, quality), 1000 * 3)
		},
		setVideoSource: newSource => {
			videoSource = newSource
			self.reloadSource()
		},
		videoDownloaded: (videoName, quality) => {
			self.setVideoSource(videoName)
			self.safeQualities[quality] = true

			modules.controls.onVideoDownloaded(quality)

			// "Done!" toast
			if (self.lastToast)
				newToastWhenReady("green", "check", "Done!")
			lastLoading = false

			self.setQualityButtons(true)
			self.downloadMp4Btn.href = `${videoName}&dl=1`

			// Remove last "loading" toast if applicable
			if (self.lastToast && self.lastToast.container)
				setToastRemove(self.lastToast.container)
			self.lastToast = null
		},
		reloadSource() {
			let lastTime = modules.globals.video.currentTime
			modules.globals.video.src = videoSource
			modules.globals.video.currentTime = lastTime
			modules.globals.video.load()
			modules.globals.video.pause()
			if (modules.player.lastPlaying)
				modules.globals.video.play()
			modules.globals.video.focus()
		}
	}

	// Autoload HD video
	function preloadHDVideo() {
		const f = modules.globals.targetFormat
		self.downloadMp4Btn.innerHTML = `Download ${f.cloudtube__label.replace(" *", "")} (${f.eirtube__size})`
		lastLoading = true
		self.startLoadingQuality(f.qualityLabel)
		self.waitForNewVideoLoad(modules.globals.data.videoId, f.qualityLabel)
	}

	const preloadRatelimitRegex = /([\d]+p) in (\d\d?) seconds.../
	if (modules.globals.awaitingNewFormat) {
		let preloadRatelimited = false
		for (const toast of document.getElementsByClassName("toast-container")) {
			const innerToast = toast.querySelector(".toast")
			const text = innerToast.childNodes[1].textContent

			// Look for ratelimited preload text
			const match = text.match(preloadRatelimitRegex)
			if (match) {
				preloadRatelimited = true
				const seconds = Number(match[2])

				innerToast.childNodes[1].textContent = text.replace("You may download", "Preloading")
				toast.classList.add("nofade")

				setTimeout(() => {
					if (toast)
						setToastRemove(toast)
					self.qualitySelected(modules.globals.targetFormat.qualityLabel)
				}, (seconds + 0.5) * 1000)
				break
			}
		}

		if (!preloadRatelimited)
			preloadHDVideo()
	}

	self.downloadOggBtn.addEventListener("click", event => {
		newToastWhenReady("yellow", "loading", "Extracting audio...", true)
	})

	// Reload source if error
	modules.globals.video.addEventListener("error", () => setTimeout(self.reloadSource, 1000 * 2))

	return self
}
