import {writable} from 'svelte/store';
import {tweened} from 'svelte/motion';
import {cubicOut} from 'svelte/easing';

export let songPlayerStore = null;
export let currentTimeStore = null;

const DEFAULT_STATE = {
	currentHash: null,
	playing: false,
	duration: 0,
	currentTime: 0,
	volume: 0.3,
};

export default () => {
	if (songPlayerStore) return songPlayerStore;

	let currentState = {...DEFAULT_STATE};
	let audio = null;
	currentTimeStore = tweened(0, {duration: 10, easing: cubicOut});

	const {subscribe, set, update} = writable(currentState);

	function cleanup() {
		if (audio) {
			audio.removeEventListener('timeupdate', handleTimeUpdate);
			audio.removeEventListener('loadedmetadata', handleMetadata);
			audio.removeEventListener('ended', handleEnded);
			audio.removeEventListener('pause', handleEnded);
			audio.pause();
			audio.currentTime = 0;

			audio = null;
		}
	}

	function handleTimeUpdate() {
		currentTimeStore.set(audio.currentTime);
	}

	function handleMetadata() {
		update(state => ({...state, duration: audio.duration}));
	}

	function handleEnded() {
		update(state => ({...state, playing: false, currentHash: null}));
	}

	function togglePlay(hash, local = false) {
		update(state => {
			const isPlaying = hash == state.currentHash ? !state.playing : true;

			let url = local ? `https://cdn.songs.beatleader.com/${hash}.mp3` : `https://eu.cdn.beatsaver.com/${hash.toLowerCase()}.mp3`;

			if (hash !== state.currentHash) {
				cleanup();
				currentTimeStore.set(0);
				audio = new Audio(url);
				audio.volume = state.volume;
				audio.addEventListener('timeupdate', handleTimeUpdate);
				audio.addEventListener('loadedmetadata', handleMetadata);
				audio.addEventListener('ended', handleEnded);
				audio.addEventListener('pause', handleEnded);
			} else if (!audio) {
				audio = new Audio(url);
				audio.volume = state.volume;
				audio.addEventListener('timeupdate', handleTimeUpdate);
				audio.addEventListener('loadedmetadata', handleMetadata);
				audio.addEventListener('ended', handleEnded);
				audio.addEventListener('pause', handleEnded);
			}

			if (isPlaying) {
				audio?.play();
			} else {
				audio?.pause();
			}

			return {
				...state,
				currentHash: hash,
				playing: isPlaying,
			};
		});
	}

	function setVolume(volume) {
		update(state => {
			if (audio) {
				audio.volume = volume;
			}
			return {...state, volume};
		});
	}

	const reset = () => {
		cleanup();
		set(DEFAULT_STATE);
	};

	songPlayerStore = {
		subscribe,
		togglePlay,
		setVolume,
		reset,
	};

	return songPlayerStore;
};
