'use strict';

function docReady(fn) {
	// see if DOM is already available
	if (document.readyState === "complete" || document.readyState === "interactive") {
		setTimeout(fn, 1); // call on next available tick
	} else {
		document.addEventListener("DOMContentLoaded", fn);
	}
}

docReady(function() {
	/* Get Our Elements */
	let players = document.querySelectorAll('.castos-player');

	let i18n = window.ssp_player_i18n || {};

	players.forEach(function (player) {
		let playerId = player.dataset.player_id,
			playerData = window['ssp_castos_player_' + playerId],
			episodeId = player.dataset.episode,
			playback = player.querySelector('.ssp-playback'),
			audio,
			playBtn = player.querySelector('.play-btn'),
			pauseBtn = player.querySelector('.pause-btn'),
			cover = player.querySelector('.player__artwork'),
			duration = player.querySelector('.ssp-duration'),
			timer = player.querySelector('.ssp-timer'),
			progress = player.querySelector('.ssp-progress'),
			progressBar = player.querySelector('.progress__filled'),
			skipButtons = playback.querySelectorAll('[data-skip]'),
			volumeBtn = player.querySelector('.player-btn__volume'),
			speedBtn = player.querySelector('.player-btn__speed'),
			loader = player.querySelector('.ssp-loader'),
			playlistItems = player.querySelector('.playlist__items'),
			podcastTitle = player.querySelector('.player__podcast-title'),
			episodeTitle = player.querySelector('.player__episode-title'),
			playlistScroll = player.querySelector('.playlist__wrapper'),
			isPlaylistPlayer = !!playlistScroll,
			playlistLoader,
			toggleTimeout;

		/* Helper functions */
		function padNum(num) {
			return ('' + (num + 100)).substring(1);
		}

		function formatTime(totalSeconds) {
			let hours = Math.floor(totalSeconds / 3600);
			totalSeconds %= 3600;
			let minutes = Math.floor(totalSeconds / 60),
				seconds = Math.floor(totalSeconds % 60),
			 	output = 0;
			hours > 0 ? output = padNum(hours) + ' : ' + padNum(minutes) + ' : ' + padNum(seconds) : output = padNum(minutes) + ':' + padNum(seconds);
			return output;
		}

		/* Build out functions */
		function togglePlayback() {
			clearTimeout(toggleTimeout);

			// Prevent double toggling when user presses space button
			toggleTimeout = setTimeout(function(){
				if (audio.paused) {
					playAudio();
					pauseBtn.focus();
				} else {
					pauseAudio();
					playBtn.focus();
				}
			}, 100);
		}

		function playAudio() {
			audio.play();
			syncPlayButton();
		}

		function pauseAudio(){
			audio.pause();
			syncPlayButton();
		}

		function syncPlayButton() {
			if (audio.paused) {
				pauseBtn.classList.add('hide');
				playBtn.classList.remove('hide');
				playBtn.setAttribute('aria-pressed', 'false');
				pauseBtn.setAttribute('aria-pressed', 'true');
			} else {
				pauseBtn.classList.remove('hide');
				playBtn.classList.add('hide');
				playBtn.setAttribute('aria-pressed', 'true');
				pauseBtn.setAttribute('aria-pressed', 'false');
			}
		}

		function updateDuration() {
			duration.innerHTML = formatTime( audio.duration );
			duration.setAttribute( 'datetime', durationToISO( audio.duration ) );
			progress.setAttribute( 'aria-valuemax', Math.floor( audio.duration ) );
		}

		function durationToISO( seconds ) {
			const hours = Math.floor( seconds / 3600 );
			const minutes = Math.floor( (seconds % 3600) / 60 );
			const remainingSeconds = Math.floor( seconds % 60 );

			let isoString = 'PT';

			if ( hours > 0 ) {
				isoString += hours + 'H';
			}

			if ( minutes > 0 || hours > 0 ) {
				isoString += minutes + 'M';
			}

			isoString += remainingSeconds + 'S';

			return isoString;
		}

		function handleProgress() {
			let percent = audio.currentTime / audio.duration * 100;
			progressBar.style.flexBasis = percent + '%';
			timer.innerHTML = formatTime( audio.currentTime );
			progress.setAttribute( 'aria-valuenow', Math.floor( audio.currentTime ) );
		}

		function scrub(e) {
			audio.currentTime = e.offsetX / progress.offsetWidth * audio.duration;
		}

		function skip() {
			audio.currentTime += parseFloat(this.dataset.skip);
		}

		function toggleMute() {
			if (audio.volume === 1) {
				audio.volume = 0;
				volumeBtn.classList.add('off');
				volumeBtn.setAttribute('aria-pressed', 'true');
			} else {
				audio.volume = 1;
				volumeBtn.classList.remove('off');
				volumeBtn.setAttribute('aria-pressed', 'false');
			}
		}

		function handleSpeedChange() {
			let newSpeed = this.dataset.speed < 2 ? (parseFloat( this.dataset.speed ) + 0.2).toFixed( 1 ) : 0.4;
			setSpeed( newSpeed );
		}

		function setSpeed(speed){
			if( speed < 0.4 || speed > 2 ){
				speed = 1;
			}

			speedBtn.setAttribute('data-speed', speed);
			speedBtn.innerHTML = speed + 'x';
			speedBtn.setAttribute('aria-label', (i18n.playback_speed || 'Playback speed, currently %sx').replace('%s', speed));
			audio.playbackRate = speed;
		}

		function handleWaiting() {
			loader.classList.remove('hide');
		}

		function handleCanPlay() {
			loader.classList.add('hide');
		}

		function initAudio(){

			handleCanPlay();
			audio = player.querySelector('.clip-' + episodeId );
			audio.addEventListener('play', syncPlayButton);
			audio.addEventListener('pause', syncPlayButton);
			audio.addEventListener('playing', syncPlayButton);
			audio.addEventListener('playing', updateDuration);
			audio.addEventListener('timeupdate', handleProgress);

			audio.onended = function () {
				hideElement(pauseBtn);
				showElement(playBtn);
				let currentActiveItem = player.querySelector('.playlist__item.active');

				if(!currentActiveItem){
					return;
				}

				currentActiveItem.classList.remove('active');
				currentActiveItem.removeAttribute('aria-selected');

				let	nextItem = currentActiveItem.nextElementSibling;
				if (nextItem) {
					let event = document.createEvent('HTMLEvents');
					event.initEvent('click', true, false);
					nextItem.dispatchEvent(event);
				}
			};

			audio.addEventListener('waiting', handleWaiting);
			audio.addEventListener('canplay', handleCanPlay);
		}

		function hideElement(element) {
			element.classList.add('hide');
		}

		function showElement(element) {
			element.classList.remove('hide');
		}

		/* Hook up the event listeners */
		playBtn.addEventListener('click', togglePlayback);
		pauseBtn.addEventListener('click', togglePlayback);
		cover.addEventListener('click', togglePlayback);
		speedBtn.addEventListener('click', handleSpeedChange);
		skipButtons.forEach(function (button) {
			return button.addEventListener('click', skip);
		});
		volumeBtn.addEventListener('click', toggleMute);


		let mousedown = false;
		progress.addEventListener('click', scrub);
		progress.addEventListener('mousemove', function (e) {
			return mousedown && scrub(e);
		});
		progress.addEventListener('mousedown', function () {
			return mousedown = true;
		});
		progress.addEventListener('mouseup', function () {
			return mousedown = false;
		});

		//
		// PANELS
		//
		/* Get Our Elements */
		let subscribeBtn = player.querySelector('.subscribe-btn'),
			subscribePanel = player.querySelector('.player-panels .subscribe'),
			subscribePanelClose = player.querySelector('.player-panels .subscribe .close-btn'),
			shareBtn = player.querySelector('.share-btn'),
			sharePanel = player.querySelector('.player-panels .share'),
			sharePanelClose = player.querySelector('.player-panels .share .close-btn'),
			linkCopyElm = player.querySelector('.input-link'),
			linkCopyBtn = player.querySelector('.copy-link'),
			embedCopyElm = player.querySelector('.input-embed'),
			embedCopyBtn = player.querySelector('.copy-embed'),
			rssCopyElm = player.querySelector('.input-rss'),
			rssCopyBtn = player.querySelector('.copy-rss');

		/* Build out functions */
		function togglePanel(panel, triggerBtn) {
			if(panel.classList.contains('open')){
				panel.classList.remove('open');
				if (triggerBtn) {
					triggerBtn.setAttribute('aria-expanded', 'false');
					triggerBtn.focus();
				}
				return;
			}
			panel.classList.add('open');
			if (triggerBtn) {
				triggerBtn.setAttribute('aria-expanded', 'true');
			}
			panel.focus();
		}

		function copyLink(elm) {
			elm.select();
			if (document.execCommand('Copy')) {
				announceToScreenReader(i18n.copied || 'Copied');
			}
		}

		function announceToScreenReader(message) {
			let announcer = player.querySelector('.ssp-sr-announce');
			if (!announcer) {
				announcer = document.createElement('div');
				announcer.className = 'ssp-sr-announce';
				announcer.setAttribute('aria-live', 'polite');
				announcer.setAttribute('role', 'status');
				announcer.style.cssText = 'position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;';
				player.appendChild(announcer);
			}
			announcer.textContent = '';
			setTimeout(function() {
				announcer.textContent = message;
			}, 100);
		}

		function handlePlaylistItemKeydown(e) {
			if (e.key === 'Enter' || e.key === ' ') {
				e.preventDefault();
				handleChangePlaylistItem.call(this);
			}
		}

 		function handleChangePlaylistItem() {
			if( this.dataset.episode === episodeId ){
				return;
			}

			playlistItems.querySelectorAll('.playlist__item').forEach(function (item) {
				item.classList.remove('active');
				item.removeAttribute('aria-selected');
			});

			this.classList.add('active');
			this.setAttribute('aria-selected', 'true');

			let playlistEpisodeTitle = this.querySelector('.playlist__episode-title'),
				episodeCover = this.querySelector('.playlist__item__cover img');

			podcastTitle.textContent = playlistEpisodeTitle.dataset.podcast;
			episodeTitle.textContent = playlistEpisodeTitle.textContent;
			cover.querySelector('img').src = episodeCover.src;

			pauseAudio();

			episodeId = this.dataset.episode;

			initAudio();

			setTimeout(function () {
				togglePlayback();
			}, 500);
		}

		function handleInfiniteScroll() {
			let startLoading = function () {
					playlistLoader.style.display = 'block';
					playlistScroll.dataset.processing = '1';
				},
				stopLoading = function () {
					playlistLoader.style.display = 'none';
					playlistScroll.dataset.processing = '';
				},
				createListItem = function (item) {
					// Helper function to escape HTML content
					function escapeHtml(text) {
						if (text == null) return '';
						const div = document.createElement('div');
						div.textContent = String(text);
						return div.innerHTML;
					}

					// Helper function to validate and escape URLs
					function escapeUrl(url) {
						if (!url || typeof url !== 'string') return '';
						// Check for javascript: protocol
						if (url.toLowerCase().startsWith('javascript:')) return '';
						return escapeHtml(url);
					}

					let div = document.createElement('div');
					div.innerHTML =
						'<li class="playlist__item" data-episode="' + escapeHtml(item.episode_id) + '" tabindex="0" role="option">' +
						'<div class="playlist__item__cover">' +
						'<img src="' + escapeUrl(item.album_art && item.album_art.src ? item.album_art.src : '') + '" title="' + escapeHtml(item.title) + '" alt="' + escapeHtml(item.title) + '" />' +
						'</div>' +
						'<div class="playlist__item__details">' +
						'<h2 class="playlist__episode-title" data-podcast="' + escapeHtml(item.podcast_title) + '">' + escapeHtml(item.title) + '</h2>' +
						'<p>' + escapeHtml(item.date) + ' • ' + escapeHtml(item.duration) + '</p>' +
						'<p class="playlist__episode-description">' + escapeHtml(item.excerpt) + '</p>' +
						'</div>' +
						'<audio preload="none" class="clip clip-' + escapeHtml(item.episode_id) + '">' +
						'<source src="' + escapeUrl(item.audio_file) + '">' +
						'</audio>' +
						'</li>';

					return div.firstChild;
				},
				sendRequest = function () {
					startLoading();
					let request = new XMLHttpRequest();
					let url = new URL(playerData.ajax_url);
					let data = {
						action: 'get_playlist_items',
						atts: JSON.stringify(playerData.atts),
						page: ++playlistScroll.dataset.page,
						player_id: playerId,
						nonce: playerData.nonce
					};
					Object.keys(data).forEach(function (key) {
						url.searchParams.set(key, data[key]);
					});

					request.open('GET', url.toString(), true);
					request.onload = function () {
						if (200 === this.status) {
							let response = JSON.parse(this.response);
							if (response.data.length > 0) {
								response.data.forEach(function (e) {
										let item = createListItem(e);
										playlistItems.appendChild(item);
										item.addEventListener('click', handleChangePlaylistItem);
										item.addEventListener('keydown', handlePlaylistItemKeydown);
									}
								);
							} else {
								playlistScroll.removeEventListener('scroll', handleInfiniteScroll);
							}

						}
						stopLoading();
					};
					request.onerror = function () {
						stopLoading();
					};
					request.send();
				}


			if (!playlistScroll.dataset.processing &&
				playlistLoader.scrollHeight - playlistLoader.scrollTop === playlistLoader.clientHeight
			) {
				sendRequest();
			}
		}

		function initEventListeners(){
			/* Hook up the event listeners */
			if (subscribeBtn) {
				subscribeBtn.addEventListener('click', function () {
					return togglePanel(subscribePanel, subscribeBtn);
				});
			}

			if (subscribePanelClose) {
				subscribePanelClose.addEventListener('click', function () {
					return togglePanel(subscribePanel, subscribeBtn);
				});
			}

			if (shareBtn) {
				shareBtn.addEventListener('click', function () {
					return togglePanel(sharePanel, shareBtn);
				});
			}

			if (sharePanelClose) {
				sharePanelClose.addEventListener('click', function () {
					return togglePanel(sharePanel, shareBtn);
				});
			}

			if (linkCopyBtn) {
				linkCopyBtn.addEventListener('click', function () {
					return copyLink(linkCopyElm);
				});
			}

			if (embedCopyBtn) {
				embedCopyBtn.addEventListener('click', function () {
					return copyLink(embedCopyElm);
				});
			}

			if (rssCopyBtn) {
				rssCopyBtn.addEventListener('click', function () {
					return copyLink(rssCopyElm);
				});
			}
		}

		function initPlaylistEventListeners() {
			let items = playlistItems.querySelectorAll('.playlist__item');

			if (items) {
				items.forEach(function (item) {
					item.addEventListener('click', handleChangePlaylistItem);
					item.addEventListener('keydown', handlePlaylistItemKeydown);
				});
			}

			if (playlistScroll) {
				playlistScroll.addEventListener('scroll', handleInfiniteScroll);
			}
		}

		function initKeyboardListeners() {
			document.addEventListener( 'keydown', ( e ) => {
				// If the Space button was pressed and any of the player element is focused, toggle playback.
				if ( ! document.activeElement.closest( '.castos-player' ) ) {
					return;
				}

				if ( 'ArrowRight' === e.code ) {
					e.preventDefault();
					audio.currentTime += 30;
				} else if ( 'ArrowLeft' === e.code ) {
					e.preventDefault();
					audio.currentTime -= 10;
				} else if ( 'Space' === e.code ) {
					e.preventDefault();
					togglePlayback();
				} else if ( 'm' === e.key || 'M' === e.key ) {
					volumeBtn.dispatchEvent( new Event( 'click' ) );
					volumeBtn.focus();
				} else if ( e.shiftKey && e.code === 'Period' ) { // Increase speed (up to 2x)
					let speed = speedBtn.dataset.speed < 2 ? (parseFloat( speedBtn.dataset.speed ) + 0.2) : 2.0;
					setSpeed( speed.toFixed( 1 ) );
				} else if ( e.shiftKey && e.code === 'Comma' ) { // Decrease speed (down to 0.4x)
					let speed = speedBtn.dataset.speed > 0.4 ? (parseFloat( speedBtn.dataset.speed ) - 0.2) : 0.4;
					setSpeed( speed.toFixed( 1 ) );
				} else if ( e.shiftKey && e.code === 'Digit0' ) { // Reset speed to 1x
					setSpeed( 1 );
				} else if ( 'Escape' === e.key ) {
					e.preventDefault();
					if ( subscribePanel && subscribePanel.classList.contains( 'open' ) ) {
						togglePanel( subscribePanel, subscribeBtn );
						subscribeBtn.focus();
					}
					if ( sharePanel && sharePanel.classList.contains( 'open' ) ) {
						togglePanel( sharePanel, shareBtn );
						shareBtn.focus();
					}
				}
			} );
		}

		function init() {
			initEventListeners();
			initKeyboardListeners();
			if (isPlaylistPlayer) {
				playlistLoader = playlistScroll.querySelector('.loader');
				initPlaylistEventListeners();
			}
			initAudio();
		}

		init();
	});
});
