import type { EpisodeActionInterface, EpisodeInterface } from '../utils/types.ts'
import { getCookie, setCookie } from '../utils/cookies.ts'
import axios from '@nextcloud/axios'
import { defineStore } from 'pinia'
import { formatEpisodeTimestamp } from '../utils/time.ts'
import { generateUrl } from '@nextcloud/router'
import { showError } from '../utils/toast.ts'
import { t } from '@nextcloud/l10n'

const audio = new Audio()

export const usePlayer = defineStore('player', {
	state: () => ({
		currentTime: null as number | null,
		duration: null as number | null,
		episode: null as EpisodeInterface | null,
		loaded: false,
		paused: true,
		playCount: 0,
		podcastUrl: null as string | null,
		volume: 1,
		rate: 1,
		started: 0,
	}),
	actions: {
		init() {
			audio.playbackRate = parseFloat(getCookie('repod.rate') || '1')
			audio.volume = parseFloat(getCookie('repod.volume') || '1')

			audio.ondurationchange = () => (this.duration = audio.duration)
			audio.onended = () => this.stop()
			audio.onloadeddata = () => (this.loaded = true)
			audio.onpause = () => this.pause()
			audio.onplay = () => this.play()
			audio.onratechange = () => (this.rate = audio.playbackRate)
			audio.onseeked = () => (this.currentTime = audio.currentTime)
			audio.ontimeupdate = () => (this.currentTime = audio.currentTime)
			audio.onvolumechange = () => (this.volume = audio.volume)

			setInterval(this.act, 40000)
			setInterval(this.conflict, 1000)
		},
		act() {
			if (this.paused === false) {
				this.time()
			}
		},
		conflict() {
			this.playCount = 0
		},
		metadatas(episode: EpisodeInterface) {
			// https://developer.mozilla.org/en-US/docs/Web/API/Media_Session_API
			navigator.mediaSession.metadata = new MediaMetadata({
				title: episode.name,
				artist: episode.author,
				album: episode.title,
				artwork: episode.image ? [{ src: episode.image }] : [],
			})

			navigator.mediaSession.setActionHandler('play', this.play)
			navigator.mediaSession.setActionHandler('pause', this.pause)
			navigator.mediaSession.setActionHandler('stop', this.stop)
			navigator.mediaSession.setActionHandler(
				'seekbackward',
				(details: MediaSessionActionDetails) =>
					this.seek(audio.currentTime - (details.seekOffset || 10)),
			)
			navigator.mediaSession.setActionHandler(
				'seekforward',
				(details: MediaSessionActionDetails) =>
					this.seek(audio.currentTime + (details.seekOffset || 30)),
			)
			navigator.mediaSession.setActionHandler(
				'seekto',
				(details: MediaSessionActionDetails) =>
					!details.fastSeek && this.seek(details.seekTime || 0),
			)
		},
		async load(episode: EpisodeInterface | null, podcastUrl?: string) {
			this.episode = episode
			this.podcastUrl = podcastUrl || null

			if (this.episode?.url) {
				audio.src = this.episode.url
				audio.load()

				try {
					const action = await axios.get<EpisodeActionInterface>(
						generateUrl('/apps/repod/episodes/action?url={url}', {
							url: this.episode.url,
						}),
					)

					this.episode.action = action.data
				} catch {}

				if (
					this.episode.action &&
					this.episode.action.position < this.episode.action.total
				) {
					audio.currentTime = this.episode.action.position
					this.started = audio.currentTime
				}

				audio.play()
				this.metadatas(this.episode)
			} else {
				this.loaded = false
				this.podcastUrl = null
				navigator.mediaSession.metadata = null
				audio.src = ''
			}
		},
		pause() {
			audio.pause()
			this.paused = true
			this.time()
		},
		play() {
			this.playCount++

			if (this.playCount > 10) {
				showError(t('repod', 'A browser extension conflict with RePod'))
			} else {
				audio.play()
				this.paused = false
				this.started = audio.currentTime
			}
		},
		seek(currentTime: number) {
			audio.currentTime = currentTime
			this.time()
		},
		stop() {
			this.pause()
			this.episode = null
		},
		time() {
			if (!this.podcastUrl || !this.episode?.url) {
				return
			}

			this.episode.action = {
				podcast: this.podcastUrl,
				episode: this.episode.url,
				guid: this.episode.guid,
				action: 'play',
				timestamp: formatEpisodeTimestamp(new Date()),
				started: Math.round(this.started),
				position: Math.round(audio.currentTime),
				total: Math.round(audio.duration),
			}

			axios.post(generateUrl('/apps/gpoddersync/episode_action/create'), [
				this.episode.action,
			])
		},
		setVolume(volume: number) {
			audio.volume = volume
			setCookie('repod.volume', volume.toString(), 365)
		},
		setRate(rate: number) {
			audio.playbackRate = rate
			setCookie('repod.rate', rate.toString(), 365)
		},
	},
})
